Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2015-06-15 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:54 +0300
commit54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch)
treec3c413656432c0ef87b2841c80e42b55ad17d4e8
parent0713a3ab803e57401f18432148b4139e5fe6e5dd (diff)
15.0515.05
-rw-r--r--C/7z.h20
-rw-r--r--C/7zAlloc.c10
-rw-r--r--C/7zAlloc.h10
-rw-r--r--C/7zArcIn.c358
-rw-r--r--C/7zBuf2.c9
-rw-r--r--C/7zCrc.c69
-rw-r--r--C/7zCrcOpt.c85
-rw-r--r--C/7zDec.c204
-rw-r--r--C/7zVersion.h21
-rw-r--r--C/Aes.c29
-rw-r--r--C/Alloc.c11
-rw-r--r--C/Alloc.h15
-rw-r--r--C/Bcj2.c328
-rw-r--r--C/Bcj2.h148
-rw-r--r--C/Bcj2Enc.c312
-rw-r--r--C/Compiler.h7
-rw-r--r--C/CpuArch.c25
-rw-r--r--C/CpuArch.h100
-rw-r--r--C/LzFind.c479
-rw-r--r--C/LzFind.h20
-rw-r--r--C/LzFindMt.c164
-rw-r--r--C/LzFindMt.h4
-rw-r--r--C/LzHash.h43
-rw-r--r--C/Lzma2Dec.c40
-rw-r--r--C/Lzma2Dec.h4
-rw-r--r--C/Lzma2Enc.c4
-rw-r--r--C/LzmaDec.c178
-rw-r--r--C/LzmaEnc.c243
-rw-r--r--C/LzmaLib.c16
-rw-r--r--C/RotateDefs.h10
-rw-r--r--C/Sha1.c334
-rw-r--r--C/Sha1.h38
-rw-r--r--C/Sha256.c153
-rw-r--r--C/Threads.c4
-rw-r--r--C/Util/7z/7z.dsp14
-rw-r--r--C/Util/7z/7zMain.c154
-rw-r--r--C/Util/7z/makefile3
-rw-r--r--C/Util/7zipInstall/7zip.icobin0 -> 1078 bytes
-rw-r--r--C/Util/7zipInstall/7zipInstall.c1452
-rw-r--r--C/Util/7zipInstall/7zipInstall.dsp231
-rw-r--r--C/Util/7zipInstall/7zipInstall.dsw29
-rw-r--r--C/Util/7zipInstall/7zipInstall.manifest18
-rw-r--r--C/Util/7zipInstall/Precomp.c4
-rw-r--r--C/Util/7zipInstall/Precomp.h11
-rw-r--r--C/Util/7zipInstall/makefile40
-rw-r--r--C/Util/7zipInstall/resource.h9
-rw-r--r--C/Util/7zipInstall/resource.rc47
-rw-r--r--C/Util/7zipUninstall/7zipUninstall.c1077
-rw-r--r--C/Util/7zipUninstall/7zipUninstall.dsp124
-rw-r--r--C/Util/7zipUninstall/7zipUninstall.dsw29
-rw-r--r--C/Util/7zipUninstall/7zipUninstall.icobin0 -> 1078 bytes
-rw-r--r--C/Util/7zipUninstall/7zipUninstall.manifest18
-rw-r--r--C/Util/7zipUninstall/Precomp.c4
-rw-r--r--C/Util/7zipUninstall/Precomp.h11
-rw-r--r--C/Util/7zipUninstall/makefile17
-rw-r--r--C/Util/7zipUninstall/resource.h9
-rw-r--r--C/Util/7zipUninstall/resource.rc47
-rw-r--r--C/Util/Lzma/LzmaUtil.c6
-rw-r--r--C/Util/SfxSetup/SfxSetup.c22
-rw-r--r--C/Util/SfxSetup/SfxSetup.dsp12
-rw-r--r--C/Util/SfxSetup/makefile2
-rw-r--r--C/Util/SfxSetup/makefile_con2
-rw-r--r--C/Xz.c10
-rw-r--r--C/Xz.h14
-rw-r--r--C/XzCrc64.c24
-rw-r--r--C/XzCrc64Opt.c56
-rw-r--r--C/XzDec.c54
-rw-r--r--C/XzEnc.c23
-rw-r--r--C/XzIn.c65
-rw-r--r--CPP/7zip/Archive/7z/7z.dsp8
-rw-r--r--CPP/7zip/Archive/7z/7zCompressionMode.h43
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.cpp520
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.h51
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.cpp580
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.h67
-rw-r--r--CPP/7zip/Archive/7z/7zExtract.cpp460
-rw-r--r--CPP/7zip/Archive/7z/7zFolderInStream.cpp133
-rw-r--r--CPP/7zip/Archive/7z/7zFolderInStream.h39
-rw-r--r--CPP/7zip/Archive/7z/7zFolderOutStream.cpp146
-rw-r--r--CPP/7zip/Archive/7z/7zFolderOutStream.h52
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.cpp76
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h25
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp181
-rw-r--r--CPP/7zip/Archive/7z/7zHeader.h47
-rw-r--r--CPP/7zip/Archive/7z/7zIn.cpp279
-rw-r--r--CPP/7zip/Archive/7z/7zIn.h57
-rw-r--r--CPP/7zip/Archive/7z/7zItem.h63
-rw-r--r--CPP/7zip/Archive/7z/7zOut.cpp47
-rw-r--r--CPP/7zip/Archive/7z/7zOut.h4
-rw-r--r--CPP/7zip/Archive/7z/7zProperties.cpp48
-rw-r--r--CPP/7zip/Archive/7z/7zRegister.cpp14
-rw-r--r--CPP/7zip/Archive/7z/7zSpecStream.h10
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp1625
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.h27
-rw-r--r--CPP/7zip/Archive/ApmHandler.cpp12
-rw-r--r--CPP/7zip/Archive/ArHandler.cpp37
-rw-r--r--CPP/7zip/Archive/Archive.def8
-rw-r--r--CPP/7zip/Archive/Archive2.def10
-rw-r--r--CPP/7zip/Archive/ArchiveExports.cpp30
-rw-r--r--CPP/7zip/Archive/ArjHandler.cpp230
-rw-r--r--CPP/7zip/Archive/Bz2Handler.cpp47
-rw-r--r--CPP/7zip/Archive/Cab/CabBlockInStream.cpp13
-rw-r--r--CPP/7zip/Archive/Cab/CabHandler.cpp99
-rw-r--r--CPP/7zip/Archive/Cab/CabHeader.cpp4
-rw-r--r--CPP/7zip/Archive/Cab/CabHeader.h4
-rw-r--r--CPP/7zip/Archive/Cab/CabIn.cpp3
-rw-r--r--CPP/7zip/Archive/Cab/CabIn.h13
-rw-r--r--CPP/7zip/Archive/Cab/CabItem.h2
-rw-r--r--CPP/7zip/Archive/Cab/CabRegister.cpp12
-rw-r--r--CPP/7zip/Archive/Chm/ChmHandler.cpp37
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.cpp23
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.h8
-rw-r--r--CPP/7zip/Archive/ComHandler.cpp84
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.cpp1061
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.h462
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2MT.cpp242
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2MT.h84
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2ST.cpp595
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2ST.h165
-rw-r--r--CPP/7zip/Archive/Common/CoderMixerMT.h2
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.cpp32
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.h4
-rw-r--r--CPP/7zip/Archive/Common/OutStreamWithSha1.cpp4
-rw-r--r--CPP/7zip/Archive/Common/OutStreamWithSha1.h10
-rw-r--r--CPP/7zip/Archive/CpioHandler.cpp27
-rw-r--r--CPP/7zip/Archive/CramfsHandler.cpp26
-rw-r--r--CPP/7zip/Archive/DllExports.cpp47
-rw-r--r--CPP/7zip/Archive/DllExports2.cpp50
-rw-r--r--CPP/7zip/Archive/DmgHandler.cpp153
-rw-r--r--CPP/7zip/Archive/ElfHandler.cpp12
-rw-r--r--CPP/7zip/Archive/FatHandler.cpp60
-rw-r--r--CPP/7zip/Archive/FlvHandler.cpp31
-rw-r--r--CPP/7zip/Archive/GzHandler.cpp130
-rw-r--r--CPP/7zip/Archive/HfsHandler.cpp39
-rw-r--r--CPP/7zip/Archive/IArchive.h124
-rw-r--r--CPP/7zip/Archive/IhexHandler.cpp26
-rw-r--r--CPP/7zip/Archive/Iso/IsoHandler.cpp37
-rw-r--r--CPP/7zip/Archive/Iso/IsoHeader.cpp9
-rw-r--r--CPP/7zip/Archive/Iso/IsoHeader.h8
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.cpp193
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.h132
-rw-r--r--CPP/7zip/Archive/Iso/IsoItem.h33
-rw-r--r--CPP/7zip/Archive/Iso/IsoRegister.cpp12
-rw-r--r--CPP/7zip/Archive/LzhHandler.cpp21
-rw-r--r--CPP/7zip/Archive/LzmaHandler.cpp91
-rw-r--r--CPP/7zip/Archive/MachoHandler.cpp30
-rw-r--r--CPP/7zip/Archive/MbrHandler.cpp33
-rw-r--r--CPP/7zip/Archive/MslzHandler.cpp28
-rw-r--r--CPP/7zip/Archive/MubHandler.cpp18
-rw-r--r--CPP/7zip/Archive/Nsis/NsisDecode.cpp24
-rw-r--r--CPP/7zip/Archive/Nsis/NsisDecode.h2
-rw-r--r--CPP/7zip/Archive/Nsis/NsisHandler.cpp17
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.cpp103
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.h3
-rw-r--r--CPP/7zip/Archive/Nsis/NsisRegister.cpp12
-rw-r--r--CPP/7zip/Archive/NtfsHandler.cpp652
-rw-r--r--CPP/7zip/Archive/PeHandler.cpp183
-rw-r--r--CPP/7zip/Archive/PpmdHandler.cpp21
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.cpp149
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.h17
-rw-r--r--CPP/7zip/Archive/Rar/RarItem.h8
-rw-r--r--CPP/7zip/Archive/RpmHandler.cpp27
-rw-r--r--CPP/7zip/Archive/SplitHandler.cpp106
-rw-r--r--CPP/7zip/Archive/SquashfsHandler.cpp33
-rw-r--r--CPP/7zip/Archive/SwfHandler.cpp39
-rw-r--r--CPP/7zip/Archive/Tar/TarHandler.cpp26
-rw-r--r--CPP/7zip/Archive/Tar/TarHandler.h2
-rw-r--r--CPP/7zip/Archive/Tar/TarHandlerOut.cpp4
-rw-r--r--CPP/7zip/Archive/Tar/TarIn.cpp40
-rw-r--r--CPP/7zip/Archive/Tar/TarItem.h2
-rw-r--r--CPP/7zip/Archive/Tar/TarRegister.cpp15
-rw-r--r--CPP/7zip/Archive/Tar/TarUpdate.cpp10
-rw-r--r--CPP/7zip/Archive/Udf/UdfHandler.cpp26
-rw-r--r--CPP/7zip/Archive/Udf/UdfIn.cpp26
-rw-r--r--CPP/7zip/Archive/Udf/UdfRegister.cpp7
-rw-r--r--CPP/7zip/Archive/UefiHandler.cpp509
-rw-r--r--CPP/7zip/Archive/VhdHandler.cpp66
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.cpp67
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.h2
-rw-r--r--CPP/7zip/Archive/Wim/WimHandlerOut.cpp43
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.cpp90
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.h4
-rw-r--r--CPP/7zip/Archive/Wim/WimRegister.cpp13
-rw-r--r--CPP/7zip/Archive/XarHandler.cpp61
-rw-r--r--CPP/7zip/Archive/XzHandler.cpp285
-rw-r--r--CPP/7zip/Archive/XzHandler.h65
-rw-r--r--CPP/7zip/Archive/ZHandler.cpp12
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.cpp116
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.h6
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.cpp180
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.h2
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandlerOut.cpp24
-rw-r--r--CPP/7zip/Archive/Zip/ZipHeader.h2
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.cpp23
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.h4
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.cpp7
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.h16
-rw-r--r--CPP/7zip/Archive/Zip/ZipOut.h2
-rw-r--r--CPP/7zip/Archive/Zip/ZipRegister.cpp21
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp80
-rw-r--r--CPP/7zip/Bundles/Alone/Alone.dsp102
-rw-r--r--CPP/7zip/Bundles/Alone/makefile9
-rw-r--r--CPP/7zip/Bundles/Alone7z/Alone.dsp80
-rw-r--r--CPP/7zip/Bundles/Alone7z/makefile5
-rw-r--r--CPP/7zip/Bundles/Fm/FM.dsp342
-rw-r--r--CPP/7zip/Bundles/Fm/makefile2
-rw-r--r--CPP/7zip/Bundles/Format7z/makefile5
-rw-r--r--CPP/7zip/Bundles/Format7zExtract/makefile4
-rw-r--r--CPP/7zip/Bundles/Format7zExtractR/makefile4
-rw-r--r--CPP/7zip/Bundles/Format7zF/Arc.mak10
-rw-r--r--CPP/7zip/Bundles/Format7zF/Format7z.dsp245
-rw-r--r--CPP/7zip/Bundles/Format7zR/makefile5
-rw-r--r--CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp571
-rw-r--r--CPP/7zip/Bundles/LzmaCon/resource.rc2
-rw-r--r--CPP/7zip/Bundles/SFXCon/SFXCon.dsp66
-rw-r--r--CPP/7zip/Bundles/SFXCon/SfxCon.cpp16
-rw-r--r--CPP/7zip/Bundles/SFXCon/makefile11
-rw-r--r--CPP/7zip/Bundles/SFXCon/resource.rc2
-rw-r--r--CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp28
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp58
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp16
-rw-r--r--CPP/7zip/Bundles/SFXSetup/makefile10
-rw-r--r--CPP/7zip/Bundles/SFXSetup/resource.rc2
-rw-r--r--CPP/7zip/Bundles/SFXWin/SFXWin.dsp58
-rw-r--r--CPP/7zip/Bundles/SFXWin/makefile11
-rw-r--r--CPP/7zip/Bundles/SFXWin/resource.rc2
-rw-r--r--CPP/7zip/Common/CreateCoder.cpp316
-rw-r--r--CPP/7zip/Common/CreateCoder.h135
-rw-r--r--CPP/7zip/Common/FilePathAutoRename.cpp44
-rw-r--r--CPP/7zip/Common/FileStreams.cpp56
-rw-r--r--CPP/7zip/Common/FileStreams.h24
-rw-r--r--CPP/7zip/Common/FilterCoder.cpp435
-rw-r--r--CPP/7zip/Common/FilterCoder.h182
-rw-r--r--CPP/7zip/Common/InOutTempBuffer.cpp24
-rw-r--r--CPP/7zip/Common/InOutTempBuffer.h6
-rw-r--r--CPP/7zip/Common/LimitedStreams.cpp5
-rw-r--r--CPP/7zip/Common/LockedStream.cpp20
-rw-r--r--CPP/7zip/Common/LockedStream.h36
-rw-r--r--CPP/7zip/Common/MethodProps.cpp27
-rw-r--r--CPP/7zip/Common/MethodProps.h21
-rw-r--r--CPP/7zip/Common/ProgressUtils.cpp33
-rw-r--r--CPP/7zip/Common/ProgressUtils.h7
-rw-r--r--CPP/7zip/Common/PropId.cpp10
-rw-r--r--CPP/7zip/Common/RegisterArc.h67
-rw-r--r--CPP/7zip/Common/RegisterCodec.h69
-rw-r--r--CPP/7zip/Common/StreamBinder.cpp52
-rw-r--r--CPP/7zip/Common/StreamBinder.h32
-rw-r--r--CPP/7zip/Common/StreamObjects.cpp61
-rw-r--r--CPP/7zip/Common/StreamObjects.h25
-rw-r--r--CPP/7zip/Common/UniqBlocks.cpp21
-rw-r--r--CPP/7zip/Common/UniqBlocks.h12
-rw-r--r--CPP/7zip/Compress/ArjDecoder1.cpp309
-rw-r--r--CPP/7zip/Compress/ArjDecoder1.h91
-rw-r--r--CPP/7zip/Compress/ArjDecoder2.cpp91
-rw-r--r--CPP/7zip/Compress/ArjDecoder2.h52
-rw-r--r--CPP/7zip/Compress/BZip2Const.h25
-rw-r--r--CPP/7zip/Compress/BZip2Decoder.cpp31
-rw-r--r--CPP/7zip/Compress/BZip2Decoder.h8
-rw-r--r--CPP/7zip/Compress/BZip2Encoder.cpp102
-rw-r--r--CPP/7zip/Compress/BZip2Encoder.h6
-rw-r--r--CPP/7zip/Compress/BZip2Register.cpp12
-rw-r--r--CPP/7zip/Compress/Bcj2Coder.cpp818
-rw-r--r--CPP/7zip/Compress/Bcj2Coder.h107
-rw-r--r--CPP/7zip/Compress/Bcj2Register.cpp10
-rw-r--r--CPP/7zip/Compress/BcjCoder.cpp12
-rw-r--r--CPP/7zip/Compress/BcjCoder.h19
-rw-r--r--CPP/7zip/Compress/BcjRegister.cpp15
-rw-r--r--CPP/7zip/Compress/BitmDecoder.h15
-rw-r--r--CPP/7zip/Compress/BranchCoder.cpp19
-rw-r--r--CPP/7zip/Compress/BranchCoder.h44
-rw-r--r--CPP/7zip/Compress/BranchMisc.cpp25
-rw-r--r--CPP/7zip/Compress/BranchMisc.h28
-rw-r--r--CPP/7zip/Compress/BranchRegister.cpp36
-rw-r--r--CPP/7zip/Compress/ByteSwap.cpp62
-rw-r--r--CPP/7zip/Compress/CodecExports.cpp244
-rw-r--r--CPP/7zip/Compress/CopyCoder.cpp65
-rw-r--r--CPP/7zip/Compress/CopyCoder.h17
-rw-r--r--CPP/7zip/Compress/CopyRegister.cpp7
-rw-r--r--CPP/7zip/Compress/Deflate64Register.cpp12
-rw-r--r--CPP/7zip/Compress/DeflateConst.h70
-rw-r--r--CPP/7zip/Compress/DeflateDecoder.cpp8
-rw-r--r--CPP/7zip/Compress/DeflateEncoder.cpp87
-rw-r--r--CPP/7zip/Compress/DeflateEncoder.h22
-rw-r--r--CPP/7zip/Compress/DeflateRegister.cpp11
-rw-r--r--CPP/7zip/Compress/DeltaFilter.cpp58
-rw-r--r--CPP/7zip/Compress/DllExports2Compress.cpp7
-rw-r--r--CPP/7zip/Compress/DllExportsCompress.cpp5
-rw-r--r--CPP/7zip/Compress/HuffmanDecoder.h25
-rw-r--r--CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp8
-rw-r--r--CPP/7zip/Compress/ImplodeHuffmanDecoder.h2
-rw-r--r--CPP/7zip/Compress/LzOutWindow.h15
-rw-r--r--CPP/7zip/Compress/LzhDecoder.cpp310
-rw-r--r--CPP/7zip/Compress/LzhDecoder.h97
-rw-r--r--CPP/7zip/Compress/Lzma2Decoder.cpp167
-rw-r--r--CPP/7zip/Compress/Lzma2Decoder.h43
-rw-r--r--CPP/7zip/Compress/Lzma2Encoder.cpp8
-rw-r--r--CPP/7zip/Compress/Lzma2Register.cpp13
-rw-r--r--CPP/7zip/Compress/LzmaDecoder.cpp18
-rw-r--r--CPP/7zip/Compress/LzmaDecoder.h3
-rw-r--r--CPP/7zip/Compress/LzmaEncoder.cpp23
-rw-r--r--CPP/7zip/Compress/LzmaRegister.cpp13
-rw-r--r--CPP/7zip/Compress/PpmdDecoder.cpp4
-rw-r--r--CPP/7zip/Compress/PpmdEncoder.cpp6
-rw-r--r--CPP/7zip/Compress/PpmdRegister.cpp14
-rw-r--r--CPP/7zip/Compress/PpmdZip.cpp14
-rw-r--r--CPP/7zip/Compress/RangeCoder.h201
-rw-r--r--CPP/7zip/Compress/RangeCoderBit.h114
-rw-r--r--CPP/7zip/Compress/Rar1Decoder.cpp47
-rw-r--r--CPP/7zip/Compress/Rar2Decoder.cpp56
-rw-r--r--CPP/7zip/Compress/Rar2Decoder.h16
-rw-r--r--CPP/7zip/Compress/Rar3Decoder.cpp4
-rw-r--r--CPP/7zip/Compress/Rar3Vm.cpp14
-rw-r--r--CPP/7zip/Compress/Rar3Vm.h2
-rw-r--r--CPP/7zip/Compress/RarCodecsRegister.cpp12
-rw-r--r--CPP/7zip/Crc.mak2
-rw-r--r--CPP/7zip/Crypto/7zAes.cpp222
-rw-r--r--CPP/7zip/Crypto/7zAes.h45
-rw-r--r--CPP/7zip/Crypto/7zAesRegister.cpp16
-rw-r--r--CPP/7zip/Crypto/HmacSha1.cpp67
-rw-r--r--CPP/7zip/Crypto/HmacSha1.h6
-rw-r--r--CPP/7zip/Crypto/MyAes.h9
-rw-r--r--CPP/7zip/Crypto/MyAesReg.cpp15
-rw-r--r--CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp44
-rw-r--r--CPP/7zip/Crypto/RandGen.cpp17
-rw-r--r--CPP/7zip/Crypto/Rar20Crypto.cpp23
-rw-r--r--CPP/7zip/Crypto/Rar20Crypto.h16
-rw-r--r--CPP/7zip/Crypto/RarAes.cpp131
-rw-r--r--CPP/7zip/Crypto/RarAes.h20
-rw-r--r--CPP/7zip/Crypto/Sha1.cpp229
-rw-r--r--CPP/7zip/Crypto/Sha1.h69
-rw-r--r--CPP/7zip/Crypto/Sha1Cls.h51
-rw-r--r--CPP/7zip/Crypto/Sha1Reg.cpp55
-rw-r--r--CPP/7zip/Crypto/WzAes.cpp115
-rw-r--r--CPP/7zip/Crypto/WzAes.h59
-rw-r--r--CPP/7zip/Crypto/ZipCrypto.cpp94
-rw-r--r--CPP/7zip/Crypto/ZipCrypto.h37
-rw-r--r--CPP/7zip/Crypto/ZipStrong.cpp26
-rw-r--r--CPP/7zip/Crypto/ZipStrong.h13
-rw-r--r--CPP/7zip/Guid.txt30
-rw-r--r--CPP/7zip/ICoder.h198
-rw-r--r--CPP/7zip/IDecl.h19
-rw-r--r--CPP/7zip/IProgress.h15
-rw-r--r--CPP/7zip/IStream.h4
-rw-r--r--CPP/7zip/MyVersion.h8
-rw-r--r--CPP/7zip/PropID.h4
-rw-r--r--CPP/7zip/UI/Agent/Agent.cpp1021
-rw-r--r--CPP/7zip/UI/Agent/Agent.h116
-rw-r--r--CPP/7zip/UI/Agent/AgentOut.cpp199
-rw-r--r--CPP/7zip/UI/Agent/AgentProxy.cpp565
-rw-r--r--CPP/7zip/UI/Agent/AgentProxy.h142
-rw-r--r--CPP/7zip/UI/Agent/ArchiveFolder.cpp11
-rw-r--r--CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp50
-rw-r--r--CPP/7zip/UI/Agent/ArchiveFolderOut.cpp210
-rw-r--r--CPP/7zip/UI/Agent/IFolderArchive.h41
-rw-r--r--CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp106
-rw-r--r--CPP/7zip/UI/Agent/UpdateCallbackAgent.h2
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.cpp17
-rw-r--r--CPP/7zip/UI/Client7z/resource.rc2
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.cpp262
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.h47
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.cpp568
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.h64
-rw-r--r--CPP/7zip/UI/Common/ArchiveName.cpp60
-rw-r--r--CPP/7zip/UI/Common/ArchiveName.h4
-rw-r--r--CPP/7zip/UI/Common/ArchiveOpenCallback.cpp1
-rw-r--r--CPP/7zip/UI/Common/ArchiveOpenCallback.h10
-rw-r--r--CPP/7zip/UI/Common/Bench.cpp495
-rw-r--r--CPP/7zip/UI/Common/CompressCall.cpp110
-rw-r--r--CPP/7zip/UI/Common/CompressCall2.cpp40
-rw-r--r--CPP/7zip/UI/Common/DefaultName.cpp16
-rw-r--r--CPP/7zip/UI/Common/DirItem.h71
-rw-r--r--CPP/7zip/UI/Common/EnumDirItems.cpp351
-rw-r--r--CPP/7zip/UI/Common/EnumDirItems.h8
-rw-r--r--CPP/7zip/UI/Common/Extract.cpp182
-rw-r--r--CPP/7zip/UI/Common/Extract.h2
-rw-r--r--CPP/7zip/UI/Common/ExtractMode.h3
-rw-r--r--CPP/7zip/UI/Common/ExtractingFilePath.cpp279
-rw-r--r--CPP/7zip/UI/Common/ExtractingFilePath.h16
-rw-r--r--CPP/7zip/UI/Common/HashCalc.cpp74
-rw-r--r--CPP/7zip/UI/Common/HashCalc.h18
-rw-r--r--CPP/7zip/UI/Common/IFileExtractCallback.h84
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.cpp378
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.h195
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp457
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.h73
-rw-r--r--CPP/7zip/UI/Common/PropIDUtils.cpp177
-rw-r--r--CPP/7zip/UI/Common/PropIDUtils.h5
-rw-r--r--CPP/7zip/UI/Common/Update.cpp427
-rw-r--r--CPP/7zip/UI/Common/Update.h38
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.cpp253
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.h65
-rw-r--r--CPP/7zip/UI/Common/UpdatePair.cpp4
-rw-r--r--CPP/7zip/UI/Common/UpdateProduce.cpp11
-rw-r--r--CPP/7zip/UI/Common/UpdateProduce.h2
-rw-r--r--CPP/7zip/UI/Common/WorkDir.cpp7
-rw-r--r--CPP/7zip/UI/Console/BenchCon.cpp3
-rw-r--r--CPP/7zip/UI/Console/Console.dsp15
-rw-r--r--CPP/7zip/UI/Console/ConsoleClose.cpp21
-rw-r--r--CPP/7zip/UI/Console/ConsoleClose.h19
-rw-r--r--CPP/7zip/UI/Console/ExtractCallbackConsole.cpp781
-rw-r--r--CPP/7zip/UI/Console/ExtractCallbackConsole.h139
-rw-r--r--CPP/7zip/UI/Console/HashCon.cpp353
-rw-r--r--CPP/7zip/UI/Console/HashCon.h26
-rw-r--r--CPP/7zip/UI/Console/List.cpp576
-rw-r--r--CPP/7zip/UI/Console/Main.cpp573
-rw-r--r--CPP/7zip/UI/Console/MainAr.cpp98
-rw-r--r--CPP/7zip/UI/Console/OpenCallbackConsole.cpp77
-rw-r--r--CPP/7zip/UI/Console/OpenCallbackConsole.h48
-rw-r--r--CPP/7zip/UI/Console/PercentPrinter.cpp203
-rw-r--r--CPP/7zip/UI/Console/PercentPrinter.h68
-rw-r--r--CPP/7zip/UI/Console/UpdateCallbackConsole.cpp616
-rw-r--r--CPP/7zip/UI/Console/UpdateCallbackConsole.h97
-rw-r--r--CPP/7zip/UI/Console/UserInputUtils.cpp30
-rw-r--r--CPP/7zip/UI/Console/makefile2
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.cpp101
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.h2
-rw-r--r--CPP/7zip/UI/Explorer/DllExportsExplorer.cpp5
-rw-r--r--CPP/7zip/UI/Far/ExtractEngine.cpp183
-rw-r--r--CPP/7zip/UI/Far/ExtractEngine.h27
-rw-r--r--CPP/7zip/UI/Far/Far.cpp169
-rw-r--r--CPP/7zip/UI/Far/Far.def1
-rw-r--r--CPP/7zip/UI/Far/Far.dsp40
-rw-r--r--CPP/7zip/UI/Far/FarPlugin.h42
-rw-r--r--CPP/7zip/UI/Far/FarUtils.cpp158
-rw-r--r--CPP/7zip/UI/Far/FarUtils.h37
-rw-r--r--CPP/7zip/UI/Far/Plugin.cpp207
-rw-r--r--CPP/7zip/UI/Far/Plugin.h29
-rw-r--r--CPP/7zip/UI/Far/PluginDelete.cpp31
-rw-r--r--CPP/7zip/UI/Far/PluginRead.cpp18
-rw-r--r--CPP/7zip/UI/Far/PluginWrite.cpp257
-rw-r--r--CPP/7zip/UI/Far/ProgressBox.cpp333
-rw-r--r--CPP/7zip/UI/Far/ProgressBox.h81
-rw-r--r--CPP/7zip/UI/Far/UpdateCallbackFar.cpp179
-rw-r--r--CPP/7zip/UI/Far/UpdateCallbackFar.h17
-rw-r--r--CPP/7zip/UI/Far/makefile9
-rw-r--r--CPP/7zip/UI/FileManager/AboutDialog.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/AltStreamsFolder.cpp839
-rw-r--r--CPP/7zip/UI/FileManager/AltStreamsFolder.h100
-rw-r--r--CPP/7zip/UI/FileManager/App.cpp201
-rw-r--r--CPP/7zip/UI/FileManager/App.h2
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.cpp26
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.h2
-rw-r--r--CPP/7zip/UI/FileManager/EditPage.rc2
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.cpp453
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.h49
-rw-r--r--CPP/7zip/UI/FileManager/FM.cpp48
-rw-r--r--CPP/7zip/UI/FileManager/FM.dsp20
-rw-r--r--CPP/7zip/UI/FileManager/FM.mak1
-rw-r--r--CPP/7zip/UI/FileManager/FSDrives.cpp101
-rw-r--r--CPP/7zip/UI/FileManager/FSDrives.h8
-rw-r--r--CPP/7zip/UI/FileManager/FSFolder.cpp88
-rw-r--r--CPP/7zip/UI/FileManager/FSFolder.h30
-rw-r--r--CPP/7zip/UI/FileManager/FSFolderCopy.cpp576
-rw-r--r--CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp8
-rw-r--r--CPP/7zip/UI/FileManager/FilePlugins.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/FoldersPage.rc2
-rw-r--r--CPP/7zip/UI/FileManager/IFolder.h17
-rw-r--r--CPP/7zip/UI/FileManager/LangPage.cpp5
-rw-r--r--CPP/7zip/UI/FileManager/LangPage.rc2
-rw-r--r--CPP/7zip/UI/FileManager/LangUtils.cpp7
-rw-r--r--CPP/7zip/UI/FileManager/LangUtils.h4
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage.rc2
-rw-r--r--CPP/7zip/UI/FileManager/MyLoadMenu.cpp59
-rw-r--r--CPP/7zip/UI/FileManager/MyLoadMenu.h24
-rw-r--r--CPP/7zip/UI/FileManager/NetFolder.cpp16
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.cpp10
-rw-r--r--CPP/7zip/UI/FileManager/Panel.cpp117
-rw-r--r--CPP/7zip/UI/FileManager/Panel.h131
-rw-r--r--CPP/7zip/UI/FileManager/PanelCopy.cpp72
-rw-r--r--CPP/7zip/UI/FileManager/PanelCrc.cpp105
-rw-r--r--CPP/7zip/UI/FileManager/PanelDrag.cpp23
-rw-r--r--CPP/7zip/UI/FileManager/PanelFolderChange.cpp421
-rw-r--r--CPP/7zip/UI/FileManager/PanelItemOpen.cpp74
-rw-r--r--CPP/7zip/UI/FileManager/PanelItems.cpp87
-rw-r--r--CPP/7zip/UI/FileManager/PanelListNotify.cpp252
-rw-r--r--CPP/7zip/UI/FileManager/PanelMenu.cpp179
-rw-r--r--CPP/7zip/UI/FileManager/PanelOperations.cpp99
-rw-r--r--CPP/7zip/UI/FileManager/PanelSelect.cpp32
-rw-r--r--CPP/7zip/UI/FileManager/PanelSort.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/PanelSplitFile.cpp32
-rw-r--r--CPP/7zip/UI/FileManager/PluginInterface.h2
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.cpp70
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.h13
-rw-r--r--CPP/7zip/UI/FileManager/PropertyName.rc2
-rw-r--r--CPP/7zip/UI/FileManager/PropertyNameRes.h2
-rw-r--r--CPP/7zip/UI/FileManager/RegistryAssociations.cpp3
-rw-r--r--CPP/7zip/UI/FileManager/RootFolder.cpp93
-rw-r--r--CPP/7zip/UI/FileManager/RootFolder.h12
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage.rc2
-rw-r--r--CPP/7zip/UI/FileManager/SplitDialog.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/StringUtils.cpp5
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.cpp48
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.h2
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.rc17
-rw-r--r--CPP/7zip/UI/FileManager/SystemPageRes.h1
-rw-r--r--CPP/7zip/UI/FileManager/TextPairs.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/TextPairs.h2
-rw-r--r--CPP/7zip/UI/FileManager/UpdateCallback100.cpp75
-rw-r--r--CPP/7zip/UI/FileManager/UpdateCallback100.h24
-rw-r--r--CPP/7zip/UI/FileManager/ViewSettings.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/makefile1
-rw-r--r--CPP/7zip/UI/FileManager/resource.h1
-rw-r--r--CPP/7zip/UI/FileManager/resource.rc2
-rw-r--r--CPP/7zip/UI/GUI/BenchmarkDialog.cpp70
-rw-r--r--CPP/7zip/UI/GUI/BenchmarkDialog.h8
-rw-r--r--CPP/7zip/UI/GUI/BenchmarkDialog.rc16
-rw-r--r--CPP/7zip/UI/GUI/BenchmarkDialogRes.h3
-rw-r--r--CPP/7zip/UI/GUI/CompressDialog.cpp270
-rw-r--r--CPP/7zip/UI/GUI/CompressDialog.h2
-rw-r--r--CPP/7zip/UI/GUI/CompressDialog.rc10
-rw-r--r--CPP/7zip/UI/GUI/Extract.rc9
-rw-r--r--CPP/7zip/UI/GUI/ExtractDialog.cpp4
-rw-r--r--CPP/7zip/UI/GUI/ExtractGUI.cpp26
-rw-r--r--CPP/7zip/UI/GUI/ExtractRes.h9
-rw-r--r--CPP/7zip/UI/GUI/GUI.cpp58
-rw-r--r--CPP/7zip/UI/GUI/GUI.dsp24
-rw-r--r--CPP/7zip/UI/GUI/HashGUI.cpp81
-rw-r--r--CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp139
-rw-r--r--CPP/7zip/UI/GUI/UpdateCallbackGUI.h24
-rw-r--r--CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp59
-rw-r--r--CPP/7zip/UI/GUI/UpdateCallbackGUI2.h35
-rw-r--r--CPP/7zip/UI/GUI/UpdateGUI.cpp15
-rw-r--r--CPP/7zip/UI/GUI/makefile2
-rw-r--r--CPP/7zip/UI/GUI/resource.rc2
-rw-r--r--CPP/7zip/UI/GUI/resource3.h10
-rw-r--r--CPP/7zip/UI/GUI/resource3.rc15
-rw-r--r--CPP/Build.mak2
-rw-r--r--CPP/Common/CommandLineParser.cpp15
-rw-r--r--CPP/Common/CrcReg.cpp83
-rw-r--r--CPP/Common/DynLimBuf.h6
-rw-r--r--CPP/Common/DynamicBuffer.h12
-rw-r--r--CPP/Common/Lang.cpp13
-rw-r--r--CPP/Common/Lang.h2
-rw-r--r--CPP/Common/ListFileUtils.cpp10
-rw-r--r--CPP/Common/MyBuffer.h54
-rw-r--r--CPP/Common/MyCom.h40
-rw-r--r--CPP/Common/MyString.cpp478
-rw-r--r--CPP/Common/MyString.h308
-rw-r--r--CPP/Common/MyTypes.h5
-rw-r--r--CPP/Common/MyVector.h27
-rw-r--r--CPP/Common/NewHandler.cpp3
-rw-r--r--CPP/Common/Sha1Reg.cpp40
-rw-r--r--CPP/Common/Sha256Reg.cpp28
-rw-r--r--CPP/Common/StdOutStream.h2
-rw-r--r--CPP/Common/StringConvert.cpp350
-rw-r--r--CPP/Common/StringConvert.h2
-rw-r--r--CPP/Common/StringToInt.cpp20
-rw-r--r--CPP/Common/UTFConvert.cpp280
-rw-r--r--CPP/Common/UTFConvert.h4
-rw-r--r--CPP/Common/Wildcard.cpp257
-rw-r--r--CPP/Common/Wildcard.h24
-rw-r--r--CPP/Common/XzCrc64Reg.cpp26
-rw-r--r--CPP/Windows/COM.cpp10
-rw-r--r--CPP/Windows/COM.h4
-rw-r--r--CPP/Windows/Console.h2
-rw-r--r--CPP/Windows/Control/ComboBox.cpp18
-rw-r--r--CPP/Windows/Control/Dialog.h4
-rw-r--r--CPP/Windows/Control/Window2.h2
-rw-r--r--CPP/Windows/DLL.cpp2
-rw-r--r--CPP/Windows/DLL.h10
-rw-r--r--CPP/Windows/ErrorMsg.cpp19
-rw-r--r--CPP/Windows/FileDir.cpp201
-rw-r--r--CPP/Windows/FileDir.h7
-rw-r--r--CPP/Windows/FileFind.cpp317
-rw-r--r--CPP/Windows/FileFind.h11
-rw-r--r--CPP/Windows/FileIO.cpp2
-rw-r--r--CPP/Windows/FileLink.cpp22
-rw-r--r--CPP/Windows/FileName.cpp274
-rw-r--r--CPP/Windows/FileName.h51
-rw-r--r--CPP/Windows/MemoryGlobal.h2
-rw-r--r--CPP/Windows/Menu.h8
-rw-r--r--CPP/Windows/NationalTime.cpp8
-rw-r--r--CPP/Windows/ProcessUtils.h12
-rw-r--r--CPP/Windows/PropVariant.cpp47
-rw-r--r--CPP/Windows/PropVariant.h5
-rw-r--r--CPP/Windows/PropVariantConv.cpp2
-rw-r--r--CPP/Windows/PropVariantUtils.cpp6
-rw-r--r--CPP/Windows/PropVariantUtils.h6
-rw-r--r--CPP/Windows/Registry.cpp90
-rw-r--r--CPP/Windows/Registry.h2
-rw-r--r--CPP/Windows/ResourceString.cpp8
-rw-r--r--CPP/Windows/SecurityUtils.cpp15
-rw-r--r--CPP/Windows/Shell.cpp32
-rw-r--r--CPP/Windows/Window.cpp34
-rw-r--r--DOC/7zip.inf4
-rw-r--r--DOC/7zip.nsi4
-rw-r--r--DOC/7zip.wxs7
-rw-r--r--DOC/Methods.txt127
-rw-r--r--DOC/readme.txt4
-rw-r--r--DOC/src-history.txt2
591 files changed, 34587 insertions, 16045 deletions
diff --git a/C/7z.h b/C/7z.h
index ca4a2233..708892cc 100644
--- a/C/7z.h
+++ b/C/7z.h
@@ -1,5 +1,5 @@
/* 7z.h -- 7z interface
-2013-01-18 : Igor Pavlov : Public domain */
+2014-02-08 : Igor Pavlov : Public domain */
#ifndef __7Z_H
#define __7Z_H
@@ -11,7 +11,7 @@ EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6
-extern Byte k7zSignature[k7zSignatureSize];
+extern const Byte k7zSignature[k7zSignatureSize];
typedef struct
{
@@ -25,8 +25,7 @@ typedef struct
{
size_t PropsOffset;
UInt32 MethodID;
- Byte NumInStreams;
- Byte NumOutStreams;
+ Byte NumStreams;
Byte PropsSize;
} CSzCoderInfo;
@@ -34,23 +33,22 @@ typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
-} CSzBindPair;
+} CSzBond;
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4
-#define SZ_NUM_BINDS_IN_FOLDER_MAX 3
+#define SZ_NUM_BONDS_IN_FOLDER_MAX 3
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
-#define SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX 4
typedef struct
{
UInt32 NumCoders;
- UInt32 NumBindPairs;
+ UInt32 NumBonds;
UInt32 NumPackStreams;
- UInt32 MainOutStream;
+ UInt32 UnpackStream;
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
- CSzBindPair BindPairs[SZ_NUM_BINDS_IN_FOLDER_MAX];
+ CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
- UInt64 CodersUnpackSizes[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];
+ UInt64 CodersUnpackSizes[SZ_NUM_CODERS_IN_FOLDER_MAX];
} CSzFolder;
/*
diff --git a/C/7zAlloc.c b/C/7zAlloc.c
index 97cea299..7a3d4c00 100644
--- a/C/7zAlloc.c
+++ b/C/7zAlloc.c
@@ -1,5 +1,5 @@
/* 7zAlloc.c -- Allocation functions
-2010-10-29 : Igor Pavlov : Public domain */
+2015-02-21 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -22,7 +22,7 @@ int g_allocCountTemp = 0;
void *SzAlloc(void *p, size_t size)
{
- p = p;
+ UNUSED_VAR(p);
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
@@ -34,7 +34,7 @@ void *SzAlloc(void *p, size_t size)
void SzFree(void *p, void *address)
{
- p = p;
+ UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
{
@@ -47,7 +47,7 @@ void SzFree(void *p, void *address)
void *SzAllocTemp(void *p, size_t size)
{
- p = p;
+ UNUSED_VAR(p);
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
@@ -62,7 +62,7 @@ void *SzAllocTemp(void *p, size_t size)
void SzFreeTemp(void *p, void *address)
{
- p = p;
+ UNUSED_VAR(p);
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
{
diff --git a/C/7zAlloc.h b/C/7zAlloc.h
index 3344e937..2fd5bdbc 100644
--- a/C/7zAlloc.h
+++ b/C/7zAlloc.h
@@ -1,15 +1,23 @@
/* 7zAlloc.h -- Allocation functions
-2010-10-29 : Igor Pavlov : Public domain */
+2013-03-25 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H
#include <stdlib.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void *SzAlloc(void *p, size_t size);
void SzFree(void *p, void *address);
void *SzAllocTemp(void *p, size_t size);
void SzFreeTemp(void *p, void *address);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/C/7zArcIn.c b/C/7zArcIn.c
index cdca6564..31939daa 100644
--- a/C/7zArcIn.c
+++ b/C/7zArcIn.c
@@ -1,5 +1,5 @@
/* 7zArcIn.c -- 7z Input functions
-2014-06-16 : Igor Pavlov : Public domain */
+2015-05-16 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -10,9 +10,17 @@
#include "7zCrc.h"
#include "CpuArch.h"
-#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \
+#define MY_ALLOC(T, p, size, alloc) { \
if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; }
+#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = 0; else MY_ALLOC(T, p, size, alloc) }
+
+#define MY_ALLOC_AND_CPY(to, size, from, alloc) \
+ { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
+
+#define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \
+ { if ((size) == 0) p = 0; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }
+
#define k7zMajorVersion 0
enum EIdEnum
@@ -48,17 +56,15 @@ enum EIdEnum
// k7zIsReal
};
-Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
+const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
-#define NUM_FOLDER_CODERS_MAX 32
-#define NUM_CODER_STREAMS_MAX 32
/*
-static int SzFolder_FindBindPairForInStream(const CSzFolder *p, UInt32 inStreamIndex)
+static int SzFolder_FindBondForInStream(const CSzFolder *p, UInt32 inStreamIndex)
{
UInt32 i;
- for (i = 0; i < p->NumBindPairs; i++)
- if (p->BindPairs[i].InIndex == inStreamIndex)
+ for (i = 0; i < p->NumBonds; i++)
+ if (p->Bonds[i].InIndex == inStreamIndex)
return i;
return -1;
}
@@ -68,8 +74,16 @@ static int SzFolder_FindBindPairForInStream(const CSzFolder *p, UInt32 inStreamI
static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)
{
- MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc);
- MY_ALLOC(UInt32, p->Vals, num, alloc);
+ if (num == 0)
+ {
+ p->Defs = 0;
+ p->Vals = 0;
+ }
+ else
+ {
+ MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc);
+ MY_ALLOC(UInt32, p->Vals, num, alloc);
+ }
return SZ_OK;
}
@@ -170,7 +184,7 @@ void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
static int TestSignatureCandidate(Byte *testBytes)
{
- size_t i;
+ unsigned i;
for (i = 0; i < k7zSignatureSize; i++)
if (testBytes[i] != k7zSignature[i])
return 0;
@@ -224,7 +238,7 @@ static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value)
Byte b;
if ((firstByte & mask) == 0)
{
- UInt64 highPart = firstByte & (mask - 1);
+ UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1);
*value |= (highPart << (8 * i));
return SZ_OK;
}
@@ -367,23 +381,23 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc)
{
Byte allAreDefined;
- UInt32 i;
Byte *v2;
UInt32 numBytes = (numItems + 7) >> 3;
+ *v = NULL;
RINOK(SzReadByte(sd, &allAreDefined));
+ if (numBytes == 0)
+ return SZ_OK;
if (allAreDefined == 0)
{
if (numBytes > sd->Size)
return SZ_ERROR_ARCHIVE;
- MY_ALLOC(Byte, *v, numBytes, alloc);
- memcpy(*v, sd->Data, numBytes);
+ MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc);
SKIP_DATA(sd, numBytes);
return SZ_OK;
}
MY_ALLOC(Byte, *v, numBytes, alloc);
v2 = *v;
- for (i = 0; i < numBytes; i++)
- v2[i] = 0xFF;
+ memset(v2, 0xFF, (size_t)numBytes);
{
unsigned numBits = (unsigned)numItems & 7;
if (numBits != 0)
@@ -398,7 +412,7 @@ static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *c
CSzData sd;
UInt32 *vals;
const Byte *defs;
- MY_ALLOC(UInt32, crcs->Vals, numItems, alloc);
+ MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc);
sd = *sd2;
defs = crcs->Defs;
vals = crcs->Vals;
@@ -486,19 +500,22 @@ static SRes SzReadSwitch(CSzData *sd)
}
*/
-#define SZ_NUM_IN_STREAMS_IN_FOLDER_MAX 16
+#define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes)
{
- UInt32 numCoders, numBindPairs, numPackStreams, i;
- UInt32 numInStreams = 0, numOutStreams = 0;
+ UInt32 numCoders, i;
+ UInt32 numInStreams = 0;
const Byte *dataStart = sd->Data;
- Byte inStreamUsed[SZ_NUM_IN_STREAMS_IN_FOLDER_MAX];
+
+ f->NumCoders = 0;
+ f->NumBonds = 0;
+ f->NumPackStreams = 0;
+ f->UnpackStream = 0;
RINOK(SzReadNumber32(sd, &numCoders));
- if (numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)
+ if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)
return SZ_ERROR_UNSUPPORTED;
- f->NumCoders = numCoders;
for (i = 0; i < numCoders; i++)
{
@@ -506,9 +523,11 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes)
CSzCoderInfo *coder = f->Coders + i;
unsigned idSize, j;
UInt64 id;
+
RINOK(SzReadByte(sd, &mainByte));
if ((mainByte & 0xC0) != 0)
return SZ_ERROR_UNSUPPORTED;
+
idSize = (unsigned)(mainByte & 0xF);
if (idSize > sizeof(id))
return SZ_ERROR_UNSUPPORTED;
@@ -525,106 +544,132 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes)
return SZ_ERROR_UNSUPPORTED;
coder->MethodID = (UInt32)id;
- coder->NumInStreams = 1;
- coder->NumOutStreams = 1;
+ coder->NumStreams = 1;
coder->PropsOffset = 0;
coder->PropsSize = 0;
if ((mainByte & 0x10) != 0)
{
UInt32 numStreams;
+
RINOK(SzReadNumber32(sd, &numStreams));
- if (numStreams > NUM_CODER_STREAMS_MAX)
+ if (numStreams > k_NumCodersStreams_in_Folder_MAX)
return SZ_ERROR_UNSUPPORTED;
- coder->NumInStreams = (Byte)numStreams;
+ coder->NumStreams = (Byte)numStreams;
+
RINOK(SzReadNumber32(sd, &numStreams));
- if (numStreams > NUM_CODER_STREAMS_MAX)
+ if (numStreams != 1)
return SZ_ERROR_UNSUPPORTED;
- coder->NumOutStreams = (Byte)numStreams;
}
+
+ numInStreams += coder->NumStreams;
+
+ if (numInStreams > k_NumCodersStreams_in_Folder_MAX)
+ return SZ_ERROR_UNSUPPORTED;
+
if ((mainByte & 0x20) != 0)
{
UInt32 propsSize = 0;
RINOK(SzReadNumber32(sd, &propsSize));
- if (propsSize >= 0x40)
- return SZ_ERROR_UNSUPPORTED;
if (propsSize > sd->Size)
return SZ_ERROR_ARCHIVE;
+ if (propsSize >= 0x80)
+ return SZ_ERROR_UNSUPPORTED;
coder->PropsOffset = sd->Data - dataStart;
coder->PropsSize = (Byte)propsSize;
sd->Data += (size_t)propsSize;
sd->Size -= (size_t)propsSize;
}
- numInStreams += coder->NumInStreams;
- numOutStreams += coder->NumOutStreams;
}
- if (numOutStreams == 0)
- return SZ_ERROR_UNSUPPORTED;
-
- f->NumBindPairs = numBindPairs = numOutStreams - 1;
- if (numInStreams < numBindPairs)
- return SZ_ERROR_ARCHIVE;
- if (numInStreams > SZ_NUM_IN_STREAMS_IN_FOLDER_MAX)
- return SZ_ERROR_UNSUPPORTED;
- f->MainOutStream = 0;
- f->NumPackStreams = numPackStreams = numInStreams - numBindPairs;
- if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
- return SZ_ERROR_UNSUPPORTED;
- for (i = 0; i < numInStreams; i++)
- inStreamUsed[i] = False;
- if (numBindPairs != 0)
+ /*
+ if (numInStreams == 1 && numCoders == 1)
{
- Byte outStreamUsed[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX];
-
- if (numBindPairs > SZ_NUM_BINDS_IN_FOLDER_MAX)
+ f->NumPackStreams = 1;
+ f->PackStreams[0] = 0;
+ }
+ else
+ */
+ {
+ Byte streamUsed[k_NumCodersStreams_in_Folder_MAX];
+ UInt32 numBonds, numPackStreams;
+
+ numBonds = numCoders - 1;
+ if (numInStreams < numBonds)
+ return SZ_ERROR_ARCHIVE;
+ if (numBonds > SZ_NUM_BONDS_IN_FOLDER_MAX)
return SZ_ERROR_UNSUPPORTED;
-
- for (i = 0; i < numOutStreams; i++)
- outStreamUsed[i] = False;
-
- for (i = 0; i < numBindPairs; i++)
+ f->NumBonds = numBonds;
+
+ numPackStreams = numInStreams - numBonds;
+ if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
+ return SZ_ERROR_UNSUPPORTED;
+ f->NumPackStreams = numPackStreams;
+
+ for (i = 0; i < numInStreams; i++)
+ streamUsed[i] = False;
+
+ if (numBonds != 0)
{
- CSzBindPair *bp = f->BindPairs + i;
- RINOK(SzReadNumber32(sd, &bp->InIndex));
- if (bp->InIndex >= numInStreams)
+ Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX];
+
+ for (i = 0; i < numCoders; i++)
+ coderUsed[i] = False;
+
+ for (i = 0; i < numBonds; i++)
+ {
+ CSzBond *bp = f->Bonds + i;
+
+ RINOK(SzReadNumber32(sd, &bp->InIndex));
+ if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex])
+ return SZ_ERROR_ARCHIVE;
+ streamUsed[bp->InIndex] = True;
+
+ RINOK(SzReadNumber32(sd, &bp->OutIndex));
+ if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex])
+ return SZ_ERROR_ARCHIVE;
+ coderUsed[bp->OutIndex] = True;
+ }
+
+ for (i = 0; i < numCoders; i++)
+ if (!coderUsed[i])
+ {
+ f->UnpackStream = i;
+ break;
+ }
+
+ if (i == numCoders)
return SZ_ERROR_ARCHIVE;
- inStreamUsed[bp->InIndex] = True;
- RINOK(SzReadNumber32(sd, &bp->OutIndex));
- if (bp->OutIndex >= numInStreams)
+ }
+
+ if (numPackStreams == 1)
+ {
+ for (i = 0; i < numInStreams; i++)
+ if (!streamUsed[i])
+ break;
+ if (i == numInStreams)
return SZ_ERROR_ARCHIVE;
- outStreamUsed[bp->OutIndex] = True;
+ f->PackStreams[0] = i;
}
- for (i = 0; i < numOutStreams; i++)
- if (!outStreamUsed[i])
+ else
+ for (i = 0; i < numPackStreams; i++)
{
- f->MainOutStream = i;
- break;
+ UInt32 index;
+ RINOK(SzReadNumber32(sd, &index));
+ if (index >= numInStreams || streamUsed[index])
+ return SZ_ERROR_ARCHIVE;
+ streamUsed[index] = True;
+ f->PackStreams[i] = index;
}
- if (i == numOutStreams)
- return SZ_ERROR_ARCHIVE;
- }
-
- if (numPackStreams == 1)
- {
- for (i = 0; i < numInStreams; i++)
- if (!inStreamUsed[i])
- break;
- if (i == numInStreams)
- return SZ_ERROR_ARCHIVE;
- f->PackStreams[0] = i;
}
- else
- for (i = 0; i < numPackStreams; i++)
- {
- RINOK(SzReadNumber32(sd, f->PackStreams + i));
- }
- for (i = 0; i < numOutStreams; i++)
+ for (i = 0; i < numCoders; i++)
{
RINOK(ReadNumber(sdSizes, f->CodersUnpackSizes + i));
}
+ f->NumCoders = numCoders;
+
return SZ_OK;
}
@@ -658,24 +703,25 @@ static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)
return SZ_OK;
}
-#define k_InStreamUsed_MAX 64
-#define k_OutStreamUsed_MAX 64
+#define k_Scan_NumCoders_MAX 64
+#define k_Scan_NumCodersStreams_in_Folder_MAX 64
static SRes ReadUnpackInfo(CSzAr *p,
CSzData *sd2,
- UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
+ UInt32 numFoldersMax,
+ const CBuf *tempBufs, UInt32 numTempBufs,
ISzAlloc *alloc)
{
CSzData sd;
- Byte inStreamUsed[k_InStreamUsed_MAX];
- Byte outStreamUsed[k_OutStreamUsed_MAX];
+
UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex;
const Byte *startBufPtr;
Byte external;
RINOK(WaitId(sd2, k7zIdFolder));
+
RINOK(SzReadNumber32(sd2, &numFolders));
- if (p->NumFolders > numFoldersMax)
+ if (numFolders > numFoldersMax)
return SZ_ERROR_UNSUPPORTED;
p->NumFolders = numFolders;
@@ -685,7 +731,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
else
{
UInt32 index;
- SzReadNumber32(sd2, &index);
+ RINOK(SzReadNumber32(sd2, &index));
if (index >= numTempBufs)
return SZ_ERROR_ARCHIVE;
sd.Data = tempBufs[index].data;
@@ -703,18 +749,19 @@ static SRes ReadUnpackInfo(CSzAr *p,
for (fo = 0; fo < numFolders; fo++)
{
- UInt32 numCoders, ci, numInStreams = 0, numOutStreams = 0;
+ UInt32 numCoders, ci, numInStreams = 0;
p->FoCodersOffsets[fo] = sd.Data - startBufPtr;
+
RINOK(SzReadNumber32(&sd, &numCoders));
- if (numCoders > NUM_FOLDER_CODERS_MAX)
+ if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
return SZ_ERROR_UNSUPPORTED;
for (ci = 0; ci < numCoders; ci++)
{
Byte mainByte;
unsigned idSize;
- UInt32 coderInStreams, coderOutStreams;
+ UInt32 coderInStreams;
SZ_READ_BYTE_2(mainByte);
if ((mainByte & 0xC0) != 0)
@@ -727,17 +774,18 @@ static SRes ReadUnpackInfo(CSzAr *p,
SKIP_DATA2(sd, idSize);
coderInStreams = 1;
- coderOutStreams = 1;
+
if ((mainByte & 0x10) != 0)
{
+ UInt32 coderOutStreams;
RINOK(SzReadNumber32(&sd, &coderInStreams));
RINOK(SzReadNumber32(&sd, &coderOutStreams));
- if (coderInStreams > NUM_CODER_STREAMS_MAX ||
- coderOutStreams > NUM_CODER_STREAMS_MAX)
+ if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1)
return SZ_ERROR_UNSUPPORTED;
}
+
numInStreams += coderInStreams;
- numOutStreams += coderOutStreams;
+
if ((mainByte & 0x20) != 0)
{
UInt32 propsSize;
@@ -751,64 +799,73 @@ static SRes ReadUnpackInfo(CSzAr *p,
{
UInt32 indexOfMainStream = 0;
UInt32 numPackStreams = 1;
- if (numOutStreams != 1 || numInStreams != 1)
+
+ if (numCoders != 1 || numInStreams != 1)
{
+ Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX];
+ Byte coderUsed[k_Scan_NumCoders_MAX];
+
UInt32 i;
- UInt32 numBindPairs = numOutStreams - 1;
- if (numOutStreams == 0 || numInStreams < numBindPairs)
+ UInt32 numBonds = numCoders - 1;
+ if (numInStreams < numBonds)
return SZ_ERROR_ARCHIVE;
- if (numInStreams > k_InStreamUsed_MAX ||
- numOutStreams > k_OutStreamUsed_MAX)
+ if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
return SZ_ERROR_UNSUPPORTED;
for (i = 0; i < numInStreams; i++)
- inStreamUsed[i] = False;
- for (i = 0; i < numOutStreams; i++)
- outStreamUsed[i] = False;
+ streamUsed[i] = False;
+ for (i = 0; i < numCoders; i++)
+ coderUsed[i] = False;
- for (i = 0; i < numBindPairs; i++)
+ for (i = 0; i < numBonds; i++)
{
UInt32 index;
+
RINOK(SzReadNumber32(&sd, &index));
- if (index >= numInStreams || inStreamUsed[index])
+ if (index >= numInStreams || streamUsed[index])
return SZ_ERROR_ARCHIVE;
- inStreamUsed[index] = True;
+ streamUsed[index] = True;
+
RINOK(SzReadNumber32(&sd, &index));
- if (index >= numInStreams || outStreamUsed[index])
+ if (index >= numCoders || coderUsed[index])
return SZ_ERROR_ARCHIVE;
- outStreamUsed[index] = True;
+ coderUsed[index] = True;
}
- numPackStreams = numInStreams - numBindPairs;
+ numPackStreams = numInStreams - numBonds;
if (numPackStreams != 1)
for (i = 0; i < numPackStreams; i++)
{
- UInt32 temp;
- RINOK(SzReadNumber32(&sd, &temp));
- if (temp >= numInStreams)
+ UInt32 index;
+ RINOK(SzReadNumber32(&sd, &index));
+ if (index >= numInStreams || streamUsed[index])
return SZ_ERROR_ARCHIVE;
+ streamUsed[index] = True;
}
- for (i = 0; i < numOutStreams; i++)
- if (!outStreamUsed[i])
+ for (i = 0; i < numCoders; i++)
+ if (!coderUsed[i])
{
indexOfMainStream = i;
break;
}
- if (i == numOutStreams)
+ if (i == numCoders)
return SZ_ERROR_ARCHIVE;
}
+
p->FoStartPackStreamIndex[fo] = packStreamIndex;
- p->FoSizesOffsets[fo] = (numOutStreams << 8) | indexOfMainStream;
- numCodersOutStreams += numOutStreams;
- if (numCodersOutStreams < numOutStreams)
+ p->FoSizesOffsets[fo] = (numCoders << 8) | indexOfMainStream;
+ numCodersOutStreams += numCoders;
+ if (numCodersOutStreams < numCoders)
return SZ_ERROR_UNSUPPORTED;
+
packStreamIndex += numPackStreams;
if (packStreamIndex < numPackStreams)
return SZ_ERROR_UNSUPPORTED;
+
if (packStreamIndex > p->NumPackStreams)
return SZ_ERROR_ARCHIVE;
}
@@ -818,8 +875,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
size_t dataSize = sd.Data - startBufPtr;
p->FoStartPackStreamIndex[fo] = packStreamIndex;
p->FoCodersOffsets[fo] = dataSize;
- MY_ALLOC(Byte, p->CodersData, dataSize, alloc);
- memcpy(p->CodersData, startBufPtr, dataSize);
+ MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc);
}
if (external != 0)
@@ -831,7 +887,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
RINOK(WaitId(&sd, k7zIdCodersUnpackSize));
- // MY_ALLOC(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);
+ // MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);
{
size_t dataSize = sd.Size;
/*
@@ -843,8 +899,7 @@ static SRes ReadUnpackInfo(CSzAr *p,
*/
RINOK(SkipNumbers(&sd, numCodersOutStreams));
dataSize -= sd.Size;
- MY_ALLOC(Byte, p->UnpackSizesData, dataSize, alloc);
- memcpy(p->UnpackSizesData, sd.Data - dataSize, dataSize);
+ MY_ALLOC_ZE_AND_CPY(p->UnpackSizesData, dataSize, sd.Data - dataSize, alloc);
p->UnpackSizesDataSize = dataSize;
/*
const Byte *data = SzReadNumbers(sd.Data, sd.Data + sd.Size, p->CoderUnpackSizes, numCodersOutStreams);
@@ -1019,8 +1074,10 @@ static SRes SzReadAndDecodePackedStreams(
sdCodersUnpSizes.Data = p->UnpackSizesData;
sdCodersUnpSizes.Size = p->UnpackSizesDataSize;
+
for (fo = 0; fo < p->NumFolders; fo++)
Buf_Init(tempBufs + fo);
+
for (fo = 0; fo < p->NumFolders; fo++)
{
CBuf *tempBuf = tempBufs + fo;
@@ -1049,6 +1106,7 @@ static SRes SzReadAndDecodePackedStreams(
if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp))
return SZ_ERROR_MEM;
}
+
p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;
for (fo = 0; fo < p->NumFolders; fo++)
@@ -1060,6 +1118,7 @@ static SRes SzReadAndDecodePackedStreams(
if (CrcCalc(tempBuf->data, tempBuf->size) != p->FolderCRCs.Vals[fo])
return SZ_ERROR_CRC;
}
+
return SZ_OK;
}
@@ -1069,6 +1128,8 @@ static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size
*offsets++ = 0;
if (numFiles == 0)
return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE;
+ if (size < 2)
+ return SZ_ERROR_ARCHIVE;
if (data[size - 2] != 0 || data[size - 1] != 0)
return SZ_ERROR_ARCHIVE;
do
@@ -1100,20 +1161,23 @@ static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
CNtfsFileTime *vals;
Byte *defs;
Byte external;
+
RINOK(ReadBitVector(sd2, num, &p->Defs, alloc));
+
RINOK(SzReadByte(sd2, &external));
if (external == 0)
sd = *sd2;
else
{
UInt32 index;
- SzReadNumber32(sd2, &index);
+ RINOK(SzReadNumber32(sd2, &index));
if (index >= numTempBufs)
return SZ_ERROR_ARCHIVE;
sd.Data = tempBufs[index].data;
sd.Size = tempBufs[index].size;
}
- MY_ALLOC(CNtfsFileTime, p->Vals, num, alloc);
+
+ MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc);
vals = p->Vals;
defs = p->Defs;
for (i = 0; i < num; i++)
@@ -1127,8 +1191,10 @@ static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
}
else
vals[i].High = vals[i].Low = 0;
+
if (external == 0)
*sd2 = sd;
+
return SZ_OK;
}
@@ -1141,8 +1207,7 @@ static SRes SzReadHeader2(
// Byte **emptyFileVector, /* allocTemp */
// Byte **lwtVector, /* allocTemp */
ILookInStream *inStream,
- CBuf *tempBufs,
- UInt32 *numTempBufs,
+ CBuf *tempBufs, UInt32 *numTempBufs,
ISzAlloc *allocMain,
ISzAlloc *allocTemp
)
@@ -1225,11 +1290,12 @@ static SRes SzReadHeader2(
RINOK(ReadNumber(sd, &size));
if (size > sd->Size)
return SZ_ERROR_ARCHIVE;
- if ((UInt64)(int)type != type)
+
+ if (type >= ((UInt32)1 << 8))
{
SKIP_DATA(sd, size);
}
- else switch((int)type)
+ else switch((unsigned)type)
{
case k7zIdName:
{
@@ -1246,7 +1312,7 @@ static SRes SzReadHeader2(
else
{
UInt32 index;
- SzReadNumber32(sd, &index);
+ RINOK(SzReadNumber32(sd, &index));
if (index >= *numTempBufs)
return SZ_ERROR_ARCHIVE;
namesData = (tempBufs)[index].data;
@@ -1255,9 +1321,8 @@ static SRes SzReadHeader2(
if ((namesSize & 1) != 0)
return SZ_ERROR_ARCHIVE;
- MY_ALLOC(Byte, p->FileNames, namesSize, allocMain);
MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
- memcpy(p->FileNames, namesData, namesSize);
+ MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain);
RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))
if (external == 0)
{
@@ -1290,7 +1355,7 @@ static SRes SzReadHeader2(
else
{
UInt32 index;
- SzReadNumber32(sd, &index);
+ RINOK(SzReadNumber32(sd, &index));
if (index >= *numTempBufs)
return SZ_ERROR_ARCHIVE;
sdSwitch.Data = (tempBufs)[index].data;
@@ -1352,9 +1417,9 @@ static SRes SzReadHeader2(
sdCodersUnpSizes.Size = p->db.UnpackSizesDataSize;
MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders + 1, allocMain);
- MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain);
+ MY_ALLOC_ZE(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain);
MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);
- MY_ALLOC(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);
+ MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);
RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain));
@@ -1660,20 +1725,19 @@ static SRes SzArEx_Open2(
{
if (type == k7zIdHeader)
{
+ /*
CSzData sd2;
- int ttt;
- for (ttt = 0; ttt < 1; ttt++)
- // for (ttt = 0; ttt < 40000; ttt++)
+ unsigned ttt;
+ for (ttt = 0; ttt < 40000; ttt++)
{
SzArEx_Free(p, allocMain);
sd2 = sd;
- res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp
- );
+ res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);
if (res != SZ_OK)
break;
}
-
- // res = SzReadHeader(p, &sd, allocMain, allocTemp);
+ */
+ res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp);
}
else
res = SZ_ERROR_UNSUPPORTED;
diff --git a/C/7zBuf2.c b/C/7zBuf2.c
index e14e65f4..430f76bf 100644
--- a/C/7zBuf2.c
+++ b/C/7zBuf2.c
@@ -1,5 +1,5 @@
/* 7zBuf2.c -- Byte Buffer
-2013-11-12 : Igor Pavlov : Public domain */
+2014-08-22 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -34,8 +34,11 @@ int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
alloc->Free(alloc, p->data);
p->data = data;
}
- memcpy(p->data + p->pos, buf, size);
- p->pos += size;
+ if (size != 0)
+ {
+ memcpy(p->data + p->pos, buf, size);
+ p->pos += size;
+ }
return 1;
}
diff --git a/C/7zCrc.c b/C/7zCrc.c
index 503e3591..dc6d6abd 100644
--- a/C/7zCrc.c
+++ b/C/7zCrc.c
@@ -1,5 +1,5 @@
/* 7zCrc.c -- CRC32 init
-2013-11-12 : Igor Pavlov : Public domain */
+2015-03-10 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -8,24 +8,28 @@
#define kCrcPoly 0xEDB88320
-#ifdef MY_CPU_X86_OR_AMD64
+#ifdef MY_CPU_LE
#define CRC_NUM_TABLES 8
- UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
-#elif defined(MY_CPU_LE)
- #define CRC_NUM_TABLES 4
#else
- #define CRC_NUM_TABLES 5
+ #define CRC_NUM_TABLES 9
+
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
+
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
+ UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
#ifndef MY_CPU_BE
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
+ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
+CRC_FUNC g_CrcUpdateT4;
+CRC_FUNC g_CrcUpdateT8;
CRC_FUNC g_CrcUpdate;
+
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
@@ -38,6 +42,17 @@ UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
}
+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
+
+UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
+{
+ const Byte *p = (const Byte *)data;
+ const Byte *pEnd = p + size;
+ for (; p != pEnd; p++)
+ v = CRC_UPDATE_BYTE_2(v, *p);
+ return v;
+}
+
void MY_FAST_CALL CrcGenerateTable()
{
UInt32 i;
@@ -54,22 +69,43 @@ void MY_FAST_CALL CrcGenerateTable()
UInt32 r = g_CrcTable[i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
}
+
+ #if CRC_NUM_TABLES < 4
+ g_CrcUpdate = CrcUpdateT1;
+
+ #else
+
#ifdef MY_CPU_LE
- g_CrcUpdate = CrcUpdateT4;
+ g_CrcUpdateT4 = CrcUpdateT4;
+ g_CrcUpdate = CrcUpdateT4;
+
+ #if CRC_NUM_TABLES >= 8
+ g_CrcUpdateT8 = CrcUpdateT8;
- #if CRC_NUM_TABLES == 8
- if (!CPU_Is_InOrder())
- g_CrcUpdate = CrcUpdateT8;
- #endif
+ #ifdef MY_CPU_X86_OR_AMD64
+ if (!CPU_Is_InOrder())
+ g_CrcUpdate = CrcUpdateT8;
+ #endif
+ #endif
#else
{
#ifndef MY_CPU_BE
- UInt32 k = 1;
- if (*(const Byte *)&k == 1)
+ UInt32 k = 0x01020304;
+ const Byte *p = (const Byte *)&k;
+ if (p[0] == 4 && p[1] == 3)
+ {
+ g_CrcUpdateT4 = CrcUpdateT4;
g_CrcUpdate = CrcUpdateT4;
+ #if CRC_NUM_TABLES >= 8
+ g_CrcUpdateT8 = CrcUpdateT8;
+ // g_CrcUpdate = CrcUpdateT8;
+ #endif
+ }
+ else if (p[0] != 1 || p[1] != 2)
+ g_CrcUpdate = CrcUpdateT1;
else
#endif
{
@@ -78,8 +114,15 @@ void MY_FAST_CALL CrcGenerateTable()
UInt32 x = g_CrcTable[i - 256];
g_CrcTable[i] = CRC_UINT32_SWAP(x);
}
+ g_CrcUpdateT4 = CrcUpdateT1_BeT4;
g_CrcUpdate = CrcUpdateT1_BeT4;
+ #if CRC_NUM_TABLES >= 8
+ g_CrcUpdateT8 = CrcUpdateT1_BeT8;
+ // g_CrcUpdate = CrcUpdateT1_BeT8;
+ #endif
}
}
#endif
+
+ #endif
}
diff --git a/C/7zCrcOpt.c b/C/7zCrcOpt.c
index ce132b5d..d1e1cd7b 100644
--- a/C/7zCrcOpt.c
+++ b/C/7zCrcOpt.c
@@ -1,14 +1,14 @@
/* 7zCrcOpt.c -- CRC32 calculation
-2013-11-12 : Igor Pavlov : Public domain */
+2015-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "CpuArch.h"
-#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
-
#ifndef MY_CPU_BE
+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
+
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
@@ -18,10 +18,10 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
{
v ^= *(const UInt32 *)p;
v =
- table[0x300 + (v & 0xFF)] ^
- table[0x200 + ((v >> 8) & 0xFF)] ^
- table[0x100 + ((v >> 16) & 0xFF)] ^
- table[0x000 + ((v >> 24))];
+ table[0x300 + ((v ) & 0xFF)]
+ ^ table[0x200 + ((v >> 8) & 0xFF)]
+ ^ table[0x100 + ((v >> 16) & 0xFF)]
+ ^ table[0x000 + ((v >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
@@ -30,7 +30,28 @@ UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const U
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
- return CrcUpdateT4(v, data, size, table);
+ const Byte *p = (const Byte *)data;
+ for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
+ v = CRC_UPDATE_BYTE_2(v, *p);
+ for (; size >= 8; size -= 8, p += 8)
+ {
+ UInt32 d;
+ v ^= *(const UInt32 *)p;
+ v =
+ table[0x700 + ((v ) & 0xFF)]
+ ^ table[0x600 + ((v >> 8) & 0xFF)]
+ ^ table[0x500 + ((v >> 16) & 0xFF)]
+ ^ table[0x400 + ((v >> 24))];
+ d = *((const UInt32 *)p + 1);
+ v ^=
+ table[0x300 + ((d ) & 0xFF)]
+ ^ table[0x200 + ((d >> 8) & 0xFF)]
+ ^ table[0x100 + ((d >> 16) & 0xFF)]
+ ^ table[0x000 + ((d >> 24))];
+ }
+ for (; size > 0; size--, p++)
+ v = CRC_UPDATE_BYTE_2(v, *p);
+ return v;
}
#endif
@@ -40,27 +61,55 @@ UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const U
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
+#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))
+
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
- for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
- v = CRC_UPDATE_BYTE_2(v, *p);
- v = CRC_UINT32_SWAP(v);
table += 0x100;
+ v = CRC_UINT32_SWAP(v);
+ for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
+ v = CRC_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 4; size -= 4, p += 4)
{
v ^= *(const UInt32 *)p;
v =
- table[0x000 + (v & 0xFF)] ^
- table[0x100 + ((v >> 8) & 0xFF)] ^
- table[0x200 + ((v >> 16) & 0xFF)] ^
- table[0x300 + ((v >> 24))];
+ table[0x000 + ((v ) & 0xFF)]
+ ^ table[0x100 + ((v >> 8) & 0xFF)]
+ ^ table[0x200 + ((v >> 16) & 0xFF)]
+ ^ table[0x300 + ((v >> 24))];
}
- table -= 0x100;
+ for (; size > 0; size--, p++)
+ v = CRC_UPDATE_BYTE_2_BE(v, *p);
+ return CRC_UINT32_SWAP(v);
+}
+
+UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
+{
+ const Byte *p = (const Byte *)data;
+ table += 0x100;
v = CRC_UINT32_SWAP(v);
+ for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
+ v = CRC_UPDATE_BYTE_2_BE(v, *p);
+ for (; size >= 8; size -= 8, p += 8)
+ {
+ UInt32 d;
+ v ^= *(const UInt32 *)p;
+ v =
+ table[0x400 + ((v ) & 0xFF)]
+ ^ table[0x500 + ((v >> 8) & 0xFF)]
+ ^ table[0x600 + ((v >> 16) & 0xFF)]
+ ^ table[0x700 + ((v >> 24))];
+ d = *((const UInt32 *)p + 1);
+ v ^=
+ table[0x000 + ((d ) & 0xFF)]
+ ^ table[0x100 + ((d >> 8) & 0xFF)]
+ ^ table[0x200 + ((d >> 16) & 0xFF)]
+ ^ table[0x300 + ((d >> 24))];
+ }
for (; size > 0; size--, p++)
- v = CRC_UPDATE_BYTE_2(v, *p);
- return v;
+ v = CRC_UPDATE_BYTE_2_BE(v, *p);
+ return CRC_UINT32_SWAP(v);
}
#endif
diff --git a/C/7zDec.c b/C/7zDec.c
index 2c7c2cd0..1f326137 100644
--- a/C/7zDec.c
+++ b/C/7zDec.c
@@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder
-2014-06-16 : Igor Pavlov : Public domain */
+2015-06-13 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -12,6 +12,7 @@
#include "Bcj2.h"
#include "Bra.h"
#include "CpuArch.h"
+#include "Delta.h"
#include "LzmaDec.h"
#include "Lzma2Dec.h"
#ifdef _7ZIP_PPMD_SUPPPORT
@@ -19,14 +20,17 @@
#endif
#define k_Copy 0
+#define k_Delta 3
#define k_LZMA2 0x21
#define k_LZMA 0x30101
-#define k_BCJ 0x03030103
-#define k_PPC 0x03030205
-#define k_ARM 0x03030501
-#define k_ARMT 0x03030701
-#define k_SPARC 0x03030805
-#define k_BCJ2 0x0303011B
+#define k_BCJ 0x3030103
+#define k_BCJ2 0x303011B
+#define k_PPC 0x3030205
+#define k_IA64 0x3030401
+#define k_ARM 0x3030501
+#define k_ARMT 0x3030701
+#define k_SPARC 0x3030805
+
#ifdef _7ZIP_PPMD_SUPPPORT
@@ -174,6 +178,9 @@ static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, I
return res;
}
+
+#ifndef _7Z_NO_METHOD_LZMA2
+
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
@@ -223,6 +230,9 @@ static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize,
return res;
}
+#endif
+
+
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
{
while (inSize > 0)
@@ -248,7 +258,9 @@ static Bool IS_MAIN_METHOD(UInt32 m)
{
case k_Copy:
case k_LZMA:
+ #ifndef _7Z_NO_METHOD_LZMA2
case k_LZMA2:
+ #endif
#ifdef _7ZIP_PPMD_SUPPPORT
case k_PPMD:
#endif
@@ -260,13 +272,12 @@ static Bool IS_MAIN_METHOD(UInt32 m)
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{
return
- c->NumInStreams == 1 &&
- c->NumOutStreams == 1 &&
- /* c->MethodID <= (UInt32)0xFFFFFFFF && */
- IS_MAIN_METHOD((UInt32)c->MethodID);
+ c->NumStreams == 1
+ /* && c->MethodID <= (UInt32)0xFFFFFFFF */
+ && IS_MAIN_METHOD((UInt32)c->MethodID);
}
-#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
+#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
static SRes CheckSupportedFolder(const CSzFolder *f)
{
@@ -276,51 +287,64 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
return SZ_ERROR_UNSUPPORTED;
if (f->NumCoders == 1)
{
- if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
+ if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
+
+
+ #ifndef _7Z_NO_METHODS_FILTERS
+
if (f->NumCoders == 2)
{
const CSzCoderInfo *c = &f->Coders[1];
if (
/* c->MethodID > (UInt32)0xFFFFFFFF || */
- c->NumInStreams != 1 ||
- c->NumOutStreams != 1 ||
- f->NumPackStreams != 1 ||
- f->PackStreams[0] != 0 ||
- f->NumBindPairs != 1 ||
- f->BindPairs[0].InIndex != 1 ||
- f->BindPairs[0].OutIndex != 0)
+ c->NumStreams != 1
+ || f->NumPackStreams != 1
+ || f->PackStreams[0] != 0
+ || f->NumBonds != 1
+ || f->Bonds[0].InIndex != 1
+ || f->Bonds[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED;
switch ((UInt32)c->MethodID)
{
+ case k_Delta:
case k_BCJ:
+ case k_PPC:
+ case k_IA64:
+ case k_SPARC:
case k_ARM:
+ case k_ARMT:
break;
default:
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK;
}
+
+ #endif
+
+
if (f->NumCoders == 4)
{
- if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
- !IS_SUPPORTED_CODER(&f->Coders[2]) ||
- !IS_BCJ2(&f->Coders[3]))
+ if (!IS_SUPPORTED_CODER(&f->Coders[1])
+ || !IS_SUPPORTED_CODER(&f->Coders[2])
+ || !IS_BCJ2(&f->Coders[3]))
return SZ_ERROR_UNSUPPORTED;
- if (f->NumPackStreams != 4 ||
- f->PackStreams[0] != 2 ||
- f->PackStreams[1] != 6 ||
- f->PackStreams[2] != 1 ||
- f->PackStreams[3] != 0 ||
- f->NumBindPairs != 3 ||
- f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
- f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
- f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
+ if (f->NumPackStreams != 4
+ || f->PackStreams[0] != 2
+ || f->PackStreams[1] != 6
+ || f->PackStreams[2] != 1
+ || f->PackStreams[3] != 0
+ || f->NumBonds != 3
+ || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
+ || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
+ || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
+
return SZ_ERROR_UNSUPPORTED;
}
@@ -364,7 +388,7 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
if (outSizeCur != unpackSize)
return SZ_ERROR_MEM;
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
- if (temp == 0 && outSizeCur != 0)
+ if (!temp && outSizeCur != 0)
return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp;
tempSizes[1 - ci] = outSizeCur;
@@ -393,66 +417,118 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
{
RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
+ #ifndef _7Z_NO_METHOD_LZMA2
else if (coder->MethodID == k_LZMA2)
{
RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
- else
+ #endif
+ #ifdef _7ZIP_PPMD_SUPPPORT
+ else if (coder->MethodID == k_PPMD)
{
- #ifdef _7ZIP_PPMD_SUPPPORT
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
- #else
- return SZ_ERROR_UNSUPPORTED;
- #endif
}
+ #endif
+ else
+ return SZ_ERROR_UNSUPPORTED;
}
else if (coder->MethodID == k_BCJ2)
{
UInt64 offset = packPositions[1];
UInt64 s3Size = packPositions[2] - offset;
- SRes res;
+
if (ci != 3)
return SZ_ERROR_UNSUPPORTED;
- RINOK(LookInStream_SeekTo(inStream, startPos + offset));
+
tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM;
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
- if (tempBuf[2] == 0 && tempSizes[2] != 0)
+ if (!tempBuf[2] && tempSizes[2] != 0)
return SZ_ERROR_MEM;
- res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
- RINOK(res)
-
- res = Bcj2_Decode(
- tempBuf3, tempSize3,
- tempBuf[0], tempSizes[0],
- tempBuf[1], tempSizes[1],
- tempBuf[2], tempSizes[2],
- outBuffer, outSize);
- RINOK(res)
+
+ RINOK(LookInStream_SeekTo(inStream, startPos + offset));
+ RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
+
+ if ((tempSizes[0] & 3) != 0 ||
+ (tempSizes[1] & 3) != 0 ||
+ tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
+ return SZ_ERROR_DATA;
+
+ {
+ CBcj2Dec p;
+
+ p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3;
+ p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
+ p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
+ p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
+
+ p.dest = outBuffer;
+ p.destLim = outBuffer + outSize;
+
+ Bcj2Dec_Init(&p);
+ RINOK(Bcj2Dec_Decode(&p));
+
+ {
+ unsigned i;
+ for (i = 0; i < 4; i++)
+ if (p.bufs[i] != p.lims[i])
+ return SZ_ERROR_DATA;
+
+ if (!Bcj2Dec_IsFinished(&p))
+ return SZ_ERROR_DATA;
+
+ if (p.dest != p.destLim
+ || p.state != BCJ2_STREAM_MAIN)
+ return SZ_ERROR_DATA;
+ }
+ }
}
- else
+ #ifndef _7Z_NO_METHODS_FILTERS
+ else if (ci == 1)
{
- if (ci != 1)
- return SZ_ERROR_UNSUPPORTED;
- switch (coder->MethodID)
+ if (coder->MethodID == k_Delta)
{
- case k_BCJ:
+ if (coder->PropsSize != 1)
+ return SZ_ERROR_UNSUPPORTED;
{
- UInt32 state;
- x86_Convert_Init(state);
- x86_Convert(outBuffer, outSize, 0, &state, 0);
- break;
+ Byte state[DELTA_STATE_SIZE];
+ Delta_Init(state);
+ Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
}
- CASE_BRA_CONV(ARM)
- default:
+ }
+ else
+ {
+ if (coder->PropsSize != 0)
return SZ_ERROR_UNSUPPORTED;
+ switch (coder->MethodID)
+ {
+ case k_BCJ:
+ {
+ UInt32 state;
+ x86_Convert_Init(state);
+ x86_Convert(outBuffer, outSize, 0, &state, 0);
+ break;
+ }
+ CASE_BRA_CONV(PPC)
+ CASE_BRA_CONV(IA64)
+ CASE_BRA_CONV(SPARC)
+ CASE_BRA_CONV(ARM)
+ CASE_BRA_CONV(ARMT)
+ default:
+ return SZ_ERROR_UNSUPPORTED;
+ }
}
}
+ #endif
+ else
+ return SZ_ERROR_UNSUPPORTED;
}
+
return SZ_OK;
}
+
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize,
@@ -477,10 +553,10 @@ SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
if (res != SZ_OK)
return res;
- if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.MainOutStream])
+ if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.UnpackStream])
return SZ_ERROR_FAIL;
{
- int i;
+ unsigned i;
Byte *tempBuf[3] = { 0, 0, 0};
res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes,
p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
diff --git a/C/7zVersion.h b/C/7zVersion.h
index 47591835..a3c2c272 100644
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -1,10 +1,17 @@
-#define MY_VER_MAJOR 9
-#define MY_VER_MINOR 38
+#define MY_VER_MAJOR 15
+#define MY_VER_MINOR 05
#define MY_VER_BUILD 00
-#define MY_VERSION "9.38 beta"
-// #define MY_7ZIP_VERSION "9.38"
-#define MY_DATE "2015-01-03"
+#define MY_VERSION "15.05 beta"
+#define MY_DATE "2015-06-14"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
-#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
-#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
+#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
+#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov"
+
+#ifdef USE_COPYRIGHT_CR
+ #define MY_COPYRIGHT MY_COPYRIGHT_CR
+#else
+ #define MY_COPYRIGHT MY_COPYRIGHT_PD
+#endif
+
+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " : " MY_COPYRIGHT " : " MY_DATE
diff --git a/C/Aes.c b/C/Aes.c
index 6c49dc98..7c100c55 100644
--- a/C/Aes.c
+++ b/C/Aes.c
@@ -1,5 +1,5 @@
/* Aes.c -- AES encryption / decryption
-2013-11-12 : Igor Pavlov : Public domain */
+2015-02-23 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -7,7 +7,7 @@
#include "CpuArch.h"
static UInt32 T[256 * 4];
-static Byte Sbox[256] = {
+static const Byte Sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
@@ -40,7 +40,7 @@ AES_CODE_FUNC g_AesCtr_Code;
static UInt32 D[256 * 4];
static Byte InvS[256];
-static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
+static const Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)
@@ -56,6 +56,7 @@ void AesGenTables(void)
unsigned i;
for (i = 0; i < 256; i++)
InvS[Sbox[i]] = (Byte)i;
+
for (i = 0; i < 256; i++)
{
{
@@ -82,9 +83,11 @@ void AesGenTables(void)
D[0x300 + i] = Ui32(a9, aD, aB, aE);
}
}
+
g_AesCbc_Encode = AesCbc_Encode;
g_AesCbc_Decode = AesCbc_Decode;
g_AesCtr_Code = AesCtr_Code;
+
#ifdef MY_CPU_X86_OR_AMD64
if (CPU_Is_Aes_Supported())
{
@@ -95,34 +98,38 @@ void AesGenTables(void)
#endif
}
+
#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])]
+
#define HT4(m, i, s, p) m[i] = \
HT(i, 0, s) ^ \
HT(i, 1, s) ^ \
HT(i, 2, s) ^ \
HT(i, 3, s) ^ w[p + i]
-/* such order (2031) in HT16 is for VC6/K8 speed optimization) */
+
#define HT16(m, s, p) \
- HT4(m, 2, s, p); \
HT4(m, 0, s, p); \
- HT4(m, 3, s, p); \
HT4(m, 1, s, p); \
+ HT4(m, 2, s, p); \
+ HT4(m, 3, s, p); \
#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])]
#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];
+
#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])]
+
#define HD4(m, i, s, p) m[i] = \
HD(i, 0, s) ^ \
HD(i, 1, s) ^ \
HD(i, 2, s) ^ \
HD(i, 3, s) ^ w[p + i];
-/* such order (0231) in HD16 is for VC6/K8 speed optimization) */
+
#define HD16(m, s, p) \
HD4(m, 0, s, p); \
+ HD4(m, 1, s, p); \
HD4(m, 2, s, p); \
HD4(m, 3, s, p); \
- HD4(m, 1, s, p); \
#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])]
#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];
@@ -169,7 +176,7 @@ void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)
/* Aes_Encode and Aes_Decode functions work with little-endian words.
src and dest are pointers to 4 UInt32 words.
- arc and dest can point to same block */
+ src and dest can point to same block */
static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)
{
@@ -271,13 +278,17 @@ void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)
UInt32 temp[4];
Byte buf[16];
int i;
+
if (++p[0] == 0)
p[1]++;
+
Aes_Encode(p + 4, temp, p);
+
SetUi32(buf, temp[0]);
SetUi32(buf + 4, temp[1]);
SetUi32(buf + 8, temp[2]);
SetUi32(buf + 12, temp[3]);
+
for (i = 0; i < 16; i++)
*data++ ^= buf[i];
}
diff --git a/C/Alloc.c b/C/Alloc.c
index a9a69575..3f6ac419 100644
--- a/C/Alloc.c
+++ b/C/Alloc.c
@@ -1,5 +1,5 @@
/* Alloc.c -- Memory allocation functions
-2013-11-12 : Igor Pavlov : Public domain */
+2015-02-21 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -125,3 +125,12 @@ void BigFree(void *address)
}
#endif
+
+
+static void *SzAlloc(void *p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); }
+static void SzFree(void *p, void *address) { UNUSED_VAR(p); MyFree(address); }
+ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+static void *SzBigAlloc(void *p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); }
+static void SzBigFree(void *p, void *address) { UNUSED_VAR(p); BigFree(address); }
+ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
diff --git a/C/Alloc.h b/C/Alloc.h
index b8e41436..bac0d87e 100644
--- a/C/Alloc.h
+++ b/C/Alloc.h
@@ -1,14 +1,12 @@
/* Alloc.h -- Memory allocation functions
-2009-02-07 : Igor Pavlov : Public domain */
+2015-02-21 : Igor Pavlov : Public domain */
#ifndef __COMMON_ALLOC_H
#define __COMMON_ALLOC_H
-#include <stddef.h>
+#include "7zTypes.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+EXTERN_C_BEGIN
void *MyAlloc(size_t size);
void MyFree(void *address);
@@ -31,8 +29,9 @@ void BigFree(void *address);
#endif
-#ifdef __cplusplus
-}
-#endif
+extern ISzAlloc g_Alloc;
+extern ISzAlloc g_BigAlloc;
+
+EXTERN_C_END
#endif
diff --git a/C/Bcj2.c b/C/Bcj2.c
index 4e81cdc2..371a9e6e 100644
--- a/C/Bcj2.c
+++ b/C/Bcj2.c
@@ -1,134 +1,256 @@
-/* Bcj2.c -- Converter for x86 code (BCJ2)
-2008-10-04 : Igor Pavlov : Public domain */
+/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
+2014-11-09 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Bcj2.h"
+#include "CpuArch.h"
-#ifdef _LZMA_PROB32
-#define CProb UInt32
-#else
#define CProb UInt16
-#endif
-#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
-#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
-
-#define kNumTopBits 24
-#define kTopValue ((UInt32)1 << kNumTopBits)
-
-#define kNumBitModelTotalBits 11
-#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kTopValue ((UInt32)1 << 24)
+#define kNumModelBits 11
+#define kBitModelTotal (1 << kNumModelBits)
#define kNumMoveBits 5
-#define RC_READ_BYTE (*buffer++)
-#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
-#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
- { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
-
-#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
+#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
+#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
-#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
-#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
-#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
-
-int Bcj2_Decode(
- const Byte *buf0, SizeT size0,
- const Byte *buf1, SizeT size1,
- const Byte *buf2, SizeT size2,
- const Byte *buf3, SizeT size3,
- Byte *outBuf, SizeT outSize)
+void Bcj2Dec_Init(CBcj2Dec *p)
{
- CProb p[256 + 2];
- SizeT inPos = 0, outPos = 0;
-
- const Byte *buffer, *bufferLim;
- UInt32 range, code;
- Byte prevByte = 0;
-
- unsigned int i;
- for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
- p[i] = kBitModelTotal >> 1;
+ unsigned i;
- buffer = buf3;
- bufferLim = buffer + size3;
- RC_INIT2
+ p->state = BCJ2_DEC_STATE_OK;
+ p->ip = 0;
+ p->temp[3] = 0;
+ p->range = 0;
+ p->code = 0;
+ for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
+ p->probs[i] = kBitModelTotal >> 1;
+}
- if (outSize == 0)
- return SZ_OK;
+SRes Bcj2Dec_Decode(CBcj2Dec *p)
+{
+ if (p->range <= 5)
+ {
+ p->state = BCJ2_DEC_STATE_OK;
+ for (; p->range != 5; p->range++)
+ {
+ if (p->range == 1 && p->code != 0)
+ return SZ_ERROR_DATA;
+
+ if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
+ {
+ p->state = BCJ2_STREAM_RC;
+ return SZ_OK;
+ }
- for (;;)
+ p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
+ }
+
+ if (p->code == 0xFFFFFFFF)
+ return SZ_ERROR_DATA;
+
+ p->range = 0xFFFFFFFF;
+ }
+ else if (p->state >= BCJ2_DEC_STATE_ORIG_0)
{
- Byte b;
- CProb *prob;
- UInt32 bound;
- UInt32 ttt;
-
- SizeT limit = size0 - inPos;
- if (outSize - outPos < limit)
- limit = outSize - outPos;
- while (limit != 0)
+ while (p->state <= BCJ2_DEC_STATE_ORIG_3)
{
- Byte b = buf0[inPos];
- outBuf[outPos++] = b;
- if (IsJ(prevByte, b))
- break;
- inPos++;
- prevByte = b;
- limit--;
+ Byte *dest = p->dest;
+ if (dest == p->destLim)
+ return SZ_OK;
+ *dest = p->temp[p->state++ - BCJ2_DEC_STATE_ORIG_0];
+ p->dest = dest + 1;
}
+ }
- if (limit == 0 || outPos == outSize)
- break;
-
- b = buf0[inPos++];
-
- if (b == 0xE8)
- prob = p + prevByte;
- else if (b == 0xE9)
- prob = p + 256;
- else
- prob = p + 257;
-
- IF_BIT_0(prob)
+ /*
+ if (BCJ2_IS_32BIT_STREAM(p->state))
+ {
+ const Byte *cur = p->bufs[p->state];
+ if (cur == p->lims[p->state])
+ return SZ_OK;
+ p->bufs[p->state] = cur + 4;
+
{
- UPDATE_0(prob)
- prevByte = b;
+ UInt32 val;
+ Byte *dest;
+ SizeT rem;
+
+ p->ip += 4;
+ val = GetBe32(cur) - p->ip;
+ dest = p->dest;
+ rem = p->destLim - dest;
+ if (rem < 4)
+ {
+ SizeT i;
+ SetUi32(p->temp, val);
+ for (i = 0; i < rem; i++)
+ dest[i] = p->temp[i];
+ p->dest = dest + rem;
+ p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
+ return SZ_OK;
+ }
+ SetUi32(dest, val);
+ p->temp[3] = (Byte)(val >> 24);
+ p->dest = dest + 4;
+ p->state = BCJ2_DEC_STATE_OK;
}
+ }
+ */
+
+ for (;;)
+ {
+ if (BCJ2_IS_32BIT_STREAM(p->state))
+ p->state = BCJ2_DEC_STATE_OK;
else
{
- UInt32 dest;
- const Byte *v;
- UPDATE_1(prob)
- if (b == 0xE8)
+ if (p->range < kTopValue)
{
- v = buf1;
- if (size1 < 4)
- return SZ_ERROR_DATA;
- buf1 += 4;
- size1 -= 4;
+ if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
+ {
+ p->state = BCJ2_STREAM_RC;
+ return SZ_OK;
+ }
+ p->range <<= 8;
+ p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
}
- else
+
{
- v = buf2;
- if (size2 < 4)
- return SZ_ERROR_DATA;
- buf2 += 4;
- size2 -= 4;
+ const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
+ const Byte *srcLim;
+ Byte *dest;
+ SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
+
+ if (num == 0)
+ {
+ p->state = BCJ2_STREAM_MAIN;
+ return SZ_OK;
+ }
+
+ dest = p->dest;
+ if (num > (SizeT)(p->destLim - dest))
+ {
+ num = p->destLim - dest;
+ if (num == 0)
+ {
+ p->state = BCJ2_DEC_STATE_ORIG;
+ return SZ_OK;
+ }
+ }
+
+ srcLim = src + num;
+
+ if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)
+ *dest = src[0];
+ else for (;;)
+ {
+ Byte b = *src;
+ *dest = b;
+ if (b != 0x0F)
+ {
+ if ((b & 0xFE) == 0xE8)
+ break;
+ dest++;
+ if (++src != srcLim)
+ continue;
+ break;
+ }
+ dest++;
+ if (++src == srcLim)
+ break;
+ if ((*src & 0xF0) != 0x80)
+ continue;
+ *dest = *src;
+ break;
+ }
+
+ num = src - p->bufs[BCJ2_STREAM_MAIN];
+
+ if (src == srcLim)
+ {
+ p->temp[3] = src[-1];
+ p->bufs[BCJ2_STREAM_MAIN] = src;
+ p->ip += (UInt32)num;
+ p->dest += num;
+ p->state =
+ p->bufs[BCJ2_STREAM_MAIN] ==
+ p->lims[BCJ2_STREAM_MAIN] ?
+ BCJ2_STREAM_MAIN :
+ BCJ2_DEC_STATE_ORIG;
+ return SZ_OK;
+ }
+
+ {
+ UInt32 bound, ttt;
+ CProb *prob;
+ Byte b = src[0];
+ Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);
+
+ p->temp[3] = b;
+ p->bufs[BCJ2_STREAM_MAIN] = src + 1;
+ num++;
+ p->ip += (UInt32)num;
+ p->dest += num;
+
+ prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));
+
+ _IF_BIT_0
+ {
+ _UPDATE_0
+ continue;
+ }
+ _UPDATE_1
+
+ }
}
- dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
- ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
- outBuf[outPos++] = (Byte)dest;
- if (outPos == outSize)
- break;
- outBuf[outPos++] = (Byte)(dest >> 8);
- if (outPos == outSize)
+ }
+
+ {
+ UInt32 val;
+ unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
+ const Byte *cur = p->bufs[cj];
+ Byte *dest;
+ SizeT rem;
+
+ if (cur == p->lims[cj])
+ {
+ p->state = cj;
break;
- outBuf[outPos++] = (Byte)(dest >> 16);
- if (outPos == outSize)
+ }
+
+ val = GetBe32(cur);
+ p->bufs[cj] = cur + 4;
+
+ p->ip += 4;
+ val -= p->ip;
+ dest = p->dest;
+ rem = p->destLim - dest;
+
+ if (rem < 4)
+ {
+ SizeT i;
+ SetUi32(p->temp, val);
+ for (i = 0; i < rem; i++)
+ dest[i] = p->temp[i];
+ p->dest = dest + rem;
+ p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
break;
- outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
+ }
+
+ SetUi32(dest, val);
+ p->temp[3] = (Byte)(val >> 24);
+ p->dest = dest + 4;
}
}
- return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
+
+ if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
+ {
+ p->range <<= 8;
+ p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
+ }
+
+ return SZ_OK;
}
diff --git a/C/Bcj2.h b/C/Bcj2.h
index 1db8ea0a..8824080a 100644
--- a/C/Bcj2.h
+++ b/C/Bcj2.h
@@ -1,5 +1,5 @@
-/* Bcj2.h -- Converter for x86 code (BCJ2)
-2013-01-18 : Igor Pavlov : Public domain */
+/* Bcj2.h -- BCJ2 Converter for x86 code
+2014-11-10 : Igor Pavlov : Public domain */
#ifndef __BCJ2_H
#define __BCJ2_H
@@ -8,26 +8,138 @@
EXTERN_C_BEGIN
-/*
-Conditions:
- outSize <= FullOutputSize,
- where FullOutputSize is full size of output stream of x86_2 filter.
+#define BCJ2_NUM_STREAMS 4
+
+enum
+{
+ BCJ2_STREAM_MAIN,
+ BCJ2_STREAM_CALL,
+ BCJ2_STREAM_JUMP,
+ BCJ2_STREAM_RC
+};
+
+enum
+{
+ BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
+ BCJ2_DEC_STATE_ORIG_1,
+ BCJ2_DEC_STATE_ORIG_2,
+ BCJ2_DEC_STATE_ORIG_3,
+
+ BCJ2_DEC_STATE_ORIG,
+ BCJ2_DEC_STATE_OK
+};
+
+enum
+{
+ BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
+ BCJ2_ENC_STATE_OK
+};
-If buf0 overlaps outBuf, there are two required conditions:
- 1) (buf0 >= outBuf)
- 2) (buf0 + size0 >= outBuf + FullOutputSize).
-Returns:
- SZ_OK
- SZ_ERROR_DATA - Data error
+#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)
+
+/*
+CBcj2Dec / CBcj2Enc
+bufs sizes:
+ BUF_SIZE(n) = lims[n] - bufs[n]
+bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:
+ (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
+ (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
*/
-int Bcj2_Decode(
- const Byte *buf0, SizeT size0,
- const Byte *buf1, SizeT size1,
- const Byte *buf2, SizeT size2,
- const Byte *buf3, SizeT size3,
- Byte *outBuf, SizeT outSize);
+/*
+CBcj2Dec:
+dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
+ bufs[BCJ2_STREAM_MAIN] >= dest &&
+ bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +
+ BUF_SIZE(BCJ2_STREAM_CALL) +
+ BUF_SIZE(BCJ2_STREAM_JUMP)
+ tempReserv = 0 : for first call of Bcj2Dec_Decode
+ tempReserv = 4 : for any other calls of Bcj2Dec_Decode
+ overlap with offset = 1 is not allowed
+*/
+
+typedef struct
+{
+ const Byte *bufs[BCJ2_NUM_STREAMS];
+ const Byte *lims[BCJ2_NUM_STREAMS];
+ Byte *dest;
+ const Byte *destLim;
+
+ unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
+
+ UInt32 ip;
+ Byte temp[4];
+ UInt32 range;
+ UInt32 code;
+ UInt16 probs[2 + 256];
+} CBcj2Dec;
+
+void Bcj2Dec_Init(CBcj2Dec *p);
+
+/* Returns: SZ_OK or SZ_ERROR_DATA */
+SRes Bcj2Dec_Decode(CBcj2Dec *p);
+
+#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0)
+
+
+
+typedef enum
+{
+ BCJ2_ENC_FINISH_MODE_CONTINUE,
+ BCJ2_ENC_FINISH_MODE_END_BLOCK,
+ BCJ2_ENC_FINISH_MODE_END_STREAM
+} EBcj2Enc_FinishMode;
+
+typedef struct
+{
+ Byte *bufs[BCJ2_NUM_STREAMS];
+ const Byte *lims[BCJ2_NUM_STREAMS];
+ const Byte *src;
+ const Byte *srcLim;
+
+ unsigned state;
+ EBcj2Enc_FinishMode finishMode;
+
+ Byte prevByte;
+
+ Byte cache;
+ UInt32 range;
+ UInt64 low;
+ UInt64 cacheSize;
+
+ UInt32 ip;
+
+ /* 32-bit ralative offset in JUMP/CALL commands is
+ - (mod 4 GB) in 32-bit mode
+ - signed Int32 in 64-bit mode
+ We use (mod 4 GB) check for fileSize.
+ Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */
+ UInt32 fileIp;
+ UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */
+ UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */
+
+ UInt32 tempTarget;
+ unsigned tempPos;
+ Byte temp[4 * 2];
+
+ unsigned flushPos;
+
+ UInt16 probs[2 + 256];
+} CBcj2Enc;
+
+void Bcj2Enc_Init(CBcj2Enc *p);
+void Bcj2Enc_Encode(CBcj2Enc *p);
+
+#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos)
+#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5)
+
+
+#define BCJ2_RELAT_LIMIT_NUM_BITS 26
+#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS)
+
+/* limit for CBcj2Enc::fileSize variable */
+#define BCJ2_FileSize_MAX ((UInt32)1 << 31)
EXTERN_C_END
diff --git a/C/Bcj2Enc.c b/C/Bcj2Enc.c
new file mode 100644
index 00000000..0ea36462
--- /dev/null
+++ b/C/Bcj2Enc.c
@@ -0,0 +1,312 @@
+/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
+2014-11-10 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+/* #define SHOW_STAT */
+
+#ifdef SHOW_STAT
+#include <stdio.h>
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+#include <windows.h>
+#include <string.h>
+
+#include "Bcj2.h"
+#include "CpuArch.h"
+
+#define CProb UInt16
+
+#define kTopValue ((UInt32)1 << 24)
+#define kNumModelBits 11
+#define kBitModelTotal (1 << kNumModelBits)
+#define kNumMoveBits 5
+
+void Bcj2Enc_Init(CBcj2Enc *p)
+{
+ unsigned i;
+
+ p->state = BCJ2_ENC_STATE_OK;
+ p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
+
+ p->prevByte = 0;
+
+ p->cache = 0;
+ p->range = 0xFFFFFFFF;
+ p->low = 0;
+ p->cacheSize = 1;
+
+ p->ip = 0;
+
+ p->fileIp = 0;
+ p->fileSize = 0;
+ p->relatLimit = BCJ2_RELAT_LIMIT;
+
+ p->tempPos = 0;
+
+ p->flushPos = 0;
+
+ for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
+ p->probs[i] = kBitModelTotal >> 1;
+}
+
+static Bool MY_FAST_CALL RangeEnc_ShiftLow(CBcj2Enc *p)
+{
+ if ((UInt32)p->low < (UInt32)0xFF000000 || (UInt32)(p->low >> 32) != 0)
+ {
+ Byte *buf = p->bufs[BCJ2_STREAM_RC];
+ do
+ {
+ if (buf == p->lims[BCJ2_STREAM_RC])
+ {
+ p->state = BCJ2_STREAM_RC;
+ p->bufs[BCJ2_STREAM_RC] = buf;
+ return True;
+ }
+ *buf++ = (Byte)(p->cache + (Byte)(p->low >> 32));
+ p->cache = 0xFF;
+ }
+ while (--p->cacheSize);
+ p->bufs[BCJ2_STREAM_RC] = buf;
+ p->cache = (Byte)((UInt32)p->low >> 24);
+ }
+ p->cacheSize++;
+ p->low = (UInt32)p->low << 8;
+ return False;
+}
+
+static void Bcj2Enc_Encode_2(CBcj2Enc *p)
+{
+ if (BCJ2_IS_32BIT_STREAM(p->state))
+ {
+ Byte *cur = p->bufs[p->state];
+ if (cur == p->lims[p->state])
+ return;
+ SetBe32(cur, p->tempTarget);
+ p->bufs[p->state] = cur + 4;
+ }
+
+ p->state = BCJ2_ENC_STATE_ORIG;
+
+ for (;;)
+ {
+ if (p->range < kTopValue)
+ {
+ if (RangeEnc_ShiftLow(p))
+ return;
+ p->range <<= 8;
+ }
+
+ {
+ {
+ const Byte *src = p->src;
+ const Byte *srcLim;
+ Byte *dest;
+ SizeT num = p->srcLim - src;
+
+ if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE)
+ {
+ if (num <= 4)
+ return;
+ num -= 4;
+ }
+ else if (num == 0)
+ break;
+
+ dest = p->bufs[BCJ2_STREAM_MAIN];
+ if (num > (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest))
+ {
+ num = p->lims[BCJ2_STREAM_MAIN] - dest;
+ if (num == 0)
+ {
+ p->state = BCJ2_STREAM_MAIN;
+ return;
+ }
+ }
+
+ srcLim = src + num;
+
+ if (p->prevByte == 0x0F && (src[0] & 0xF0) == 0x80)
+ *dest = src[0];
+ else for (;;)
+ {
+ Byte b = *src;
+ *dest = b;
+ if (b != 0x0F)
+ {
+ if ((b & 0xFE) == 0xE8)
+ break;
+ dest++;
+ if (++src != srcLim)
+ continue;
+ break;
+ }
+ dest++;
+ if (++src == srcLim)
+ break;
+ if ((*src & 0xF0) != 0x80)
+ continue;
+ *dest = *src;
+ break;
+ }
+
+ num = src - p->src;
+
+ if (src == srcLim)
+ {
+ p->prevByte = src[-1];
+ p->bufs[BCJ2_STREAM_MAIN] = dest;
+ p->src = src;
+ p->ip += (UInt32)num;
+ continue;
+ }
+
+ {
+ Byte context = (Byte)(num == 0 ? p->prevByte : src[-1]);
+ Bool needConvert;
+
+ p->bufs[BCJ2_STREAM_MAIN] = dest + 1;
+ p->ip += (UInt32)num + 1;
+ src++;
+
+ needConvert = False;
+
+ if ((SizeT)(p->srcLim - src) >= 4)
+ {
+ UInt32 relatVal = GetUi32(src);
+ if ((p->fileSize == 0 || (UInt32)(p->ip + 4 + relatVal - p->fileIp) < p->fileSize)
+ && ((relatVal + p->relatLimit) >> 1) < p->relatLimit)
+ needConvert = True;
+ }
+
+ {
+ UInt32 bound;
+ unsigned ttt;
+ Byte b = src[-1];
+ CProb *prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)context : (b == 0xE9 ? 1 : 0));
+
+ ttt = *prob;
+ bound = (p->range >> kNumModelBits) * ttt;
+
+ if (!needConvert)
+ {
+ p->range = bound;
+ *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+ p->src = src;
+ p->prevByte = b;
+ continue;
+ }
+
+ p->low += bound;
+ p->range -= bound;
+ *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
+
+ {
+ UInt32 relatVal = GetUi32(src);
+ UInt32 absVal;
+ p->ip += 4;
+ absVal = p->ip + relatVal;
+ p->prevByte = src[3];
+ src += 4;
+ p->src = src;
+ {
+ unsigned cj = (b == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
+ Byte *cur = p->bufs[cj];
+ if (cur == p->lims[cj])
+ {
+ p->state = cj;
+ p->tempTarget = absVal;
+ return;
+ }
+ SetBe32(cur, absVal);
+ p->bufs[cj] = cur + 4;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM)
+ return;
+
+ for (; p->flushPos < 5; p->flushPos++)
+ if (RangeEnc_ShiftLow(p))
+ return;
+ p->state = BCJ2_ENC_STATE_OK;
+}
+
+
+void Bcj2Enc_Encode(CBcj2Enc *p)
+{
+ PRF(printf("\n"));
+ PRF(printf("---- ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
+
+ if (p->tempPos != 0)
+ {
+ unsigned extra = 0;
+
+ for (;;)
+ {
+ const Byte *src = p->src;
+ const Byte *srcLim = p->srcLim;
+ unsigned finishMode = p->finishMode;
+
+ p->src = p->temp;
+ p->srcLim = p->temp + p->tempPos;
+ if (src != srcLim)
+ p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
+
+ PRF(printf(" ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
+
+ Bcj2Enc_Encode_2(p);
+
+ {
+ unsigned num = (unsigned)(p->src - p->temp);
+ unsigned tempPos = p->tempPos - num;
+ unsigned i;
+ p->tempPos = tempPos;
+ for (i = 0; i < tempPos; i++)
+ p->temp[i] = p->temp[i + num];
+
+ p->src = src;
+ p->srcLim = srcLim;
+ p->finishMode = finishMode;
+
+ if (p->state != BCJ2_ENC_STATE_ORIG || src == srcLim)
+ return;
+
+ if (extra >= tempPos)
+ {
+ p->src = src - tempPos;
+ p->tempPos = 0;
+ break;
+ }
+
+ p->temp[tempPos] = src[0];
+ p->tempPos = tempPos + 1;
+ p->src = src + 1;
+ extra++;
+ }
+ }
+ }
+
+ PRF(printf("++++ ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src));
+
+ Bcj2Enc_Encode_2(p);
+
+ if (p->state == BCJ2_ENC_STATE_ORIG)
+ {
+ const Byte *src = p->src;
+ unsigned rem = (unsigned)(p->srcLim - src);
+ unsigned i;
+ for (i = 0; i < rem; i++)
+ p->temp[i] = src[i];
+ p->tempPos = rem;
+ p->src = src + rem;
+ }
+}
diff --git a/C/Compiler.h b/C/Compiler.h
index 6e964897..5c53d5b6 100644
--- a/C/Compiler.h
+++ b/C/Compiler.h
@@ -1,5 +1,5 @@
-/* Compiler.h -- Compiler ypes
-2013-11-12 : Igor Pavlov : Public domain */
+/* Compiler.h
+2015-03-25 : Igor Pavlov : Public domain */
#ifndef __7Z_COMPILER_H
#define __7Z_COMPILER_H
@@ -25,4 +25,7 @@
#endif
+#define UNUSED_VAR(x) (void)x;
+/* #define UNUSED_VAR(x) x=x; */
+
#endif
diff --git a/C/CpuArch.c b/C/CpuArch.c
index d7f8b1d8..36fc5bb4 100644
--- a/C/CpuArch.c
+++ b/C/CpuArch.c
@@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code
-2012-05-29: Igor Pavlov : Public domain */
+2015-03-25: Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -54,7 +54,7 @@ static UInt32 CheckFlag(UInt32 flag)
#define CHECK_CPUID_IS_SUPPORTED
#endif
-static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
+void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
#ifdef USE_ASM
@@ -116,7 +116,7 @@ Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
return True;
}
-static UInt32 kVendors[][3] =
+static const UInt32 kVendors[][3] =
{
{ 0x756E6547, 0x49656E69, 0x6C65746E},
{ 0x68747541, 0x69746E65, 0x444D4163},
@@ -144,18 +144,21 @@ Bool CPU_Is_InOrder()
UInt32 family, model;
if (!x86cpuid_CheckAndRead(&p))
return True;
- family = x86cpuid_GetFamily(&p);
- model = x86cpuid_GetModel(&p);
+
+ family = x86cpuid_GetFamily(p.ver);
+ model = x86cpuid_GetModel(p.ver);
+
firm = x86cpuid_GetFirm(&p);
+
switch (firm)
{
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
- /* Atom CPU */
- model == 0x100C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
- || model == 0x2006 /* 45 nm, Z6xx */
- || model == 0x2007 /* 32 nm, Z2460 */
- || model == 0x3005 /* 32 nm, Z2760 */
- || model == 0x3006 /* 32 nm, N2xxx, D2xxx */
+ /* In-Order Atom CPU */
+ model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
+ || model == 0x26 /* 45 nm, Z6xx */
+ || model == 0x27 /* 32 nm, Z2460 */
+ || model == 0x35 /* 32 nm, Z2760 */
+ || model == 0x36 /* 32 nm, N2xxx, D2xxx */
)));
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
diff --git a/C/CpuArch.h b/C/CpuArch.h
index 4fee0093..38835189 100644
--- a/C/CpuArch.h
+++ b/C/CpuArch.h
@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
-2013-11-12: Igor Pavlov : Public domain */
+2015-03-25: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
@@ -20,8 +20,11 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_AMD64
#endif
-#if defined(MY_CPU_AMD64) || defined(_M_IA64)
-#define MY_CPU_64BIT
+#if defined(MY_CPU_AMD64) \
+ || defined(_M_IA64) \
+ || defined(__AARCH64EL__) \
+ || defined(__AARCH64EB__)
+ #define MY_CPU_64BIT
#endif
#if defined(_M_IX86) || defined(__i386__)
@@ -32,8 +35,13 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_X86_OR_AMD64
#endif
-#if defined(MY_CPU_X86) || defined(_M_ARM)
-#define MY_CPU_32BIT
+#if defined(MY_CPU_X86) \
+ || defined(_M_ARM) \
+ || defined(__ARMEL__) \
+ || defined(__THUMBEL__) \
+ || defined(__ARMEB__) \
+ || defined(__THUMBEB__)
+ #define MY_CPU_32BIT
#endif
#if defined(_WIN32) && defined(_M_ARM)
@@ -48,30 +56,49 @@ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of pla
#define MY_CPU_LE_UNALIGN
#endif
-#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
-#define MY_CPU_LE
+#if defined(MY_CPU_X86_OR_AMD64) \
+ || defined(MY_CPU_ARM_LE) \
+ || defined(MY_CPU_IA64_LE) \
+ || defined(__LITTLE_ENDIAN__) \
+ || defined(__ARMEL__) \
+ || defined(__THUMBEL__) \
+ || defined(__AARCH64EL__) \
+ || defined(__MIPSEL__) \
+ || defined(__MIPSEL) \
+ || defined(_MIPSEL)
+ #define MY_CPU_LE
#endif
-#if defined(__BIG_ENDIAN__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__)
-#define MY_CPU_BE
+#if defined(__BIG_ENDIAN__) \
+ || defined(__ARMEB__) \
+ || defined(__THUMBEB__) \
+ || defined(__AARCH64EB__) \
+ || defined(__MIPSEB__) \
+ || defined(__MIPSEB) \
+ || defined(_MIPSEB) \
+ || defined(__m68k__)
+ #define MY_CPU_BE
#endif
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
Stop_Compiling_Bad_Endian
#endif
+
#ifdef MY_CPU_LE_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
-#define SetUi16(p, d) *(UInt16 *)(p) = (d);
-#define SetUi32(p, d) *(UInt32 *)(p) = (d);
-#define SetUi64(p, d) *(UInt64 *)(p) = (d);
+#define SetUi16(p, v) *(UInt16 *)(p) = (v);
+#define SetUi32(p, v) *(UInt32 *)(p) = (v);
+#define SetUi64(p, v) *(UInt64 *)(p) = (v);
#else
-#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
+#define GetUi16(p) ( (UInt16) ( \
+ ((const Byte *)(p))[0] | \
+ ((UInt16)((const Byte *)(p))[1] << 8) ))
#define GetUi32(p) ( \
((const Byte *)(p))[0] | \
@@ -81,23 +108,24 @@ Stop_Compiling_Bad_Endian
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
-#define SetUi16(p, d) { UInt32 _x_ = (d); \
- ((Byte *)(p))[0] = (Byte)_x_; \
- ((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
+#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
+ _ppp_[0] = (Byte)_vvv_; \
+ _ppp_[1] = (Byte)(_vvv_ >> 8); }
-#define SetUi32(p, d) { UInt32 _x_ = (d); \
- ((Byte *)(p))[0] = (Byte)_x_; \
- ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
- ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
- ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
+#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
+ _ppp_[0] = (Byte)_vvv_; \
+ _ppp_[1] = (Byte)(_vvv_ >> 8); \
+ _ppp_[2] = (Byte)(_vvv_ >> 16); \
+ _ppp_[3] = (Byte)(_vvv_ >> 24); }
-#define SetUi64(p, d) { UInt64 _x64_ = (d); \
- SetUi32(p, (UInt32)_x64_); \
- SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
+#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
+ SetUi32(_ppp2_ , (UInt32)_vvv2_); \
+ SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
#endif
-#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
+
+#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
#include <stdlib.h>
@@ -106,6 +134,8 @@ Stop_Compiling_Bad_Endian
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
+#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
+
#else
#define GetBe32(p) ( \
@@ -116,9 +146,19 @@ Stop_Compiling_Bad_Endian
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
+#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
+ _ppp_[0] = (Byte)(_vvv_ >> 24); \
+ _ppp_[1] = (Byte)(_vvv_ >> 16); \
+ _ppp_[2] = (Byte)(_vvv_ >> 8); \
+ _ppp_[3] = (Byte)_vvv_; }
+
#endif
-#define GetBe16(p) ((UInt16)(((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]))
+
+#define GetBe16(p) ( (UInt16) ( \
+ ((UInt16)((const Byte *)(p))[0] << 8) | \
+ ((const Byte *)(p))[1] ))
+
#ifdef MY_CPU_X86_OR_AMD64
@@ -140,12 +180,14 @@ enum
CPU_FIRM_VIA
};
+void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
+
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p);
-#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
-#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
-#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
+#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
+#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
+#define x86cpuid_GetStepping(ver) (ver & 0xF)
Bool CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported();
diff --git a/C/LzFind.c b/C/LzFind.c
index 262b395b..fbb6cdb2 100644
--- a/C/LzFind.c
+++ b/C/LzFind.c
@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms
-2009-04-22 : Igor Pavlov : Public domain */
+2015-05-15 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -12,7 +12,7 @@
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
#define kNormalizeMask (~(kNormalizeStepMin - 1))
-#define kMaxHistorySize ((UInt32)3 << 30)
+#define kMaxHistorySize ((UInt32)7 << 29)
#define kStartMaxLen 3
@@ -21,7 +21,7 @@ static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
if (!p->directInput)
{
alloc->Free(alloc, p->bufferBase);
- p->bufferBase = 0;
+ p->bufferBase = NULL;
}
}
@@ -35,17 +35,16 @@ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *a
p->blockSize = blockSize;
return 1;
}
- if (p->bufferBase == 0 || p->blockSize != blockSize)
+ if (!p->bufferBase || p->blockSize != blockSize)
{
LzInWindow_Free(p, alloc);
p->blockSize = blockSize;
p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
}
- return (p->bufferBase != 0);
+ return (p->bufferBase != NULL);
}
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
-Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
@@ -60,6 +59,7 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
{
if (p->streamEndWasReached || p->result != SZ_OK)
return;
+
if (p->directInput)
{
UInt32 curSize = 0xFFFFFFFF - p->streamPos;
@@ -71,12 +71,14 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
p->streamEndWasReached = 1;
return;
}
+
for (;;)
{
Byte *dest = p->buffer + (p->streamPos - p->pos);
size_t size = (p->bufferBase + p->blockSize - dest);
if (size == 0)
return;
+
p->result = p->stream->Read(p->stream, dest, &size);
if (p->result != SZ_OK)
return;
@@ -94,8 +96,8 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
void MatchFinder_MoveBlock(CMatchFinder *p)
{
memmove(p->bufferBase,
- p->buffer - p->keepSizeBefore,
- (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
+ p->buffer - p->keepSizeBefore,
+ (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
p->buffer = p->bufferBase + p->keepSizeBefore;
}
@@ -135,15 +137,15 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
void MatchFinder_Construct(CMatchFinder *p)
{
UInt32 i;
- p->bufferBase = 0;
+ p->bufferBase = NULL;
p->directInput = 0;
- p->hash = 0;
+ p->hash = NULL;
MatchFinder_SetDefaultSettings(p);
for (i = 0; i < 256; i++)
{
UInt32 r = i;
- int j;
+ unsigned j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
p->crc[i] = r;
@@ -153,7 +155,7 @@ void MatchFinder_Construct(CMatchFinder *p)
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->hash);
- p->hash = 0;
+ p->hash = NULL;
}
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
@@ -162,11 +164,11 @@ void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
LzInWindow_Free(p, alloc);
}
-static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
+static CLzRef* AllocRefs(size_t num, ISzAlloc *alloc)
{
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
if (sizeInBytes / sizeof(CLzRef) != num)
- return 0;
+ return NULL;
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
}
@@ -175,19 +177,24 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
ISzAlloc *alloc)
{
UInt32 sizeReserv;
+
if (historySize > kMaxHistorySize)
{
MatchFinder_Free(p, alloc);
return 0;
}
+
sizeReserv = historySize >> 1;
- if (historySize > ((UInt32)2 << 30))
- sizeReserv = historySize >> 2;
+ if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3;
+ else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2;
+
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+
if (LzInWindow_Create(p, sizeReserv, alloc))
{
UInt32 newCyclicBufferSize = historySize + 1;
@@ -212,6 +219,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
hs = (1 << 24) - 1;
else
hs >>= 1;
+ /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
}
}
p->hashMask = hs;
@@ -223,24 +231,32 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
}
{
- UInt32 prevSize = p->hashSizeSum + p->numSons;
- UInt32 newSize;
+ size_t newSize;
+ size_t numSons;
p->historySize = historySize;
p->hashSizeSum = hs;
p->cyclicBufferSize = newCyclicBufferSize;
- p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
- newSize = p->hashSizeSum + p->numSons;
- if (p->hash != 0 && prevSize == newSize)
+
+ numSons = newCyclicBufferSize;
+ if (p->btMode)
+ numSons <<= 1;
+ newSize = hs + numSons;
+
+ if (p->hash && p->numRefs == newSize)
return 1;
+
MatchFinder_FreeThisClassMemory(p, alloc);
+ p->numRefs = newSize;
p->hash = AllocRefs(newSize, alloc);
- if (p->hash != 0)
+
+ if (p->hash)
{
p->son = p->hash + p->hashSizeSum;
return 1;
}
}
}
+
MatchFinder_Free(p, alloc);
return 0;
}
@@ -249,9 +265,11 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
{
UInt32 limit = kMaxValForNormalize - p->pos;
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
+
if (limit2 < limit)
limit = limit2;
limit2 = p->streamPos - p->pos;
+
if (limit2 <= p->keepSizeAfter)
{
if (limit2 > 0)
@@ -259,8 +277,10 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
}
else
limit2 -= p->keepSizeAfter;
+
if (limit2 < limit)
limit = limit2;
+
{
UInt32 lenLimit = p->streamPos - p->pos;
if (lenLimit > p->matchMaxLen)
@@ -273,8 +293,11 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
void MatchFinder_Init(CMatchFinder *p)
{
UInt32 i;
- for (i = 0; i < p->hashSizeSum; i++)
- p->hash[i] = kEmptyHashValue;
+ UInt32 *hash = p->hash;
+ UInt32 num = p->hashSizeSum;
+ for (i = 0; i < num; i++)
+ hash[i] = kEmptyHashValue;
+
p->cyclicBufferPos = 0;
p->buffer = p->bufferBase;
p->pos = p->streamPos = p->cyclicBufferSize;
@@ -289,9 +312,9 @@ static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
return (p->pos - p->historySize - 1) & kNormalizeMask;
}
-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)
{
- UInt32 i;
+ size_t i;
for (i = 0; i < numItems; i++)
{
UInt32 value = items[i];
@@ -306,7 +329,7 @@ void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
static void MatchFinder_Normalize(CMatchFinder *p)
{
UInt32 subValue = MatchFinder_GetSubValue(p);
- MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
+ MatchFinder_Normalize3(subValue, p->hash, p->numRefs);
MatchFinder_ReduceOffsets(p, subValue);
}
@@ -467,7 +490,7 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define GET_MATCHES_HEADER2(minLen, ret_op) \
- UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
+ UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer;
@@ -483,13 +506,20 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define SKIP_FOOTER \
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+#define UPDATE_maxLen { \
+ ptrdiff_t diff = (ptrdiff_t)0 - d2; \
+ const Byte *c = cur + maxLen; \
+ const Byte *lim = cur + lenLimit; \
+ for (; c != lim; c++) if (*(c + diff) != *c) break; \
+ maxLen = (UInt32)(c - cur); }
+
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(2)
HASH2_CALC;
- curMatch = p->hash[hashValue];
- p->hash[hashValue] = p->pos;
+ curMatch = p->hash[hv];
+ p->hash[hv] = p->pos;
offset = 0;
GET_MATCHES_FOOTER(offset, 1)
}
@@ -499,35 +529,38 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
- curMatch = p->hash[hashValue];
- p->hash[hashValue] = p->pos;
+ curMatch = p->hash[hv];
+ p->hash[hv] = p->pos;
offset = 0;
GET_MATCHES_FOOTER(offset, 2)
}
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 hash2Value, delta2, maxLen, offset;
+ UInt32 h2, d2, maxLen, offset, pos;
+ UInt32 *hash;
GET_MATCHES_HEADER(3)
HASH3_CALC;
- delta2 = p->pos - p->hash[hash2Value];
- curMatch = p->hash[kFix3HashSize + hashValue];
-
- p->hash[hash2Value] =
- p->hash[kFix3HashSize + hashValue] = p->pos;
+ hash = p->hash;
+ pos = p->pos;
+
+ d2 = pos - hash[h2];
+ curMatch = hash[kFix3HashSize + hv];
+
+ hash[h2] = pos;
+ hash[kFix3HashSize + hv] = pos;
maxLen = 2;
offset = 0;
- if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+
+ if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
- for (; maxLen != lenLimit; maxLen++)
- if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
- break;
+ UPDATE_maxLen
distances[0] = maxLen;
- distances[1] = delta2 - 1;
+ distances[1] = d2 - 1;
offset = 2;
if (maxLen == lenLimit)
{
@@ -535,44 +568,51 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
MOVE_POS_RET;
}
}
+
GET_MATCHES_FOOTER(offset, maxLen)
}
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+ UInt32 h2, h3, d2, d3, maxLen, offset, pos;
+ UInt32 *hash;
GET_MATCHES_HEADER(4)
HASH4_CALC;
- delta2 = p->pos - p->hash[ hash2Value];
- delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
- curMatch = p->hash[kFix4HashSize + hashValue];
-
- p->hash[ hash2Value] =
- p->hash[kFix3HashSize + hash3Value] =
- p->hash[kFix4HashSize + hashValue] = p->pos;
+ hash = p->hash;
+ pos = p->pos;
+
+ d2 = pos - hash[ h2];
+ d3 = pos - hash[kFix3HashSize + h3];
+
+ curMatch = hash[kFix4HashSize + hv];
+
+ hash[ h2] = pos;
+ hash[kFix3HashSize + h3] = pos;
+ hash[kFix4HashSize + hv] = pos;
- maxLen = 1;
+ maxLen = 0;
offset = 0;
- if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+
+ if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
distances[0] = maxLen = 2;
- distances[1] = delta2 - 1;
+ distances[1] = d2 - 1;
offset = 2;
}
- if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+
+ if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
maxLen = 3;
- distances[offset + 1] = delta3 - 1;
+ distances[offset + 1] = d3 - 1;
offset += 2;
- delta2 = delta3;
+ d2 = d3;
}
+
if (offset != 0)
{
- for (; maxLen != lenLimit; maxLen++)
- if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
- break;
+ UPDATE_maxLen
distances[offset - 2] = maxLen;
if (maxLen == lenLimit)
{
@@ -580,46 +620,131 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
MOVE_POS_RET;
}
}
+
if (maxLen < 3)
maxLen = 3;
+
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+/*
+static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
+ UInt32 *hash;
+ GET_MATCHES_HEADER(5)
+
+ HASH5_CALC;
+
+ hash = p->hash;
+ pos = p->pos;
+
+ d2 = pos - hash[ h2];
+ d3 = pos - hash[kFix3HashSize + h3];
+ d4 = pos - hash[kFix4HashSize + h4];
+
+ curMatch = hash[kFix5HashSize + hv];
+
+ hash[ h2] = pos;
+ hash[kFix3HashSize + h3] = pos;
+ hash[kFix4HashSize + h4] = pos;
+ hash[kFix5HashSize + hv] = pos;
+
+ maxLen = 0;
+ offset = 0;
+
+ if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
+ {
+ distances[0] = maxLen = 2;
+ distances[1] = d2 - 1;
+ offset = 2;
+ if (*(cur - d2 + 2) == cur[2])
+ distances[0] = maxLen = 3;
+ else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+ {
+ distances[2] = maxLen = 3;
+ distances[3] = d3 - 1;
+ offset = 4;
+ d2 = d3;
+ }
+ }
+ else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+ {
+ distances[0] = maxLen = 3;
+ distances[1] = d3 - 1;
+ offset = 2;
+ d2 = d3;
+ }
+
+ if (d2 != d4 && d4 < p->cyclicBufferSize
+ && *(cur - d4) == *cur
+ && *(cur - d4 + 3) == *(cur + 3))
+ {
+ maxLen = 4;
+ distances[offset + 1] = d4 - 1;
+ offset += 2;
+ d2 = d4;
+ }
+
+ if (offset != 0)
+ {
+ UPDATE_maxLen
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit)
+ {
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ MOVE_POS_RET;
+ }
+ }
+
+ if (maxLen < 4)
+ maxLen = 4;
+
GET_MATCHES_FOOTER(offset, maxLen)
}
+*/
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+ UInt32 h2, h3, d2, d3, maxLen, offset, pos;
+ UInt32 *hash;
GET_MATCHES_HEADER(4)
HASH4_CALC;
- delta2 = p->pos - p->hash[ hash2Value];
- delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
- curMatch = p->hash[kFix4HashSize + hashValue];
+ hash = p->hash;
+ pos = p->pos;
+
+ d2 = pos - hash[ h2];
+ d3 = pos - hash[kFix3HashSize + h3];
+
+ curMatch = hash[kFix4HashSize + hv];
- p->hash[ hash2Value] =
- p->hash[kFix3HashSize + hash3Value] =
- p->hash[kFix4HashSize + hashValue] = p->pos;
+ hash[ h2] = pos;
+ hash[kFix3HashSize + h3] = pos;
+ hash[kFix4HashSize + hv] = pos;
- maxLen = 1;
+ maxLen = 0;
offset = 0;
- if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+
+ if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
distances[0] = maxLen = 2;
- distances[1] = delta2 - 1;
+ distances[1] = d2 - 1;
offset = 2;
}
- if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+
+ if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
{
maxLen = 3;
- distances[offset + 1] = delta3 - 1;
+ distances[offset + 1] = d3 - 1;
offset += 2;
- delta2 = delta3;
+ d2 = d3;
}
+
if (offset != 0)
{
- for (; maxLen != lenLimit; maxLen++)
- if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
- break;
+ UPDATE_maxLen
distances[offset - 2] = maxLen;
if (maxLen == lenLimit)
{
@@ -627,22 +752,103 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
MOVE_POS_RET;
}
}
+
if (maxLen < 3)
maxLen = 3;
+
+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ distances + offset, maxLen) - (distances));
+ MOVE_POS_RET
+}
+
+/*
+static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
+ UInt32 *hash;
+ GET_MATCHES_HEADER(5)
+
+ HASH5_CALC;
+
+ hash = p->hash;
+ pos = p->pos;
+
+ d2 = pos - hash[ h2];
+ d3 = pos - hash[kFix3HashSize + h3];
+ d4 = pos - hash[kFix4HashSize + h4];
+
+ curMatch = hash[kFix5HashSize + hv];
+
+ hash[ h2] = pos;
+ hash[kFix3HashSize + h3] = pos;
+ hash[kFix4HashSize + h4] = pos;
+ hash[kFix5HashSize + hv] = pos;
+
+ maxLen = 0;
+ offset = 0;
+
+ if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
+ {
+ distances[0] = maxLen = 2;
+ distances[1] = d2 - 1;
+ offset = 2;
+ if (*(cur - d2 + 2) == cur[2])
+ distances[0] = maxLen = 3;
+ else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+ {
+ distances[2] = maxLen = 3;
+ distances[3] = d3 - 1;
+ offset = 4;
+ d2 = d3;
+ }
+ }
+ else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
+ {
+ distances[0] = maxLen = 3;
+ distances[1] = d3 - 1;
+ offset = 2;
+ d2 = d3;
+ }
+
+ if (d2 != d4 && d4 < p->cyclicBufferSize
+ && *(cur - d4) == *cur
+ && *(cur - d4 + 3) == *(cur + 3))
+ {
+ maxLen = 4;
+ distances[offset + 1] = d4 - 1;
+ offset += 2;
+ d2 = d4;
+ }
+
+ if (offset != 0)
+ {
+ UPDATE_maxLen
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit)
+ {
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS_RET;
+ }
+ }
+
+ if (maxLen < 4)
+ maxLen = 4;
+
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
- distances + offset, maxLen) - (distances));
+ distances + offset, maxLen) - (distances));
MOVE_POS_RET
}
+*/
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
- curMatch = p->hash[hashValue];
- p->hash[hashValue] = p->pos;
+ curMatch = p->hash[hv];
+ p->hash[hv] = p->pos;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
- distances, 2) - (distances));
+ distances, 2) - (distances));
MOVE_POS_RET
}
@@ -652,8 +858,8 @@ static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
SKIP_HEADER(2)
HASH2_CALC;
- curMatch = p->hash[hashValue];
- p->hash[hashValue] = p->pos;
+ curMatch = p->hash[hv];
+ p->hash[hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
@@ -665,8 +871,8 @@ void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
SKIP_HEADER(3)
HASH_ZIP_CALC;
- curMatch = p->hash[hashValue];
- p->hash[hashValue] = p->pos;
+ curMatch = p->hash[hv];
+ p->hash[hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
@@ -676,12 +882,14 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
- UInt32 hash2Value;
+ UInt32 h2;
+ UInt32 *hash;
SKIP_HEADER(3)
HASH3_CALC;
- curMatch = p->hash[kFix3HashSize + hashValue];
- p->hash[hash2Value] =
- p->hash[kFix3HashSize + hashValue] = p->pos;
+ hash = p->hash;
+ curMatch = hash[kFix3HashSize + hv];
+ hash[h2] =
+ hash[kFix3HashSize + hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
@@ -691,43 +899,90 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
- UInt32 hash2Value, hash3Value;
+ UInt32 h2, h3;
+ UInt32 *hash;
SKIP_HEADER(4)
HASH4_CALC;
- curMatch = p->hash[kFix4HashSize + hashValue];
- p->hash[ hash2Value] =
- p->hash[kFix3HashSize + hash3Value] = p->pos;
- p->hash[kFix4HashSize + hashValue] = p->pos;
+ hash = p->hash;
+ curMatch = hash[kFix4HashSize + hv];
+ hash[ h2] =
+ hash[kFix3HashSize + h3] =
+ hash[kFix4HashSize + hv] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
+/*
+static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 h2, h3, h4;
+ UInt32 *hash;
+ SKIP_HEADER(5)
+ HASH5_CALC;
+ hash = p->hash;
+ curMatch = hash[kFix5HashSize + hv];
+ hash[ h2] =
+ hash[kFix3HashSize + h3] =
+ hash[kFix4HashSize + h4] =
+ hash[kFix5HashSize + hv] = p->pos;
+ SKIP_FOOTER
+ }
+ while (--num != 0);
+}
+*/
+
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
- UInt32 hash2Value, hash3Value;
+ UInt32 h2, h3;
+ UInt32 *hash;
SKIP_HEADER(4)
HASH4_CALC;
- curMatch = p->hash[kFix4HashSize + hashValue];
- p->hash[ hash2Value] =
- p->hash[kFix3HashSize + hash3Value] =
- p->hash[kFix4HashSize + hashValue] = p->pos;
+ hash = p->hash;
+ curMatch = hash[kFix4HashSize + hv];
+ hash[ h2] =
+ hash[kFix3HashSize + h3] =
+ hash[kFix4HashSize + hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
while (--num != 0);
}
+/*
+static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do
+ {
+ UInt32 h2, h3, h4;
+ UInt32 *hash;
+ SKIP_HEADER(5)
+ HASH5_CALC;
+ hash = p->hash;
+ curMatch = p->hash[kFix5HashSize + hv];
+ hash[ h2] =
+ hash[kFix3HashSize + h3] =
+ hash[kFix4HashSize + h4] =
+ hash[kFix5HashSize + hv] = p->pos;
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS
+ }
+ while (--num != 0);
+}
+*/
+
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
SKIP_HEADER(3)
HASH_ZIP_CALC;
- curMatch = p->hash[hashValue];
- p->hash[hashValue] = p->pos;
+ curMatch = p->hash[hv];
+ p->hash[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
@@ -737,13 +992,22 @@ void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
{
vTable->Init = (Mf_Init_Func)MatchFinder_Init;
- vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
if (!p->btMode)
{
- vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
- vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+ /* if (p->numHashBytes <= 4) */
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+ }
+ /*
+ else
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
+ }
+ */
}
else if (p->numHashBytes == 2)
{
@@ -755,9 +1019,16 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
}
- else
+ else /* if (p->numHashBytes == 4) */
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
}
+ /*
+ else
+ {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
+ }
+ */
}
diff --git a/C/LzFind.h b/C/LzFind.h
index 706143d2..2c094877 100644
--- a/C/LzFind.h
+++ b/C/LzFind.h
@@ -1,5 +1,5 @@
/* LzFind.h -- Match finder for LZ algorithms
-2013-01-18 : Igor Pavlov : Public domain */
+2015-05-01 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_H
#define __LZ_FIND_H
@@ -21,6 +21,11 @@ typedef struct _CMatchFinder
UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+ Byte streamEndWasReached;
+ Byte btMode;
+ Byte bigHash;
+ Byte directInput;
+
UInt32 matchMaxLen;
CLzRef *hash;
CLzRef *son;
@@ -29,27 +34,22 @@ typedef struct _CMatchFinder
Byte *bufferBase;
ISeqInStream *stream;
- int streamEndWasReached;
-
+
UInt32 blockSize;
UInt32 keepSizeBefore;
UInt32 keepSizeAfter;
UInt32 numHashBytes;
- int directInput;
size_t directInputRem;
- int btMode;
- int bigHash;
UInt32 historySize;
UInt32 fixedHashSize;
UInt32 hashSizeSum;
- UInt32 numSons;
SRes result;
UInt32 crc[256];
+ size_t numRefs;
} CMatchFinder;
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
-#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
@@ -68,7 +68,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc);
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
-void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
@@ -82,7 +82,6 @@ Conditions:
*/
typedef void (*Mf_Init_Func)(void *object);
-typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
@@ -91,7 +90,6 @@ typedef void (*Mf_Skip_Func)(void *object, UInt32);
typedef struct _IMatchFinder
{
Mf_Init_Func Init;
- Mf_GetIndexByte_Func GetIndexByte;
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
Mf_GetMatches_Func GetMatches;
diff --git a/C/LzFindMt.c b/C/LzFindMt.c
index cee8ea74..2b7c1576 100644
--- a/C/LzFindMt.c
+++ b/C/LzFindMt.c
@@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
-2014-12-29 : Igor Pavlov : Public domain */
+2015-05-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -7,7 +7,7 @@
#include "LzFindMt.h"
-void MtSync_Construct(CMtSync *p)
+static void MtSync_Construct(CMtSync *p)
{
p->wasCreated = False;
p->csWasInitialized = False;
@@ -20,7 +20,7 @@ void MtSync_Construct(CMtSync *p)
Semaphore_Construct(&p->filledSemaphore);
}
-void MtSync_GetNextBlock(CMtSync *p)
+static void MtSync_GetNextBlock(CMtSync *p)
{
if (p->needStart)
{
@@ -48,7 +48,7 @@ void MtSync_GetNextBlock(CMtSync *p)
/* MtSync_StopWriting must be called if Writing was started */
-void MtSync_StopWriting(CMtSync *p)
+static void MtSync_StopWriting(CMtSync *p)
{
UInt32 myNumBlocks = p->numProcessedBlocks;
if (!Thread_WasCreated(&p->thread) || p->needStart)
@@ -71,7 +71,7 @@ void MtSync_StopWriting(CMtSync *p)
p->needStart = True;
}
-void MtSync_Destruct(CMtSync *p)
+static void MtSync_Destruct(CMtSync *p)
{
if (Thread_WasCreated(&p->thread))
{
@@ -134,20 +134,20 @@ void MtSync_Init(CMtSync *p) { p->needStart = True; }
#define kMtMaxValForNormalize 0xFFFFFFFF
#define DEF_GetHeads2(name, v, action) \
-static void GetHeads ## name(const Byte *p, UInt32 pos, \
-UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
-{ action; for (; numHeads != 0; numHeads--) { \
-const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
+ static void GetHeads ## name(const Byte *p, UInt32 pos, \
+ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
+ { action; for (; numHeads != 0; numHeads--) { \
+ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
-DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )
+DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), UNUSED_VAR(hashMask); UNUSED_VAR(crc); )
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
-void HashThreadFunc(CMatchFinderMt *mt)
+static void HashThreadFunc(CMatchFinderMt *mt)
{
CMtSync *p = &mt->hashSync;
for (;;)
@@ -192,7 +192,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
{
UInt32 subValue = (mf->pos - mf->historySize - 1);
MatchFinder_ReduceOffsets(mf, subValue);
- MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
+ MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1);
}
{
UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
@@ -217,7 +217,7 @@ void HashThreadFunc(CMatchFinderMt *mt)
}
}
-void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
+static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
{
MtSync_GetNextBlock(&p->hashSync);
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
@@ -233,7 +233,7 @@ void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
#define NO_INLINE MY_FAST_CALL
-Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
+static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
{
@@ -310,12 +310,14 @@ Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CL
#endif
-void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
+static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{
UInt32 numProcessed = 0;
UInt32 curPos = 2;
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
+
distances[1] = p->hashNumAvail;
+
while (curPos < limit)
{
if (p->hashBufPos == p->hashBufPosLimit)
@@ -324,9 +326,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
distances[1] = numProcessed + p->hashNumAvail;
if (p->hashNumAvail >= p->numHashBytes)
continue;
+ distances[0] = curPos + p->hashNumAvail;
+ distances += curPos;
for (; p->hashNumAvail != 0; p->hashNumAvail--)
- distances[curPos++] = 0;
- break;
+ *distances++ = 0;
+ return;
}
{
UInt32 size = p->hashBufPosLimit - p->hashBufPos;
@@ -343,13 +347,14 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
if (size2 < size)
size = size2;
}
+
#ifndef MFMT_GM_INLINE
while (curPos < limit && size-- != 0)
{
UInt32 *startDistances = distances + curPos;
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
- pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
- startDistances + 1, p->numHashBytes - 1) - startDistances);
+ pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ startDistances + 1, p->numHashBytes - 1) - startDistances);
*startDistances = num - 1;
curPos += num;
cyclicBufferPos++;
@@ -360,7 +365,7 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{
UInt32 posRes;
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
- distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
+ distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos), size, &posRes);
p->hashBufPos += posRes - pos;
cyclicBufferPos += posRes - pos;
p->buffer += posRes - pos;
@@ -376,10 +381,11 @@ void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
p->cyclicBufferPos = cyclicBufferPos;
}
}
+
distances[0] = curPos;
}
-void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
+static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
{
CMtSync *sync = &p->hashSync;
if (!sync->needStart)
@@ -393,7 +399,7 @@ void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
{
UInt32 subValue = p->pos - p->cyclicBufferSize;
- MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
+ MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2);
p->pos -= subValue;
}
@@ -432,15 +438,15 @@ void BtThreadFunc(CMatchFinderMt *mt)
void MatchFinderMt_Construct(CMatchFinderMt *p)
{
- p->hashBuf = 0;
+ p->hashBuf = NULL;
MtSync_Construct(&p->hashSync);
MtSync_Construct(&p->btSync);
}
-void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
+static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->hashBuf);
- p->hashBuf = 0;
+ p->hashBuf = NULL;
}
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
@@ -457,9 +463,11 @@ static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { Has
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p)
{
Byte allocaDummy[0x180];
- allocaDummy[0] = 0;
- allocaDummy[1] = allocaDummy[0];
- BtThreadFunc((CMatchFinderMt *)p);
+ unsigned i = 0;
+ for (i = 0; i < 16; i++)
+ allocaDummy[i] = (Byte)0;
+ if (allocaDummy[0] == 0)
+ BtThreadFunc((CMatchFinderMt *)p);
return 0;
}
@@ -470,10 +478,10 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
p->historySize = historySize;
if (kMtBtBlockSize <= matchMaxLen * 4)
return SZ_ERROR_PARAM;
- if (p->hashBuf == 0)
+ if (!p->hashBuf)
{
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
- if (p->hashBuf == 0)
+ if (!p->hashBuf)
return SZ_ERROR_MEM;
p->btBuf = p->hashBuf + kHashBufferSize;
}
@@ -519,13 +527,13 @@ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
/* p->MatchFinder->ReleaseStream(); */
}
-void MatchFinderMt_Normalize(CMatchFinderMt *p)
+static void MatchFinderMt_Normalize(CMatchFinderMt *p)
{
MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
p->lzPos = p->historySize + 1;
}
-void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
+static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
{
UInt32 blockIndex;
MtSync_GetNextBlock(&p->btSync);
@@ -537,34 +545,29 @@ void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
MatchFinderMt_Normalize(p);
}
-const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
+static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
{
return p->pointerToCurPos;
}
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
-UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
+static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
{
GET_NEXT_BLOCK_IF_REQUIRED;
return p->btNumAvailBytes;
}
-Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
-{
- return p->pointerToCurPos[index];
-}
-
-UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{
- UInt32 hash2Value, curMatch2;
+ UInt32 h2, curMatch2;
UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos;
MT_HASH2_CALC
- curMatch2 = hash[hash2Value];
- hash[hash2Value] = lzPos;
+ curMatch2 = hash[h2];
+ hash[h2] = lzPos;
if (curMatch2 >= matchMinPos)
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
@@ -572,23 +575,23 @@ UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
*distances++ = 2;
*distances++ = lzPos - curMatch2 - 1;
}
+
return distances;
}
-UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{
- UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
+ UInt32 h2, h3, curMatch2, curMatch3;
UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos;
MT_HASH3_CALC
- curMatch2 = hash[ hash2Value];
- curMatch3 = hash[kFix3HashSize + hash3Value];
+ curMatch2 = hash[ h2];
+ curMatch3 = hash[kFix3HashSize + h3];
- hash[ hash2Value] =
- hash[kFix3HashSize + hash3Value] =
- lzPos;
+ hash[ h2] = lzPos;
+ hash[kFix3HashSize + h3] = lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{
@@ -601,43 +604,45 @@ UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
distances[0] = 2;
distances += 2;
}
+
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
{
*distances++ = 3;
*distances++ = lzPos - curMatch3 - 1;
}
+
return distances;
}
/*
-UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
+static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{
- UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
+ UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4;
UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos;
MT_HASH4_CALC
- curMatch2 = hash[ hash2Value];
- curMatch3 = hash[kFix3HashSize + hash3Value];
- curMatch4 = hash[kFix4HashSize + hash4Value];
+ curMatch2 = hash[ h2];
+ curMatch3 = hash[kFix3HashSize + h3];
+ curMatch4 = hash[kFix4HashSize + h4];
- hash[ hash2Value] =
- hash[kFix3HashSize + hash3Value] =
- hash[kFix4HashSize + hash4Value] =
- lzPos;
+ hash[ h2] = lzPos;
+ hash[kFix3HashSize + h3] = lzPos;
+ hash[kFix4HashSize + h4] = lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{
distances[1] = lzPos - curMatch2 - 1;
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
{
- distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
+ distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
return distances + 2;
}
distances[0] = 2;
distances += 2;
}
+
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
{
distances[1] = lzPos - curMatch3 - 1;
@@ -659,13 +664,14 @@ UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
*distances++ = 4;
*distances++ = lzPos - curMatch4 - 1;
}
+
return distances;
}
*/
#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
-UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
+static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
{
const UInt32 *btBuf = p->btBuf + p->btBufPos;
UInt32 len = *btBuf++;
@@ -683,7 +689,7 @@ UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
return len;
}
-UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
+static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
{
const UInt32 *btBuf = p->btBuf + p->btBufPos;
UInt32 len = *btBuf++;
@@ -691,6 +697,7 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
if (len == 0)
{
+ /* change for bt5 ! */
if (p->btNumAvailBytes-- >= 4)
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
}
@@ -706,7 +713,7 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
*distances2++ = *btBuf++;
}
while ((len -= 2) != 0);
- len = (UInt32)(distances2 - (distances));
+ len = (UInt32)(distances2 - (distances));
}
INCREASE_LZ_POS
return len;
@@ -716,41 +723,41 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
-void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
+static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
{
SKIP_HEADER2_MT { p->btNumAvailBytes--;
SKIP_FOOTER_MT
}
-void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
+static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
{
SKIP_HEADER_MT(2)
- UInt32 hash2Value;
+ UInt32 h2;
MT_HASH2_CALC
- hash[hash2Value] = p->lzPos;
+ hash[h2] = p->lzPos;
SKIP_FOOTER_MT
}
-void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
+static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
{
SKIP_HEADER_MT(3)
- UInt32 hash2Value, hash3Value;
+ UInt32 h2, h3;
MT_HASH3_CALC
- hash[kFix3HashSize + hash3Value] =
- hash[ hash2Value] =
+ hash[kFix3HashSize + h3] =
+ hash[ h2] =
p->lzPos;
SKIP_FOOTER_MT
}
/*
-void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
+static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
{
SKIP_HEADER_MT(4)
- UInt32 hash2Value, hash3Value, hash4Value;
+ UInt32 h2, h3, h4;
MT_HASH4_CALC
- hash[kFix4HashSize + hash4Value] =
- hash[kFix3HashSize + hash3Value] =
- hash[ hash2Value] =
+ hash[kFix4HashSize + h4] =
+ hash[kFix3HashSize + h3] =
+ hash[ h2] =
p->lzPos;
SKIP_FOOTER_MT
}
@@ -759,11 +766,11 @@ void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
{
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
- vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
- switch(p->MatchFinder->numHashBytes)
+
+ switch (p->MatchFinder->numHashBytes)
{
case 2:
p->GetHeadsFunc = GetHeads2;
@@ -779,7 +786,6 @@ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
default:
/* case 4: */
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
- /* p->GetHeadsFunc = GetHeads4; */
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
break;
diff --git a/C/LzFindMt.h b/C/LzFindMt.h
index 6a7095b0..89b91fef 100644
--- a/C/LzFindMt.h
+++ b/C/LzFindMt.h
@@ -1,5 +1,5 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
-2013-01-18 : Igor Pavlov : Public domain */
+2015-05-03 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_MT_H
#define __LZ_FIND_MT_H
@@ -75,7 +75,7 @@ typedef struct _CMatchFinderMt
UInt32 matchMaxLen;
UInt32 numHashBytes;
UInt32 pos;
- Byte *buffer;
+ const Byte *buffer;
UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
UInt32 cutValue;
diff --git a/C/LzHash.h b/C/LzHash.h
index f3e89966..e7c94230 100644
--- a/C/LzHash.h
+++ b/C/LzHash.h
@@ -1,5 +1,5 @@
/* LzHash.h -- HASH functions for LZ algorithms
-2009-02-07 : Igor Pavlov : Public domain */
+2015-04-12 : Igor Pavlov : Public domain */
#ifndef __LZ_HASH_H
#define __LZ_HASH_H
@@ -12,43 +12,46 @@
#define kFix4HashSize (kHash2Size + kHash3Size)
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
-#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
+#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
#define HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
- hash2Value = temp & (kHash2Size - 1); \
- hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+ h2 = temp & (kHash2Size - 1); \
+ hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
#define HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
- hash2Value = temp & (kHash2Size - 1); \
- hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
- hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
+ h2 = temp & (kHash2Size - 1); \
+ temp ^= ((UInt32)cur[2] << 8); \
+ h3 = temp & (kHash3Size - 1); \
+ hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
#define HASH5_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
- hash2Value = temp & (kHash2Size - 1); \
- hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
- hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
- hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
- hash4Value &= (kHash4Size - 1); }
+ h2 = temp & (kHash2Size - 1); \
+ temp ^= ((UInt32)cur[2] << 8); \
+ h3 = temp & (kHash3Size - 1); \
+ temp ^= (p->crc[cur[3]] << 5); \
+ h4 = temp & (kHash4Size - 1); \
+ hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
-/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
-#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
+/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
#define MT_HASH2_CALC \
- hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+ h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
#define MT_HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
- hash2Value = temp & (kHash2Size - 1); \
- hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+ h2 = temp & (kHash2Size - 1); \
+ h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
#define MT_HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
- hash2Value = temp & (kHash2Size - 1); \
- hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
- hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
+ h2 = temp & (kHash2Size - 1); \
+ temp ^= ((UInt32)cur[2] << 8); \
+ h3 = temp & (kHash3Size - 1); \
+ h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
#endif
diff --git a/C/Lzma2Dec.c b/C/Lzma2Dec.c
index 502a1588..31843674 100644
--- a/C/Lzma2Dec.c
+++ b/C/Lzma2Dec.c
@@ -1,5 +1,5 @@
/* Lzma2Dec.c -- LZMA2 Decoder
-2010-12-15 : Igor Pavlov : Public domain */
+2014-10-29 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */
@@ -99,7 +99,7 @@ void Lzma2Dec_Init(CLzma2Dec *p)
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
{
- switch(p->state)
+ switch (p->state)
{
case LZMA2_STATE_CONTROL:
p->control = b;
@@ -140,7 +140,7 @@ static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
case LZMA2_STATE_PROP:
{
- int lc, lp;
+ unsigned lc, lp;
if (b >= (9 * 5 * 5))
return LZMA2_STATE_ERROR;
lc = b % 9;
@@ -179,13 +179,16 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
while (p->state != LZMA2_STATE_FINISHED)
{
SizeT dicPos = p->decoder.dicPos;
+
if (p->state == LZMA2_STATE_ERROR)
return SZ_ERROR_DATA;
+
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{
*status = LZMA_STATUS_NOT_FINISHED;
return SZ_OK;
}
+
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{
if (*srcLen == inSize)
@@ -195,8 +198,15 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
}
(*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++);
+
+ if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
+ {
+ p->state = LZMA2_STATE_ERROR;
+ return SZ_ERROR_DATA;
+ }
continue;
}
+
{
SizeT destSizeCur = dicLimit - dicPos;
SizeT srcSizeCur = inSize - *srcLen;
@@ -222,7 +232,10 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (initDic)
p->needInitProp = p->needInitState = True;
else if (p->needInitDic)
+ {
+ p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
+ }
p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
}
@@ -231,7 +244,10 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
srcSizeCur = destSizeCur;
if (srcSizeCur == 0)
+ {
+ p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
+ }
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
@@ -247,17 +263,21 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (p->state == LZMA2_STATE_DATA)
{
- int mode = LZMA2_GET_LZMA_MODE(p);
+ unsigned mode = LZMA2_GET_LZMA_MODE(p);
Bool initDic = (mode == 3);
- Bool initState = (mode > 0);
+ Bool initState = (mode != 0);
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
+ {
+ p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
+ }
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->needInitDic = False;
p->needInitState = False;
p->state = LZMA2_STATE_DATA_CONT;
}
+
if (srcSizeCur > p->packSize)
srcSizeCur = (SizeT)p->packSize;
@@ -276,16 +296,22 @@ SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
if (srcSizeCur == 0 && outSizeProcessed == 0)
{
- if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
- p->unpackSize != 0 || p->packSize != 0)
+ if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+ || p->unpackSize != 0
+ || p->packSize != 0)
+ {
+ p->state = LZMA2_STATE_ERROR;
return SZ_ERROR_DATA;
+ }
p->state = LZMA2_STATE_CONTROL;
}
+
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
*status = LZMA_STATUS_NOT_FINISHED;
}
}
}
+
*status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
}
diff --git a/C/Lzma2Dec.h b/C/Lzma2Dec.h
index 367daf6b..e6a0f6ed 100644
--- a/C/Lzma2Dec.h
+++ b/C/Lzma2Dec.h
@@ -1,5 +1,5 @@
/* Lzma2Dec.h -- LZMA2 Decoder
-2013-01-18 : Igor Pavlov : Public domain */
+2015-05-13 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H
@@ -15,7 +15,7 @@ typedef struct
CLzmaDec decoder;
UInt32 packSize;
UInt32 unpackSize;
- int state;
+ unsigned state;
Byte control;
Bool needInitDic;
Bool needInitState;
diff --git a/C/Lzma2Enc.c b/C/Lzma2Enc.c
index 0c8e02e9..07535559 100644
--- a/C/Lzma2Enc.c
+++ b/C/Lzma2Enc.c
@@ -238,9 +238,9 @@ void Lzma2EncProps_Normalize(CLzma2EncProps *p)
if (temp > p->lzmaProps.reduceSize)
{
UInt64 numBlocks = temp / p->blockSize;
- if (numBlocks < t2)
+ if (numBlocks < (unsigned)t2)
{
- t2 = (UInt32)numBlocks;
+ t2 = (unsigned)numBlocks;
t3 = t1 * t2;
}
}
diff --git a/C/LzmaDec.c b/C/LzmaDec.c
index bbf650de..c8326667 100644
--- a/C/LzmaDec.c
+++ b/C/LzmaDec.c
@@ -1,5 +1,5 @@
/* LzmaDec.c -- LZMA Decoder
-2015-01-01 : Igor Pavlov : Public domain */
+2015-05-14 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -114,14 +114,14 @@
#define Literal (RepLenCoder + kNumLenProbs)
#define LZMA_BASE_SIZE 1846
-#define LZMA_LIT_SIZE 768
-
-#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+#define LZMA_LIT_SIZE 0x300
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
+#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
#define LZMA_DIC_MIN (1 << 12)
/* First LZMA-symbol is always decoded.
@@ -133,8 +133,8 @@ Out:
p->remainLen:
< kMatchSpecLenStart : normal remain
= kMatchSpecLenStart : finished
- = kMatchSpecLenStart + 1 : Flush marker
- = kMatchSpecLenStart + 2 : State Init Marker
+ = kMatchSpecLenStart + 1 : Flush marker (unused now)
+ = kMatchSpecLenStart + 2 : State Init Marker (unused now)
*/
static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
@@ -172,9 +172,10 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
unsigned symbol;
UPDATE_0(prob);
prob = probs + Literal;
- if (checkDicSize != 0 || processedPos != 0)
- prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
- (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+ if (processedPos != 0 || checkDicSize != 0)
+ prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
+ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+ processedPos++;
if (state < kNumLitStates)
{
@@ -195,7 +196,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
}
else
{
- unsigned matchByte = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
unsigned offs = 0x100;
state -= (state < 10) ? 3 : 6;
symbol = 1;
@@ -222,11 +223,11 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
}
#endif
}
+
dic[dicPos++] = (Byte)symbol;
- processedPos++;
continue;
}
- else
+
{
UPDATE_1(prob);
prob = probs + IsRep + state;
@@ -249,7 +250,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
IF_BIT_0(prob)
{
UPDATE_0(prob);
- dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
dicPos++;
processedPos++;
state = state < kNumLitStates ? 9 : 11;
@@ -290,6 +291,8 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
state = state < kNumLitStates ? 8 : 11;
prob = probs + RepLenCoder;
}
+
+ #ifdef _LZMA_SIZE_OPT
{
unsigned limit, offset;
CLzmaProb *probLen = prob + LenChoice;
@@ -322,6 +325,42 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
TREE_DECODE(probLen, limit, len);
len += offset;
}
+ #else
+ {
+ CLzmaProb *probLen = prob + LenChoice;
+ IF_BIT_0(probLen)
+ {
+ UPDATE_0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ len = 1;
+ TREE_GET_BIT(probLen, len);
+ TREE_GET_BIT(probLen, len);
+ TREE_GET_BIT(probLen, len);
+ len -= 8;
+ }
+ else
+ {
+ UPDATE_1(probLen);
+ probLen = prob + LenChoice2;
+ IF_BIT_0(probLen)
+ {
+ UPDATE_0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ len = 1;
+ TREE_GET_BIT(probLen, len);
+ TREE_GET_BIT(probLen, len);
+ TREE_GET_BIT(probLen, len);
+ }
+ else
+ {
+ UPDATE_1(probLen);
+ probLen = prob + LenHigh;
+ TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
+ len += kLenNumLowSymbols + kLenNumMidSymbols;
+ }
+ }
+ }
+ #endif
if (state >= kNumStates)
{
@@ -332,7 +371,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
if (distance >= kStartPosModelIndex)
{
unsigned posSlot = (unsigned)distance;
- int numDirectBits = (int)(((distance >> 1) - 1));
+ unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));
distance = (2 | (distance & 1));
if (posSlot < kEndPosModelIndex)
{
@@ -391,6 +430,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
}
}
}
+
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
@@ -407,17 +447,21 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
len += kMatchMinLen;
- if (limit == dicPos)
- return SZ_ERROR_DATA;
{
- SizeT rem = limit - dicPos;
- unsigned curLen = ((rem < len) ? (unsigned)rem : len);
- SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
+ SizeT rem;
+ unsigned curLen;
+ SizeT pos;
+
+ if ((rem = limit - dicPos) == 0)
+ return SZ_ERROR_DATA;
+
+ curLen = ((rem < len) ? (unsigned)rem : len);
+ pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
processedPos += curLen;
len -= curLen;
- if (pos + curLen <= dicBufSize)
+ if (curLen <= dicBufSize - pos)
{
Byte *dest = dic + dicPos;
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
@@ -441,7 +485,9 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
}
}
while (dicPos < limit && buf < bufLimit);
+
NORMALIZE;
+
p->buf = buf;
p->range = range;
p->code = code;
@@ -465,9 +511,10 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
SizeT dicPos = p->dicPos;
SizeT dicBufSize = p->dicBufSize;
unsigned len = p->remainLen;
- UInt32 rep0 = p->reps[0];
- if (limit - dicPos < len)
- len = (unsigned)(limit - dicPos);
+ SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
+ SizeT rem = limit - dicPos;
+ if (rem < len)
+ len = (unsigned)(rem);
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
p->checkDicSize = p->prop.dicSize;
@@ -477,7 +524,7 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
while (len != 0)
{
len--;
- dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
dicPos++;
}
p->dicPos = dicPos;
@@ -495,17 +542,19 @@ static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte
if (limit - p->dicPos > rem)
limit2 = p->dicPos + rem;
}
+
RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
- if (p->processedPos >= p->prop.dicSize)
+
+ if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
p->checkDicSize = p->prop.dicSize;
+
LzmaDec_WriteRem(p, limit);
}
while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
if (p->remainLen > kMatchSpecLenStart)
- {
p->remainLen = kMatchSpecLenStart;
- }
+
return 0;
}
@@ -522,12 +571,12 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
UInt32 range = p->range;
UInt32 code = p->code;
const Byte *bufLimit = buf + inSize;
- CLzmaProb *probs = p->probs;
+ const CLzmaProb *probs = p->probs;
unsigned state = p->state;
ELzmaDummy res;
{
- CLzmaProb *prob;
+ const CLzmaProb *prob;
UInt32 bound;
unsigned ttt;
unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
@@ -541,9 +590,9 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
prob = probs + Literal;
if (p->checkDicSize != 0 || p->processedPos != 0)
- prob += (LZMA_LIT_SIZE *
- ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
- (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+ prob += ((UInt32)LZMA_LIT_SIZE *
+ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
+ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
if (state < kNumLitStates)
{
@@ -553,13 +602,13 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
else
{
unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
- ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
+ (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];
unsigned offs = 0x100;
unsigned symbol = 1;
do
{
unsigned bit;
- CLzmaProb *probLit;
+ const CLzmaProb *probLit;
matchByte <<= 1;
bit = (matchByte & offs);
probLit = prob + offs + bit + symbol;
@@ -629,7 +678,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
}
{
unsigned limit, offset;
- CLzmaProb *probLen = prob + LenChoice;
+ const CLzmaProb *probLen = prob + LenChoice;
IF_BIT_0_CHECK(probLen)
{
UPDATE_0_CHECK;
@@ -669,7 +718,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex)
{
- int numDirectBits = ((posSlot >> 1) - 1);
+ unsigned numDirectBits = ((posSlot >> 1) - 1);
/* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
@@ -708,13 +757,6 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
}
-static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
-{
- p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
- p->range = 0xFFFFFFFF;
- p->needFlush = 0;
-}
-
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
{
p->needFlush = 1;
@@ -739,8 +781,8 @@ void LzmaDec_Init(CLzmaDec *p)
static void LzmaDec_InitStateReal(CLzmaDec *p)
{
- UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
- UInt32 i;
+ SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
+ SizeT i;
CLzmaProb *probs = p->probs;
for (i = 0; i < numProbs; i++)
probs[i] = kBitModelTotal >> 1;
@@ -762,7 +804,7 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
{
int checkEndMarkNow;
- if (p->needFlush != 0)
+ if (p->needFlush)
{
for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
p->tempBuf[p->tempBufSize++] = *src++;
@@ -773,8 +815,13 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
}
if (p->tempBuf[0] != 0)
return SZ_ERROR_DATA;
-
- LzmaDec_InitRc(p, p->tempBuf);
+ p->code =
+ ((UInt32)p->tempBuf[1] << 24)
+ | ((UInt32)p->tempBuf[2] << 16)
+ | ((UInt32)p->tempBuf[3] << 8)
+ | ((UInt32)p->tempBuf[4]);
+ p->range = 0xFFFFFFFF;
+ p->needFlush = 0;
p->tempBufSize = 0;
}
@@ -858,7 +905,16 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
p->buf = p->tempBuf;
if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
return SZ_ERROR_DATA;
- lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
+
+ {
+ unsigned kkk = (unsigned)(p->buf - p->tempBuf);
+ if (rem < kkk)
+ return SZ_ERROR_FAIL; /* some internal error */
+ rem -= kkk;
+ if (lookAhead < rem)
+ return SZ_ERROR_FAIL; /* some internal error */
+ lookAhead -= rem;
+ }
(*srcLen) += lookAhead;
src += lookAhead;
inSize -= lookAhead;
@@ -913,13 +969,13 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *sr
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->probs);
- p->probs = 0;
+ p->probs = NULL;
}
static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->dic);
- p->dic = 0;
+ p->dic = NULL;
}
void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
@@ -957,12 +1013,12 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
{
UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
- if (p->probs == 0 || numProbs != p->numProbs)
+ if (!p->probs || numProbs != p->numProbs)
{
LzmaDec_FreeProbs(p, alloc);
p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
p->numProbs = numProbs;
- if (p->probs == 0)
+ if (!p->probs)
return SZ_ERROR_MEM;
}
return SZ_OK;
@@ -983,12 +1039,22 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll
SizeT dicBufSize;
RINOK(LzmaProps_Decode(&propNew, props, propsSize));
RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
- dicBufSize = propNew.dicSize;
- if (p->dic == 0 || dicBufSize != p->dicBufSize)
+
+ {
+ UInt32 dictSize = propNew.dicSize;
+ SizeT mask = ((UInt32)1 << 12) - 1;
+ if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1;
+ else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;;
+ dicBufSize = ((SizeT)dictSize + mask) & ~mask;
+ if (dicBufSize < dictSize)
+ dicBufSize = dictSize;
+ }
+
+ if (!p->dic || dicBufSize != p->dicBufSize)
{
LzmaDec_FreeDict(p, alloc);
p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
- if (p->dic == 0)
+ if (!p->dic)
{
LzmaDec_FreeProbs(p, alloc);
return SZ_ERROR_MEM;
diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c
index 37e05a95..ea214850 100644
--- a/C/LzmaEnc.c
+++ b/C/LzmaEnc.c
@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder
-2014-12-29 : Igor Pavlov : Public domain */
+2015-05-15 Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -23,6 +23,9 @@
static unsigned g_STAT_OFFSET = 0;
#endif
+#define kMaxHistorySize ((UInt32)3 << 29)
+/* #define kMaxHistorySize ((UInt32)7 << 29) */
+
#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
#define kBlockSize (9 << 10)
@@ -58,6 +61,7 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
int level = p->level;
if (level < 0) level = 5;
p->level = level;
+
if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
if (p->dictSize > p->reduceSize)
{
@@ -68,14 +72,17 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
}
}
+
if (p->lc < 0) p->lc = 3;
if (p->lp < 0) p->lp = 0;
if (p->pb < 0) p->pb = 2;
+
if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
if (p->numHashBytes < 0) p->numHashBytes = 4;
- if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
+ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
+
if (p->numThreads < 0)
p->numThreads =
#ifndef _7ZIP_ST
@@ -92,17 +99,18 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
return props.dictSize;
}
+#if (_MSC_VER >= 1400)
+/* BSR code is fast for some new CPUs */
/* #define LZMA_LOG_BSR */
-/* Define it for Intel's CPU */
-
+#endif
#ifdef LZMA_LOG_BSR
-#define kDicLogSizeMaxCompress 30
+#define kDicLogSizeMaxCompress 32
#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
-UInt32 GetPosSlot1(UInt32 pos)
+static UInt32 GetPosSlot1(UInt32 pos)
{
UInt32 res;
BSR2_RET(pos, res);
@@ -113,27 +121,44 @@ UInt32 GetPosSlot1(UInt32 pos)
#else
-#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
+#define kNumLogBits (9 + sizeof(size_t) / 2)
+/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */
+
#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
-void LzmaEnc_FastPosInit(Byte *g_FastPos)
+static void LzmaEnc_FastPosInit(Byte *g_FastPos)
{
- int c = 2, slotFast;
+ unsigned slot;
g_FastPos[0] = 0;
g_FastPos[1] = 1;
+ g_FastPos += 2;
- for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
+ for (slot = 2; slot < kNumLogBits * 2; slot++)
{
- UInt32 k = (1 << ((slotFast >> 1) - 1));
- UInt32 j;
- for (j = 0; j < k; j++, c++)
- g_FastPos[c] = (Byte)slotFast;
+ size_t k = ((size_t)1 << ((slot >> 1) - 1));
+ size_t j;
+ for (j = 0; j < k; j++)
+ g_FastPos[j] = (Byte)slot;
+ g_FastPos += k;
}
}
+/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
+/*
#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
(0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
res = p->g_FastPos[pos >> i] + (i * 2); }
+*/
+
+/*
+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
+ (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
+ res = p->g_FastPos[pos >> i] + (i * 2); }
+*/
+
+#define BSR2_RET(pos, res) { UInt32 i = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
+ res = p->g_FastPos[pos >> i] + (i * 2); }
+
/*
#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
p->g_FastPos[pos >> 6] + 12 : \
@@ -213,6 +238,7 @@ typedef struct
#define kNumStates 12
+
typedef struct
{
CLzmaProb choice;
@@ -222,14 +248,16 @@ typedef struct
CLzmaProb high[kLenNumHighSymbols];
} CLenEnc;
+
typedef struct
{
CLenEnc p;
- UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
UInt32 tableSize;
+ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
UInt32 counters[LZMA_NUM_PB_STATES_MAX];
} CLenPriceEnc;
+
typedef struct
{
UInt32 range;
@@ -244,10 +272,14 @@ typedef struct
SRes res;
} CRangeEnc;
+
typedef struct
{
CLzmaProb *litProbs;
+ UInt32 state;
+ UInt32 reps[LZMA_NUM_REPS];
+
CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
CLzmaProb isRep[kNumStates];
CLzmaProb isRepG0[kNumStates];
@@ -261,15 +293,49 @@ typedef struct
CLenPriceEnc lenEnc;
CLenPriceEnc repLenEnc;
-
- UInt32 reps[LZMA_NUM_REPS];
- UInt32 state;
} CSaveState;
+
typedef struct
{
- IMatchFinder matchFinder;
void *matchFinderObj;
+ IMatchFinder matchFinder;
+
+ UInt32 optimumEndIndex;
+ UInt32 optimumCurrentIndex;
+
+ UInt32 longestMatchLength;
+ UInt32 numPairs;
+ UInt32 numAvail;
+
+ UInt32 numFastBytes;
+ UInt32 additionalOffset;
+ UInt32 reps[LZMA_NUM_REPS];
+ UInt32 state;
+
+ unsigned lc, lp, pb;
+ unsigned lpMask, pbMask;
+ unsigned lclp;
+
+ CLzmaProb *litProbs;
+
+ Bool fastMode;
+ Bool writeEndMark;
+ Bool finished;
+ Bool multiThread;
+ Bool needInit;
+
+ UInt64 nowPos64;
+
+ UInt32 matchPriceCount;
+ UInt32 alignPriceCount;
+
+ UInt32 distTableSize;
+
+ UInt32 dictSize;
+ SRes result;
+
+ CRangeEnc rc;
#ifndef _7ZIP_ST
Bool mtMode;
@@ -282,12 +348,6 @@ typedef struct
Byte pad[128];
#endif
- UInt32 optimumEndIndex;
- UInt32 optimumCurrentIndex;
-
- UInt32 longestMatchLength;
- UInt32 numPairs;
- UInt32 numAvail;
COptimal opt[kNumOpts];
#ifndef LZMA_LOG_BSR
@@ -296,22 +356,10 @@ typedef struct
UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
- UInt32 numFastBytes;
- UInt32 additionalOffset;
- UInt32 reps[LZMA_NUM_REPS];
- UInt32 state;
UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
UInt32 alignPrices[kAlignTableSize];
- UInt32 alignPriceCount;
-
- UInt32 distTableSize;
-
- unsigned lc, lp, pb;
- unsigned lpMask, pbMask;
-
- CLzmaProb *litProbs;
CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
CLzmaProb isRep[kNumStates];
@@ -327,26 +375,14 @@ typedef struct
CLenPriceEnc lenEnc;
CLenPriceEnc repLenEnc;
- unsigned lclp;
-
- Bool fastMode;
-
- CRangeEnc rc;
-
- Bool writeEndMark;
- UInt64 nowPos64;
- UInt32 matchPriceCount;
- Bool finished;
- Bool multiThread;
-
- SRes result;
- UInt32 dictSize;
-
- int needInit;
-
CSaveState saveState;
+
+ #ifndef _7ZIP_ST
+ Byte pad2[128];
+ #endif
} CLzmaEnc;
+
void LzmaEnc_SaveState(CLzmaEncHandle pp)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
@@ -370,7 +406,7 @@ void LzmaEnc_SaveState(CLzmaEncHandle pp)
memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
memcpy(dest->reps, p->reps, sizeof(p->reps));
- memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
+ memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));
}
void LzmaEnc_RestoreState(CLzmaEncHandle pp)
@@ -396,7 +432,7 @@ void LzmaEnc_RestoreState(CLzmaEncHandle pp)
memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
memcpy(dest->reps, p->reps, sizeof(p->reps));
- memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
+ memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));
}
SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
@@ -405,9 +441,13 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
CLzmaEncProps props = *props2;
LzmaEncProps_Normalize(&props);
- if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
- props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))
+ if (props.lc > LZMA_LC_MAX
+ || props.lp > LZMA_LP_MAX
+ || props.pb > LZMA_PB_MAX
+ || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)
+ || props.dictSize > kMaxHistorySize)
return SZ_ERROR_PARAM;
+
p->dictSize = props.dictSize;
{
unsigned fb = props.fb;
@@ -421,7 +461,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
p->lp = props.lp;
p->pb = props.pb;
p->fastMode = (props.algo == 0);
- p->matchFinderBase.btMode = props.btMode;
+ p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
{
UInt32 numHashBytes = 4;
if (props.btMode)
@@ -607,7 +647,7 @@ static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol,
while (symbol < 0x10000);
}
-void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
+static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
{
UInt32 i;
for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
@@ -643,7 +683,7 @@ void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
-static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const UInt32 *ProbPrices)
{
UInt32 price = 0;
symbol |= 0x100;
@@ -656,7 +696,7 @@ static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *Pro
return price;
}
-static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const UInt32 *ProbPrices)
{
UInt32 price = 0;
UInt32 offs = 0x100;
@@ -700,7 +740,7 @@ static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLeve
}
}
-static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)
{
UInt32 price = 0;
symbol |= (1 << numBitLevels);
@@ -712,7 +752,7 @@ static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 s
return price;
}
-static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, const UInt32 *ProbPrices)
{
UInt32 price = 0;
UInt32 m = 1;
@@ -763,7 +803,7 @@ static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posSt
}
}
-static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, const UInt32 *ProbPrices)
{
UInt32 a0 = GET_PRICE_0a(p->choice);
UInt32 a1 = GET_PRICE_1a(p->choice);
@@ -786,20 +826,20 @@ static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UIn
prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
}
-static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, const UInt32 *ProbPrices)
{
LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
p->counters[posState] = p->tableSize;
}
-static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, const UInt32 *ProbPrices)
{
UInt32 posState;
for (posState = 0; posState < numPosStates; posState++)
LenPriceEnc_UpdateTable(p, posState, ProbPrices);
}
-static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, const UInt32 *ProbPrices)
{
LenEnc_Encode(&p->p, rc, symbol, posState);
if (updatePrice)
@@ -845,14 +885,16 @@ static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
lenRes = p->matches[numPairs - 2];
if (lenRes == p->numFastBytes)
{
- const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
- UInt32 distance = p->matches[numPairs - 1] + 1;
UInt32 numAvail = p->numAvail;
if (numAvail > LZMA_MATCH_LEN_MAX)
numAvail = LZMA_MATCH_LEN_MAX;
{
- const Byte *pby2 = pby - distance;
- for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
+ const Byte *pbyCur = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ const Byte *pby = pbyCur + lenRes;
+ ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[numPairs - 1];
+ const Byte *pbyLim = pbyCur + numAvail;
+ for (; pby != pbyLim && *pby == pby[dif]; pby++);
+ lenRes = (UInt32)(pby - pbyCur);
}
}
}
@@ -937,7 +979,7 @@ static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
return p->optimumCurrentIndex;
}
-#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * (UInt32)0x300)
static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
{
@@ -981,7 +1023,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
UInt32 lenTest;
const Byte *data2;
reps[i] = p->reps[i];
- data2 = data - (reps[i] + 1);
+ data2 = data - reps[i] - 1;
if (data[0] != data2[0] || data[1] != data2[1])
{
repLens[i] = 0;
@@ -1282,7 +1324,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
/* try Literal + rep0 */
UInt32 temp;
UInt32 lenTest2;
- const Byte *data2 = data - (reps[0] + 1);
+ const Byte *data2 = data - reps[0] - 1;
UInt32 limit = p->numFastBytes + 1;
if (limit > numAvailFull)
limit = numAvailFull;
@@ -1325,7 +1367,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
UInt32 lenTest;
UInt32 lenTestTemp;
UInt32 price;
- const Byte *data2 = data - (reps[repIndex] + 1);
+ const Byte *data2 = data - reps[repIndex] - 1;
if (data[0] != data2[0] || data[1] != data2[1])
continue;
for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
@@ -1442,7 +1484,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
if (/*_maxMode && */lenTest == matches[offs])
{
/* Try Match + Literal + Rep0 */
- const Byte *data2 = data - (curBack + 1);
+ const Byte *data2 = data - curBack - 1;
UInt32 lenTest2 = lenTest + 1;
UInt32 limit = lenTest2 + p->numFastBytes;
UInt32 nextRepMatchPrice;
@@ -1525,7 +1567,7 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
for (i = 0; i < LZMA_NUM_REPS; i++)
{
UInt32 len;
- const Byte *data2 = data - (p->reps[i] + 1);
+ const Byte *data2 = data - p->reps[i] - 1;
if (data[0] != data2[0] || data[1] != data2[1])
continue;
for (len = 2; len < numAvail && data[len] == data2[len]; len++);
@@ -1594,7 +1636,7 @@ static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
for (i = 0; i < LZMA_NUM_REPS; i++)
{
UInt32 len, limit;
- const Byte *data2 = data - (p->reps[i] + 1);
+ const Byte *data2 = data - p->reps[i] - 1;
if (data[0] != data2[0] || data[1] != data2[1])
continue;
limit = mainLen - 1;
@@ -1690,6 +1732,7 @@ void LzmaEnc_Construct(CLzmaEnc *p)
{
RangeEnc_Construct(&p->rc);
MatchFinder_Construct(&p->matchFinderBase);
+
#ifndef _7ZIP_ST
MatchFinderMt_Construct(&p->matchFinderMt);
p->matchFinderMt.MatchFinder = &p->matchFinderBase;
@@ -1732,6 +1775,7 @@ void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
#ifndef _7ZIP_ST
MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
#endif
+
MatchFinder_Free(&p->matchFinderBase, allocBig);
LzmaEnc_FreeLits(p, alloc);
RangeEnc_Free(&p->rc, alloc);
@@ -1768,7 +1812,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
ReadMatchDistances(p, &numPairs);
RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
p->state = kLiteralNextStates[p->state];
- curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
+ curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
LitEnc_Encode(&p->rc, p->litProbs, curByte);
p->additionalOffset--;
nowPos32++;
@@ -1894,7 +1938,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
break;
}
- else if (processed >= (1 << 15))
+ else if (processed >= (1 << 17))
{
p->nowPos64 += nowPos32 - startPos32;
return CheckErrors(p);
@@ -1912,6 +1956,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
UInt32 beforeSize = kNumOpts;
if (!RangeEnc_Alloc(&p->rc, alloc))
return SZ_ERROR_MEM;
+
#ifndef _7ZIP_ST
p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
#endif
@@ -1921,8 +1966,8 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
{
LzmaEnc_FreeLits(p, alloc);
- p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
- p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
+ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
if (p->litProbs == 0 || p->saveState.litProbs == 0)
{
LzmaEnc_FreeLits(p, alloc);
@@ -1932,7 +1977,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
}
}
- p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
+ p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
if (beforeSize + p->dictSize < keepWindowSize)
beforeSize = keepWindowSize - p->dictSize;
@@ -1952,6 +1997,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I
p->matchFinderObj = &p->matchFinderBase;
MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
}
+
return SZ_OK;
}
@@ -1980,9 +2026,10 @@ void LzmaEnc_Init(CLzmaEnc *p)
}
{
- UInt32 num = 0x300 << (p->lp + p->lc);
+ UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
+ CLzmaProb *probs = p->litProbs;
for (i = 0; i < num; i++)
- p->litProbs[i] = kProbInitValue;
+ probs[i] = kProbInitValue;
}
{
@@ -2089,7 +2136,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
if (p->mtMode)
MatchFinderMt_ReleaseStream(&p->matchFinderMt);
#else
- pp = pp;
+ UNUSED_VAR(pp);
#endif
}
@@ -2201,25 +2248,23 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
- int i;
+ unsigned i;
UInt32 dictSize = p->dictSize;
if (*size < LZMA_PROPS_SIZE)
return SZ_ERROR_PARAM;
*size = LZMA_PROPS_SIZE;
props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
- for (i = 11; i <= 30; i++)
+ if (dictSize >= ((UInt32)1 << 22))
{
- if (dictSize <= ((UInt32)2 << i))
- {
- dictSize = (2 << i);
- break;
- }
- if (dictSize <= ((UInt32)3 << i))
- {
- dictSize = (3 << i);
- break;
- }
+ UInt32 kDictMask = ((UInt32)1 << 20) - 1;
+ if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)
+ dictSize = (dictSize + kDictMask) & ~kDictMask;
+ }
+ else for (i = 11; i <= 30; i++)
+ {
+ if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }
+ if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }
}
for (i = 0; i < 4; i++)
diff --git a/C/LzmaLib.c b/C/LzmaLib.c
index 02a51185..706e9e58 100644
--- a/C/LzmaLib.c
+++ b/C/LzmaLib.c
@@ -1,18 +1,12 @@
/* LzmaLib.c -- LZMA library wrapper
-2008-08-05
-Igor Pavlov
-Public domain */
+2015-06-13 : Igor Pavlov : Public domain */
-#include "LzmaEnc.h"
-#include "LzmaDec.h"
#include "Alloc.h"
+#include "LzmaDec.h"
+#include "LzmaEnc.h"
#include "LzmaLib.h"
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
-MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
+MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
unsigned char *outProps, size_t *outPropsSize,
int level, /* 0 <= level <= 9, default = 5 */
unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
@@ -38,7 +32,7 @@ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned cha
}
-MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,
+MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,
const unsigned char *props, size_t propsSize)
{
ELzmaStatus status;
diff --git a/C/RotateDefs.h b/C/RotateDefs.h
index 1b83e5ea..8f01d1a6 100644
--- a/C/RotateDefs.h
+++ b/C/RotateDefs.h
@@ -1,5 +1,5 @@
/* RotateDefs.h -- Rotate functions
-2013-11-12 : Igor Pavlov : Public domain */
+2015-03-25 : Igor Pavlov : Public domain */
#ifndef __ROTATE_DEFS_H
#define __ROTATE_DEFS_H
@@ -8,16 +8,20 @@
#include <stdlib.h>
-// #if (_MSC_VER >= 1200)
+/* don't use _rotl with MINGW. It can insert slow call to function. */
+
+/* #if (_MSC_VER >= 1200) */
#pragma intrinsic(_rotl)
#pragma intrinsic(_rotr)
-// #endif
+/* #endif */
#define rotlFixed(x, n) _rotl((x), (n))
#define rotrFixed(x, n) _rotr((x), (n))
#else
+/* new compilers can translate these macros to fast commands. */
+
#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
diff --git a/C/Sha1.c b/C/Sha1.c
new file mode 100644
index 00000000..785c7064
--- /dev/null
+++ b/C/Sha1.c
@@ -0,0 +1,334 @@
+/* Sha1.c -- SHA-1 Hash
+2015-05-10 : Igor Pavlov : Public domain
+This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
+
+#include "Precomp.h"
+
+#include <string.h>
+
+#include "CpuArch.h"
+#include "RotateDefs.h"
+#include "Sha1.h"
+
+// define it for speed optimization
+// #define _SHA1_UNROLL
+
+#ifdef _SHA1_UNROLL
+ #define kNumW 16
+ #define WW(i) W[(i)&15]
+#else
+ #define kNumW 80
+ #define WW(i) W[i]
+#endif
+
+#define w0(i) (W[i] = data[i])
+
+#define w1(i) (WW(i) = rotlFixed(WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16), 1))
+
+#define f1(x,y,z) (z^(x&(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+
+#define RK(a,b,c,d,e, fx, w, k) e += fx(b,c,d) + w + k + rotlFixed(a,5); b = rotlFixed(b,30);
+
+#define R0(a,b,c,d,e, i) RK(a,b,c,d,e, f1, w0(i), 0x5A827999)
+#define R1(a,b,c,d,e, i) RK(a,b,c,d,e, f1, w1(i), 0x5A827999)
+#define R2(a,b,c,d,e, i) RK(a,b,c,d,e, f2, w1(i), 0x6ED9EBA1)
+#define R3(a,b,c,d,e, i) RK(a,b,c,d,e, f3, w1(i), 0x8F1BBCDC)
+#define R4(a,b,c,d,e, i) RK(a,b,c,d,e, f4, w1(i), 0xCA62C1D6)
+
+#define RX_1_4(rx1, rx4, i) \
+ rx1(a,b,c,d,e, i); \
+ rx4(e,a,b,c,d, i+1); \
+ rx4(d,e,a,b,c, i+2); \
+ rx4(c,d,e,a,b, i+3); \
+ rx4(b,c,d,e,a, i+4); \
+
+#define RX_5(rx, i) RX_1_4(rx, rx, i);
+
+#ifdef _SHA1_UNROLL
+
+ #define RX_15 \
+ RX_5(R0, 0); \
+ RX_5(R0, 5); \
+ RX_5(R0, 10);
+
+ #define RX_20(rx, i) \
+ RX_5(rx, i); \
+ RX_5(rx, i + 5); \
+ RX_5(rx, i + 10); \
+ RX_5(rx, i + 15);
+
+#else
+
+#define RX_15 { unsigned i; for (i = 0; i < 15; i += 5) { RX_5(R0, i); } }
+#define RX_20(rx, ii) { unsigned i; i = ii; for (; i < ii + 20; i += 5) { RX_5(rx, i); } }
+
+#endif
+
+
+void Sha1_Init(CSha1 *p)
+{
+ p->state[0] = 0x67452301;
+ p->state[1] = 0xEFCDAB89;
+ p->state[2] = 0x98BADCFE;
+ p->state[3] = 0x10325476;
+ p->state[4] = 0xC3D2E1F0;
+ p->count = 0;
+}
+
+void Sha1_GetBlockDigest(CSha1 *p, const UInt32 *data, UInt32 *destDigest)
+{
+ UInt32 a, b, c, d, e;
+ UInt32 W[kNumW];
+
+ a = p->state[0];
+ b = p->state[1];
+ c = p->state[2];
+ d = p->state[3];
+ e = p->state[4];
+
+ RX_15
+
+ RX_1_4(R0, R1, 15);
+
+ RX_20(R2, 20);
+ RX_20(R3, 40);
+ RX_20(R4, 60);
+
+ destDigest[0] = p->state[0] + a;
+ destDigest[1] = p->state[1] + b;
+ destDigest[2] = p->state[2] + c;
+ destDigest[3] = p->state[3] + d;
+ destDigest[4] = p->state[4] + e;
+}
+
+void Sha1_UpdateBlock_Rar(CSha1 *p, UInt32 *data, int returnRes)
+{
+ UInt32 a, b, c, d, e;
+ UInt32 W[kNumW];
+
+ a = p->state[0];
+ b = p->state[1];
+ c = p->state[2];
+ d = p->state[3];
+ e = p->state[4];
+
+ RX_15
+
+ RX_1_4(R0, R1, 15);
+
+ RX_20(R2, 20);
+ RX_20(R3, 40);
+ RX_20(R4, 60);
+
+ p->state[0] += a;
+ p->state[1] += b;
+ p->state[2] += c;
+ p->state[3] += d;
+ p->state[4] += e;
+
+ if (returnRes)
+ {
+ unsigned i;
+ for (i = 0 ; i < SHA1_NUM_BLOCK_WORDS; i++)
+ data[i] = W[kNumW - SHA1_NUM_BLOCK_WORDS + i];
+ }
+}
+
+#define Sha1_UpdateBlock(p) Sha1_GetBlockDigest(p, p->buffer, p->state)
+
+void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
+{
+ unsigned pos, pos2;
+ if (size == 0)
+ return;
+ pos = (unsigned)p->count & 0x3F;
+ p->count += size;
+ pos2 = pos & 3;
+ pos >>= 2;
+
+ if (pos2 != 0)
+ {
+ UInt32 w = ((UInt32)data[0]) << 24;
+ if (--size && pos2 < 3)
+ {
+ w |= ((UInt32)data[1]) << 16;
+ if (--size && pos2 < 2)
+ {
+ w |= ((UInt32)data[2]) << 8;
+ --size;
+ }
+ }
+ data += 4 - pos2;
+ p->buffer[pos++] |= (w >> (8 * pos2));
+ }
+
+ for (;;)
+ {
+ if (pos == SHA1_NUM_BLOCK_WORDS)
+ {
+ for (;;)
+ {
+ unsigned i;
+ Sha1_UpdateBlock(p);
+ if (size < SHA1_BLOCK_SIZE)
+ break;
+ size -= SHA1_BLOCK_SIZE;
+ for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i += 2)
+ {
+ p->buffer[i ] = GetBe32(data);
+ p->buffer[i + 1] = GetBe32(data + 4);
+ data += 8;
+ }
+ }
+ pos = 0;
+ }
+ if (size < 4)
+ break;
+
+ p->buffer[pos] = GetBe32(data);
+ data += 4;
+ size -= 4;
+ pos++;
+ }
+
+ if (size != 0)
+ {
+ UInt32 w = ((UInt32)data[0]) << 24;
+ if (size > 1)
+ {
+ w |= ((UInt32)data[1]) << 16;
+ if (size > 2)
+ w |= ((UInt32)data[2]) << 8;
+ }
+ p->buffer[pos] = w;
+ }
+}
+
+void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size, int rar350Mode)
+{
+ int returnRes = False;
+
+ unsigned pos = (unsigned)p->count & 0x3F;
+ p->count += size;
+
+ while (size--)
+ {
+ unsigned pos2 = (pos & 3);
+ UInt32 v = ((UInt32)*data++) << (8 * (3 - pos2));
+ UInt32 *ref = &(p->buffer[pos >> 2]);
+ pos++;
+ if (pos2 == 0)
+ {
+ *ref = v;
+ continue;
+ }
+ *ref |= v;
+
+ if (pos == SHA1_BLOCK_SIZE)
+ {
+ pos = 0;
+ Sha1_UpdateBlock_Rar(p, p->buffer, returnRes);
+ if (returnRes)
+ {
+ unsigned i;
+ for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
+ {
+ UInt32 d = p->buffer[i];
+ Byte *prev = data + i * 4 - SHA1_BLOCK_SIZE;
+ SetUi32(prev, d);
+ }
+ }
+ returnRes = rar350Mode;
+ }
+ }
+}
+
+void Sha1_Final(CSha1 *p, Byte *digest)
+{
+ unsigned pos = (unsigned)p->count & 0x3F;
+ unsigned pos2 = (pos & 3);
+ UInt64 numBits;
+ UInt32 w;
+ unsigned i;
+
+ pos >>= 2;
+
+ w = 0;
+ if (pos2 != 0)
+ w = p->buffer[pos];
+ p->buffer[pos++] = w | (((UInt32)0x80000000) >> (8 * pos2));
+
+ while (pos != (SHA1_NUM_BLOCK_WORDS - 2))
+ {
+ pos &= 0xF;
+ if (pos == 0)
+ Sha1_UpdateBlock(p);
+ p->buffer[pos++] = 0;
+ }
+
+ numBits = (p->count << 3);
+ p->buffer[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
+ p->buffer[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
+ Sha1_UpdateBlock(p);
+
+ for (i = 0; i < SHA1_NUM_DIGEST_WORDS; i++)
+ {
+ UInt32 v = p->state[i];
+ SetBe32(digest, v);
+ digest += 4;
+ }
+
+ Sha1_Init(p);
+}
+
+
+void Sha1_32_PrepareBlock(const CSha1 *p, UInt32 *block, unsigned size)
+{
+ const UInt64 numBits = (p->count + size) << 5;
+ block[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
+ block[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
+ block[size++] = 0x80000000;
+ while (size != (SHA1_NUM_BLOCK_WORDS - 2))
+ block[size++] = 0;
+}
+
+void Sha1_32_Update(CSha1 *p, const UInt32 *data, size_t size)
+{
+ unsigned pos = (unsigned)p->count & 0xF;
+ p->count += size;
+ while (size--)
+ {
+ p->buffer[pos++] = *data++;
+ if (pos == SHA1_NUM_BLOCK_WORDS)
+ {
+ pos = 0;
+ Sha1_UpdateBlock(p);
+ }
+ }
+}
+
+void Sha1_32_Final(CSha1 *p, UInt32 *digest)
+{
+ UInt64 numBits;
+ unsigned pos = (unsigned)p->count & 0xF;
+ p->buffer[pos++] = 0x80000000;
+
+ while (pos != (SHA1_NUM_BLOCK_WORDS - 2))
+ {
+ pos &= 0xF;
+ if (pos == 0)
+ Sha1_UpdateBlock(p);
+ p->buffer[pos++] = 0;
+ }
+
+ numBits = (p->count << 5);
+ p->buffer[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
+ p->buffer[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
+
+ Sha1_GetBlockDigest(p, p->buffer, digest);
+
+ Sha1_Init(p);
+}
diff --git a/C/Sha1.h b/C/Sha1.h
new file mode 100644
index 00000000..e578a826
--- /dev/null
+++ b/C/Sha1.h
@@ -0,0 +1,38 @@
+/* Sha1.h -- SHA-1 Hash
+2015-03-04 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_SHA1_H
+#define __7Z_SHA1_H
+
+#include "7zTypes.h"
+
+EXTERN_C_BEGIN
+
+#define SHA1_NUM_BLOCK_WORDS 16
+#define SHA1_NUM_DIGEST_WORDS 5
+
+#define SHA1_BLOCK_SIZE (SHA1_NUM_BLOCK_WORDS * 4)
+#define SHA1_DIGEST_SIZE (SHA1_NUM_DIGEST_WORDS * 4)
+
+typedef struct
+{
+ UInt32 state[SHA1_NUM_DIGEST_WORDS];
+ UInt64 count;
+ UInt32 buffer[SHA1_NUM_BLOCK_WORDS];
+} CSha1;
+
+void Sha1_Init(CSha1 *p);
+
+void Sha1_GetBlockDigest(CSha1 *p, const UInt32 *data, UInt32 *destDigest);
+void Sha1_Update(CSha1 *p, const Byte *data, size_t size);
+void Sha1_Final(CSha1 *p, Byte *digest);
+
+void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size, int rar350Mode);
+
+void Sha1_32_PrepareBlock(const CSha1 *p, UInt32 *block, unsigned size);
+void Sha1_32_Update(CSha1 *p, const UInt32 *data, size_t size);
+void Sha1_32_Final(CSha1 *p, UInt32 *digest);
+
+EXTERN_C_END
+
+#endif
diff --git a/C/Sha256.c b/C/Sha256.c
index db0c7061..3a8cc41a 100644
--- a/C/Sha256.c
+++ b/C/Sha256.c
@@ -1,14 +1,21 @@
/* Crypto/Sha256.c -- SHA-256 Hash
-2010-06-11 : Igor Pavlov : Public domain
+2015-03-02 : Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Precomp.h"
+#include <string.h>
+
+#include "CpuArch.h"
#include "RotateDefs.h"
#include "Sha256.h"
/* define it for speed optimization */
-/* #define _SHA256_UNROLL */
+#ifndef _SFX
+#define _SHA256_UNROLL
+#define _SHA256_UNROLL2
+#endif
+
/* #define _SHA256_UNROLL2 */
void Sha256_Init(CSha256 *p)
@@ -29,26 +36,18 @@ void Sha256_Init(CSha256 *p)
#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))
#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))
-#define blk0(i) (W[i] = data[i])
-#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))
+#define blk0(i) (W[i])
+#define blk2(i) (W[i] += s1(W[((i)-2)&15]) + W[((i)-7)&15] + s0(W[((i)-15)&15]))
#define Ch(x,y,z) (z^(x&(y^z)))
#define Maj(x,y,z) ((x&y)|(z&(x|y)))
-#define a(i) T[(0-(i))&7]
-#define b(i) T[(1-(i))&7]
-#define c(i) T[(2-(i))&7]
-#define d(i) T[(3-(i))&7]
-#define e(i) T[(4-(i))&7]
-#define f(i) T[(5-(i))&7]
-#define g(i) T[(6-(i))&7]
-#define h(i) T[(7-(i))&7]
-
-
#ifdef _SHA256_UNROLL2
-#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\
- d += h; h += S0(a) + Maj(a, b, c)
+#define R(a,b,c,d,e,f,g,h, i) \
+ h += S1(e) + Ch(e,f,g) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \
+ d += h; \
+ h += S0(a) + Maj(a, b, c)
#define RX_8(i) \
R(a,b,c,d,e,f,g,h, i); \
@@ -60,14 +59,32 @@ void Sha256_Init(CSha256 *p)
R(c,d,e,f,g,h,a,b, i+6); \
R(b,c,d,e,f,g,h,a, i+7)
+#define RX_16 RX_8(0); RX_8(8);
+
#else
-#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\
- d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
+#define a(i) T[(0-(i))&7]
+#define b(i) T[(1-(i))&7]
+#define c(i) T[(2-(i))&7]
+#define d(i) T[(3-(i))&7]
+#define e(i) T[(4-(i))&7]
+#define f(i) T[(5-(i))&7]
+#define g(i) T[(6-(i))&7]
+#define h(i) T[(7-(i))&7]
+
+#define R(i) \
+ h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+(j)] + (j ? blk2(i) : blk0(i)); \
+ d(i) += h(i); \
+ h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) \
#ifdef _SHA256_UNROLL
-#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);
+#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);
+#define RX_16 RX_8(0); RX_8(8);
+
+#else
+
+#define RX_16 unsigned i; for (i = 0; i < 16; i++) { R(i); }
#endif
@@ -92,10 +109,12 @@ static const UInt32 K[64] = {
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
-static void Sha256_Transform(UInt32 *state, const UInt32 *data)
+static void Sha256_WriteByteBlock(CSha256 *p)
{
UInt32 W[16];
unsigned j;
+ UInt32 *state = p->state;
+
#ifdef _SHA256_UNROLL2
UInt32 a,b,c,d,e,f,g,h;
a = state[0];
@@ -112,14 +131,15 @@ static void Sha256_Transform(UInt32 *state, const UInt32 *data)
T[j] = state[j];
#endif
+ for (j = 0; j < 16; j += 2)
+ {
+ W[j ] = GetBe32(p->buffer + j * 4);
+ W[j + 1] = GetBe32(p->buffer + j * 4 + 4);
+ }
+
for (j = 0; j < 64; j += 16)
{
- #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)
- RX_8(0); RX_8(8);
- #else
- unsigned i;
- for (i = 0; i < 16; i++) { R(i); }
- #endif
+ RX_16
}
#ifdef _SHA256_UNROLL2
@@ -146,61 +166,72 @@ static void Sha256_Transform(UInt32 *state, const UInt32 *data)
#undef s0
#undef s1
-static void Sha256_WriteByteBlock(CSha256 *p)
-{
- UInt32 data32[16];
- unsigned i;
- for (i = 0; i < 16; i++)
- data32[i] =
- ((UInt32)(p->buffer[i * 4 ]) << 24) +
- ((UInt32)(p->buffer[i * 4 + 1]) << 16) +
- ((UInt32)(p->buffer[i * 4 + 2]) << 8) +
- ((UInt32)(p->buffer[i * 4 + 3]));
- Sha256_Transform(p->state, data32);
-}
-
void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
{
- UInt32 curBufferPos = (UInt32)p->count & 0x3F;
- while (size > 0)
+ if (size == 0)
+ return;
+
{
- p->buffer[curBufferPos++] = *data++;
- p->count++;
- size--;
- if (curBufferPos == 64)
+ unsigned pos = (unsigned)p->count & 0x3F;
+ unsigned num;
+
+ p->count += size;
+
+ num = 64 - pos;
+ if (num > size)
{
- curBufferPos = 0;
- Sha256_WriteByteBlock(p);
+ memcpy(p->buffer + pos, data, size);
+ return;
}
+
+ size -= num;
+ memcpy(p->buffer + pos, data, num);
+ data += num;
+ }
+
+ for (;;)
+ {
+ Sha256_WriteByteBlock(p);
+ if (size < 64)
+ break;
+ size -= 64;
+ memcpy(p->buffer, data, 64);
+ data += 64;
}
+
+ if (size != 0)
+ memcpy(p->buffer, data, size);
}
void Sha256_Final(CSha256 *p, Byte *digest)
{
- UInt64 lenInBits = (p->count << 3);
- UInt32 curBufferPos = (UInt32)p->count & 0x3F;
+ unsigned pos = (unsigned)p->count & 0x3F;
unsigned i;
- p->buffer[curBufferPos++] = 0x80;
- while (curBufferPos != (64 - 8))
+
+ p->buffer[pos++] = 0x80;
+
+ while (pos != (64 - 8))
{
- curBufferPos &= 0x3F;
- if (curBufferPos == 0)
+ pos &= 0x3F;
+ if (pos == 0)
Sha256_WriteByteBlock(p);
- p->buffer[curBufferPos++] = 0;
+ p->buffer[pos++] = 0;
}
- for (i = 0; i < 8; i++)
+
{
- p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56);
- lenInBits <<= 8;
+ UInt64 numBits = (p->count << 3);
+ SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32));
+ SetBe32(p->buffer + 64 - 4, (UInt32)(numBits));
}
+
Sha256_WriteByteBlock(p);
for (i = 0; i < 8; i++)
{
- *digest++ = (Byte)(p->state[i] >> 24);
- *digest++ = (Byte)(p->state[i] >> 16);
- *digest++ = (Byte)(p->state[i] >> 8);
- *digest++ = (Byte)(p->state[i]);
+ UInt32 v = p->state[i];
+ SetBe32(digest, v);
+ digest += 4;
}
+
Sha256_Init(p);
}
diff --git a/C/Threads.c b/C/Threads.c
index d71e13a4..d3d0912d 100644
--- a/C/Threads.c
+++ b/C/Threads.c
@@ -1,9 +1,9 @@
/* Threads.c -- multithreading library
-2013-11-12 : Igor Pavlov : Public domain */
+2014-09-21 : Igor Pavlov : Public domain */
#include "Precomp.h"
-#ifndef _WIN32_WCE
+#ifndef UNDER_CE
#include <process.h>
#endif
diff --git a/C/Util/7z/7z.dsp b/C/Util/7z/7z.dsp
index 92818667..be0f0a74 100644
--- a/C/Util/7z/7z.dsp
+++ b/C/Util/7z/7z.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /Yu"Precomp.h" /FD /c
+# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAcs /Yu"Precomp.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
@@ -165,6 +165,10 @@ SOURCE=..\..\Bra86.c
# End Source File
# Begin Source File
+SOURCE=..\..\BraIA64.c
+# End Source File
+# Begin Source File
+
SOURCE=..\..\CpuArch.c
# End Source File
# Begin Source File
@@ -173,6 +177,14 @@ SOURCE=..\..\CpuArch.h
# End Source File
# Begin Source File
+SOURCE=..\..\Delta.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Delta.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Lzma2Dec.c
# End Source File
# Begin Source File
diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c
index 8ba02efd..c1e49bf4 100644
--- a/C/Util/7z/7zMain.c
+++ b/C/Util/7z/7zMain.c
@@ -1,5 +1,5 @@
/* 7zMain.c - Test application for 7z Decoder
-2015-01-02 : Igor Pavlov : Public domain */
+2015-05-11 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -34,75 +34,117 @@ static int Buf_EnsureSize(CBuf *dest, size_t size)
}
#ifndef _WIN32
+#define _USE_UTF8
+#endif
+
+/* #define _USE_UTF8 */
+
+#ifdef _USE_UTF8
-static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+#define _UTF8_START(n) (0x100 - (1 << (7 - (n))))
-static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen)
+#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))
+
+#define _UTF8_HEAD(n, val) ((Byte)(_UTF8_START(n) + (val >> (6 * (n)))))
+#define _UTF8_CHAR(n, val) ((Byte)(0x80 + (((val) >> (6 * (n))) & 0x3F)))
+
+static size_t Utf16_To_Utf8_Calc(const UInt16 *src, const UInt16 *srcLim)
{
- size_t destPos = 0, srcPos = 0;
+ size_t size = 0;
for (;;)
{
- unsigned numAdds;
- UInt32 value;
- if (srcPos == srcLen)
+ UInt32 val;
+ if (src == srcLim)
+ return size;
+
+ size++;
+ val = *src++;
+
+ if (val < 0x80)
+ continue;
+
+ if (val < _UTF8_RANGE(1))
{
- *destLen = destPos;
- return True;
+ size++;
+ continue;
}
- value = src[srcPos++];
- if (value < 0x80)
+
+ if (val >= 0xD800 && val < 0xDC00 && src != srcLim)
+ {
+ UInt32 c2 = *src;
+ if (c2 >= 0xDC00 && c2 < 0xE000)
+ {
+ src++;
+ size += 3;
+ continue;
+ }
+ }
+
+ size += 2;
+ }
+}
+
+static Byte *Utf16_To_Utf8(Byte *dest, const UInt16 *src, const UInt16 *srcLim)
+{
+ for (;;)
+ {
+ UInt32 val;
+ if (src == srcLim)
+ return dest;
+
+ val = *src++;
+
+ if (val < 0x80)
{
- if (dest)
- dest[destPos] = (char)value;
- destPos++;
+ *dest++ = (char)val;
continue;
}
- if (value >= 0xD800 && value < 0xE000)
+
+ if (val < _UTF8_RANGE(1))
{
- UInt32 c2;
- if (value >= 0xDC00 || srcPos == srcLen)
- break;
- c2 = src[srcPos++];
- if (c2 < 0xDC00 || c2 >= 0xE000)
- break;
- value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
+ dest[0] = _UTF8_HEAD(1, val);
+ dest[1] = _UTF8_CHAR(0, val);
+ dest += 2;
+ continue;
}
- for (numAdds = 1; numAdds < 5; numAdds++)
- if (value < (((UInt32)1) << (numAdds * 5 + 6)))
- break;
- if (dest)
- dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
- destPos++;
- do
+
+ if (val >= 0xD800 && val < 0xDC00 && src != srcLim)
{
- numAdds--;
- if (dest)
- dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
- destPos++;
+ UInt32 c2 = *src;
+ if (c2 >= 0xDC00 && c2 < 0xE000)
+ {
+ src++;
+ val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
+ dest[0] = _UTF8_HEAD(3, val);
+ dest[1] = _UTF8_CHAR(2, val);
+ dest[2] = _UTF8_CHAR(1, val);
+ dest[3] = _UTF8_CHAR(0, val);
+ dest += 4;
+ continue;
+ }
}
- while (numAdds != 0);
+
+ dest[0] = _UTF8_HEAD(2, val);
+ dest[1] = _UTF8_CHAR(1, val);
+ dest[2] = _UTF8_CHAR(0, val);
+ dest += 3;
}
- *destLen = destPos;
- return False;
}
static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen)
{
- size_t destLen = 0;
- Bool res;
- Utf16_To_Utf8(NULL, &destLen, src, srcLen);
+ size_t destLen = Utf16_To_Utf8_Calc(src, src + srcLen);
destLen += 1;
if (!Buf_EnsureSize(dest, destLen))
return SZ_ERROR_MEM;
- res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);
- dest->data[destLen] = 0;
- return res ? SZ_OK : SZ_ERROR_FAIL;
+ *Utf16_To_Utf8(dest->data, src, src + srcLen) = 0;
+ return SZ_OK;
}
#endif
static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
- #ifdef _WIN32
+ #ifndef _USE_UTF8
, UINT codePage
#endif
)
@@ -110,7 +152,7 @@ static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
unsigned len = 0;
for (len = 0; s[len] != 0; len++);
- #ifdef _WIN32
+ #ifndef _USE_UTF8
{
unsigned size = len * 3 + 100;
if (!Buf_EnsureSize(buf, size))
@@ -191,7 +233,7 @@ static SRes PrintString(const UInt16 *s)
SRes res;
Buf_Init(&buf);
res = Utf16_To_Char(&buf, s
- #ifdef _WIN32
+ #ifndef _USE_UTF8
, CP_OEMCP
#endif
);
@@ -281,7 +323,7 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s)
UIntToStr_2(s, sec); s[2] = 0;
}
-void PrintError(const char *sz)
+void PrintError(char *sz)
{
printf("\nERROR: %s\n", sz);
}
@@ -318,6 +360,7 @@ int MY_CDECL main(int numargs, char *args[])
// UInt32 parents[NUM_PARENTS_MAX];
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");
+
if (numargs == 1)
{
printf(
@@ -329,6 +372,7 @@ int MY_CDECL main(int numargs, char *args[])
" x: eXtract files with full paths\n");
return 0;
}
+
if (numargs < 3)
{
PrintError("incorrect command");
@@ -364,11 +408,14 @@ int MY_CDECL main(int numargs, char *args[])
CrcGenerateTable();
SzArEx_Init(&db);
+
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
+
if (res == SZ_OK)
{
char *command = args[1];
int listCommand = 0, testCommand = 0, fullPaths = 0;
+
if (strcmp(command, "l") == 0) listCommand = 1;
else if (strcmp(command, "t") == 0) testCommand = 1;
else if (strcmp(command, "e") == 0) { }
@@ -397,7 +444,7 @@ int MY_CDECL main(int numargs, char *args[])
size_t outSizeProcessed = 0;
// const CSzFileItem *f = db.Files + i;
size_t len;
- int isDir = SzArEx_IsDir(&db, i);
+ unsigned isDir = SzArEx_IsDir(&db, i);
if (listCommand == 0 && isDir && !fullPaths)
continue;
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
@@ -433,6 +480,7 @@ int MY_CDECL main(int numargs, char *args[])
fileSize = SzArEx_GetFileSize(&db, i);
UInt64ToStr(fileSize, s);
+
if (SzBitWithVals_Check(&db.MTime, i))
ConvertFileTimeToString(&db.MTime.Vals[i], t);
else
@@ -452,6 +500,7 @@ int MY_CDECL main(int numargs, char *args[])
printf("\n");
continue;
}
+
fputs(testCommand ?
"Testing ":
"Extracting ",
@@ -459,6 +508,7 @@ int MY_CDECL main(int numargs, char *args[])
res = PrintString(temp);
if (res != SZ_OK)
break;
+
if (isDir)
printf("/");
else
@@ -470,6 +520,7 @@ int MY_CDECL main(int numargs, char *args[])
if (res != SZ_OK)
break;
}
+
if (!testCommand)
{
CSzFile outFile;
@@ -477,6 +528,7 @@ int MY_CDECL main(int numargs, char *args[])
size_t j;
UInt16 *name = (UInt16 *)temp;
const UInt16 *destPath = (const UInt16 *)name;
+
for (j = 0; name[j] != 0; j++)
if (name[j] == '/')
{
@@ -502,19 +554,23 @@ int MY_CDECL main(int numargs, char *args[])
res = SZ_ERROR_FAIL;
break;
}
+
processedSize = outSizeProcessed;
+
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
{
PrintError("can not write output file");
res = SZ_ERROR_FAIL;
break;
}
+
if (File_Close(&outFile))
{
PrintError("can not close output file");
res = SZ_ERROR_FAIL;
break;
}
+
#ifdef USE_WINDOWS_FILE
if (SzBitWithVals_Check(&db.Attribs, i))
SetFileAttributesW(destPath, db.Attribs.Vals[i]);
@@ -525,15 +581,18 @@ int MY_CDECL main(int numargs, char *args[])
IAlloc_Free(&allocImp, outBuffer);
}
}
+
SzArEx_Free(&db, &allocImp);
SzFree(NULL, temp);
File_Close(&archiveStream.file);
+
if (res == SZ_OK)
{
printf("\nEverything is Ok\n");
return 0;
}
+
if (res == SZ_ERROR_UNSUPPORTED)
PrintError("decoder doesn't support this archive");
else if (res == SZ_ERROR_MEM)
@@ -542,5 +601,6 @@ int MY_CDECL main(int numargs, char *args[])
PrintError("CRC error");
else
printf("\nERROR #%d\n", res);
+
return 1;
}
diff --git a/C/Util/7z/makefile b/C/Util/7z/makefile
index e0aa1e37..9a49fd51 100644
--- a/C/Util/7z/makefile
+++ b/C/Util/7z/makefile
@@ -1,4 +1,3 @@
-# MY_STATIC_LINK=1
CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT
PROG = 7zDec.exe
@@ -15,7 +14,9 @@ C_OBJS = \
$O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
+ $O\BraIA64.obj \
$O\CpuArch.obj \
+ $O\Delta.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
$O\Ppmd7.obj \
diff --git a/C/Util/7zipInstall/7zip.ico b/C/Util/7zipInstall/7zip.ico
new file mode 100644
index 00000000..47ffb781
--- /dev/null
+++ b/C/Util/7zipInstall/7zip.ico
Binary files differ
diff --git a/C/Util/7zipInstall/7zipInstall.c b/C/Util/7zipInstall/7zipInstall.c
new file mode 100644
index 00000000..dc636d64
--- /dev/null
+++ b/C/Util/7zipInstall/7zipInstall.c
@@ -0,0 +1,1452 @@
+/* 7zipInnstall.c - 7-Zip Installer
+2015-06-13 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+#define SZ_ERROR_ABORT 100
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+#endif
+
+#include <windows.h>
+#include <ShlObj.h>
+
+#define LLL_(quote) L##quote
+#define LLL(quote) LLL_(quote)
+
+#include "../../7z.h"
+#include "../../7zAlloc.h"
+#include "../../7zCrc.h"
+#include "../../7zFile.h"
+#include "../../7zVersion.h"
+#include "../../CpuArch.h"
+
+#include "resource.h"
+
+static const WCHAR *k_7zip = L"7-Zip";
+
+static const WCHAR *k_Reg_Software_7zip = L"Software\\7-Zip";
+
+// #define _64BIT_INSTALLER 1
+
+#ifdef _WIN64
+ #define _64BIT_INSTALLER 1
+#endif
+
+#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
+
+#ifdef _64BIT_INSTALLER
+ #define k_7zip_with_Ver k_7zip_with_Ver_base L" x64"
+#else
+ #define k_7zip_with_Ver k_7zip_with_Ver_base
+#endif
+
+static const WCHAR *k_7zip_with_Ver_str = k_7zip_with_Ver;
+
+static const WCHAR *k_7zip_Setup = k_7zip_with_Ver L" Setup";
+
+static const WCHAR *k_Reg_Path = L"Path";
+
+static const WCHAR *k_Reg_Path32 = L"Path"
+ #ifdef _64BIT_INSTALLER
+ L"64"
+ #else
+ L"32"
+ #endif
+ ;
+
+#if defined(_64BIT_INSTALLER) && !defined(_WIN64)
+ #define k_Reg_WOW_Flag KEY_WOW64_64KEY
+#else
+ #define k_Reg_WOW_Flag 0
+#endif
+
+#ifdef _WIN64
+ #define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY
+#else
+ #define k_Reg_WOW_Flag_32 0
+#endif
+
+#define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}"
+
+static const WCHAR *k_Reg_CLSID_7zip = L"CLSID\\" k_7zip_CLSID;
+static const WCHAR *k_Reg_CLSID_7zip_Inproc = L"CLSID\\" k_7zip_CLSID L"\\InprocServer32";
+
+#define g_AllUsers True
+
+static Bool g_Install_was_Pressed;
+static Bool g_Finished;
+static Bool g_SilentMode;
+
+static HWND g_HWND;
+static HWND g_Path_HWND;
+static HWND g_InfoLine_HWND;
+static HWND g_Progress_HWND;
+
+static WCHAR path[MAX_PATH * 2 + 40];
+
+
+#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))
+
+static void PrintErrorMessage(const char *s)
+{
+ WCHAR s2[256 + 4];
+ unsigned i;
+ for (i = 0; i < 256; i++)
+ {
+ Byte b = s[i];
+ if (b == 0)
+ break;
+ s2[i] = b;
+ }
+ s2[i] = 0;
+ MessageBoxW(g_HWND, s2, k_7zip_with_Ver_str, MB_ICONERROR);
+}
+
+static WRes MyCreateDir(const WCHAR *name)
+{
+ return CreateDirectoryW(name, NULL) ? 0 : GetLastError();
+}
+
+#define IS_SEPAR(c) (c == WCHAR_PATH_SEPARATOR)
+#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
+#define IS_DRIVE_PATH(s) (IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]))
+
+static int ReverseFind_PathSepar(const wchar_t *s)
+{
+ int separ = -1;
+ int i;
+ for (i = 0;; i++)
+ {
+ wchar_t c = s[i];
+ if (c == 0)
+ return separ;
+ if (IS_SEPAR(c))
+ separ = i;
+ }
+}
+
+static WRes CreateComplexDir()
+{
+ WCHAR s[MAX_PATH + 10];
+
+ unsigned prefixSize = 0;
+ WRes wres;
+
+ {
+ size_t len = wcslen(path);
+ if (len > MAX_PATH)
+ return ERROR_INVALID_NAME;
+ wcscpy(s, path);
+ }
+
+ if (IS_DRIVE_PATH(s))
+ prefixSize = 3;
+ else if (IS_SEPAR(s[1]) && IS_SEPAR(s[1]))
+ prefixSize = 2;
+ else
+ return ERROR_INVALID_NAME;
+
+ {
+ DWORD attrib = GetFileAttributesW(s);
+ if (attrib != INVALID_FILE_ATTRIBUTES)
+ return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ? 0 : ERROR_ALREADY_EXISTS;
+ }
+
+ wres = MyCreateDir(s);
+ if (wres == 0 || wres == ERROR_ALREADY_EXISTS)
+ return 0;
+
+ {
+ size_t len = wcslen(s);
+ {
+ int pos = ReverseFind_PathSepar(s);
+ if (pos < 0)
+ return wres;
+ if ((unsigned)pos < prefixSize)
+ return wres;
+ if ((unsigned)pos == len - 1)
+ {
+ if (len == 1)
+ return 0;
+ s[pos] = 0;
+ len = pos;
+ }
+ }
+
+ for (;;)
+ {
+ int pos;
+ wres = MyCreateDir(s);
+ if (wres == 0)
+ break;
+ if (wres == ERROR_ALREADY_EXISTS)
+ {
+ DWORD attrib = GetFileAttributesW(s);
+ if (attrib != INVALID_FILE_ATTRIBUTES)
+ if ((attrib & FILE_ATTRIBUTE_DIRECTORY) == 0)
+ return ERROR_ALREADY_EXISTS;
+ break;
+ }
+ pos = ReverseFind_PathSepar(s);
+ if (pos < 0 || pos == 0 || (unsigned)pos < prefixSize)
+ return wres;
+ s[pos] = 0;
+ }
+
+ for (;;)
+ {
+ size_t pos = wcslen(s);
+ if (pos >= len)
+ return 0;
+ s[pos] = CHAR_PATH_SEPARATOR;
+ wres = MyCreateDir(s);
+ if (wres != 0)
+ return wres;
+ }
+ }
+}
+
+
+static int MyRegistry_QueryString(HKEY hKey, LPCWSTR name, LPWSTR dest)
+{
+ DWORD cnt = MAX_PATH * sizeof(name[0]);
+ DWORD type = 0;
+ LONG res = RegQueryValueExW(hKey, name, NULL, &type, (LPBYTE)dest, (DWORD *)&cnt);
+ if (type != REG_SZ)
+ return False;
+ return res == ERROR_SUCCESS;
+}
+
+static int MyRegistry_QueryString2(HKEY hKey, LPCWSTR keyName, LPCWSTR valName, LPWSTR dest)
+{
+ HKEY key = 0;
+ LONG res = RegOpenKeyExW(hKey, keyName, 0, KEY_READ | k_Reg_WOW_Flag, &key);
+ if (res != ERROR_SUCCESS)
+ return False;
+ {
+ Bool res2 = MyRegistry_QueryString(key, valName, dest);
+ RegCloseKey(key);
+ return res2;
+ }
+}
+
+static LONG MyRegistry_SetString(HKEY hKey, LPCWSTR name, LPCWSTR val)
+{
+ return RegSetValueExW(hKey, name, 0, REG_SZ,
+ (const BYTE *)val, (DWORD)(wcslen(val) + 1) * sizeof(val[0]));
+}
+
+static LONG MyRegistry_SetDWORD(HKEY hKey, LPCWSTR name, DWORD val)
+{
+ return RegSetValueExW(hKey, name, 0, REG_DWORD, (const BYTE *)&val, sizeof(DWORD));
+}
+
+
+static LONG MyRegistry_CreateKey(HKEY parentKey, LPCWSTR name, HKEY *destKey)
+{
+ return RegCreateKeyExW(parentKey, name, 0, NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS | k_Reg_WOW_Flag,
+ NULL, destKey, NULL);
+}
+
+static LONG MyRegistry_CreateKeyAndVal(HKEY parentKey, LPCWSTR keyName, LPCWSTR valName, LPCWSTR val)
+{
+ HKEY destKey = 0;
+ LONG res = MyRegistry_CreateKey(parentKey, keyName, &destKey);
+ if (res == ERROR_SUCCESS)
+ {
+ res = MyRegistry_SetString(destKey, valName, val);
+ res = RegCloseKey(destKey);
+ }
+ return res;
+}
+
+
+#ifdef _64BIT_INSTALLER
+
+static LONG MyRegistry_CreateKey_32(HKEY parentKey, LPCWSTR name, HKEY *destKey)
+{
+ return RegCreateKeyExW(parentKey, name, 0, NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS | k_Reg_WOW_Flag_32,
+ NULL, destKey, NULL);
+}
+
+static LONG MyRegistry_CreateKeyAndVal_32(HKEY parentKey, LPCWSTR keyName, LPCWSTR valName, LPCWSTR val)
+{
+ HKEY destKey = 0;
+ LONG res = MyRegistry_CreateKey_32(parentKey, keyName, &destKey);
+ if (res == ERROR_SUCCESS)
+ {
+ res = MyRegistry_SetString(destKey, valName, val);
+ res = RegCloseKey(destKey);
+ }
+ return res;
+}
+
+#endif
+
+
+
+#ifdef UNDER_CE
+ #define kBufSize (1 << 13)
+#else
+ #define kBufSize (1 << 15)
+#endif
+
+#define kSignatureSearchLimit (1 << 22)
+
+static Bool FindSignature(CSzFile *stream, UInt64 *resPos)
+{
+ Byte buf[kBufSize];
+ size_t numPrevBytes = 0;
+ *resPos = 0;
+
+ for (;;)
+ {
+ size_t processed, pos;
+ if (*resPos > kSignatureSearchLimit)
+ return False;
+ processed = kBufSize - numPrevBytes;
+ if (File_Read(stream, buf + numPrevBytes, &processed) != 0)
+ return False;
+ processed += numPrevBytes;
+ if (processed < k7zStartHeaderSize ||
+ (processed == k7zStartHeaderSize && numPrevBytes != 0))
+ return False;
+ processed -= k7zStartHeaderSize;
+ for (pos = 0; pos <= processed; pos++)
+ {
+ for (; buf[pos] != '7' && pos <= processed; pos++);
+ if (pos > processed)
+ break;
+ if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0)
+ if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8))
+ {
+ *resPos += pos;
+ return True;
+ }
+ }
+ *resPos += processed;
+ numPrevBytes = k7zStartHeaderSize;
+ memmove(buf, buf + processed, k7zStartHeaderSize);
+ }
+}
+
+static void HexToString(UInt32 val, WCHAR *s)
+{
+ UInt64 v = val;
+ unsigned i;
+ for (i = 1;; i++)
+ {
+ v >>= 4;
+ if (v == 0)
+ break;
+ }
+ s[i] = 0;
+ do
+ {
+ unsigned t = (unsigned)((val & 0xF));
+ val >>= 4;
+ s[--i] = (WCHAR)(unsigned)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ }
+ while (i);
+}
+
+
+#ifndef UNDER_CE
+
+int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM data)
+{
+ UNUSED_VAR(lp)
+ UNUSED_VAR(data)
+ UNUSED_VAR(hwnd)
+
+ switch (uMsg)
+ {
+ case BFFM_INITIALIZED:
+ {
+ SendMessage(hwnd, BFFM_SETSELECTIONW, TRUE, data);
+ break;
+ }
+ case BFFM_SELCHANGED:
+ {
+ // show selected path for BIF_STATUSTEXT
+ WCHAR dir[MAX_PATH];
+ if (!SHGetPathFromIDListW((LPITEMIDLIST)lp, dir))
+ dir[0] = 0;
+ SendMessage(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+static Bool MyBrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
+ LPCWSTR initialFolder, LPWSTR resultPath)
+{
+ WCHAR displayName[MAX_PATH];
+ BROWSEINFOW browseInfo;
+
+ displayName[0] = 0;
+ browseInfo.hwndOwner = owner;
+ browseInfo.pidlRoot = NULL;
+
+ // there are Unicode/Astring problems in some WinCE SDK ?
+ browseInfo.pszDisplayName = displayName;
+ browseInfo.lpszTitle = title;
+ browseInfo.ulFlags = ulFlags;
+ browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
+ browseInfo.lParam = (LPARAM)initialFolder;
+ {
+ LPITEMIDLIST idlist = SHBrowseForFolderW(&browseInfo);
+ if (idlist)
+ {
+ SHGetPathFromIDListW(idlist, resultPath);
+ // free idlist
+ // CoTaskMemFree(idlist);
+ return True;
+ }
+ return False;
+ }
+}
+
+#endif
+
+static void NormalizePrefix(WCHAR *s)
+{
+ size_t i = 0;
+
+ for (;; i++)
+ {
+ wchar_t c = s[i];
+ if (c == 0)
+ break;
+ if (c == '/')
+ s[i] = WCHAR_PATH_SEPARATOR;
+ }
+
+ if (i != 0 && s[i - 1] != WCHAR_PATH_SEPARATOR)
+ {
+ s[i] = WCHAR_PATH_SEPARATOR;
+ s[i + 1] = 0;
+ }
+}
+
+static char MyCharLower_Ascii(char c)
+{
+ if (c >= 'A' && c <= 'Z')
+ return (char)((unsigned char)c + 0x20);
+ return c;
+}
+
+static wchar_t MyWCharLower_Ascii(wchar_t c)
+{
+ if (c >= 'A' && c <= 'Z')
+ return (wchar_t)(c + 0x20);
+ return c;
+}
+
+static const WCHAR *FindSubString(const WCHAR *s1, const char *s2)
+{
+ for (;;)
+ {
+ unsigned i;
+ if (*s1 == 0)
+ return NULL;
+ for (i = 0;; i++)
+ {
+ Byte b = s2[i];
+ if (b == 0)
+ return s1;
+ if (MyWCharLower_Ascii(s1[i]) != (Byte)MyCharLower_Ascii(b))
+ {
+ s1++;
+ break;
+ }
+ }
+ }
+}
+
+static void Set7zipPostfix(WCHAR *s)
+{
+ NormalizePrefix(s);
+ if (FindSubString(s, "7-Zip"))
+ return;
+ wcscat(s, L"7-Zip\\");
+}
+
+
+static int Install();
+
+static void OnClose()
+{
+ if (g_Install_was_Pressed && !g_Finished)
+ {
+ if (MessageBoxW(g_HWND,
+ L"Do you want to cancel " k_7zip_with_Ver L" installation?",
+ k_7zip_with_Ver,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) != IDYES)
+ return;
+ }
+ DestroyWindow(g_HWND);
+ g_HWND = NULL;
+}
+
+static INT_PTR CALLBACK MyDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ // UNUSED_VAR(hwnd)
+ UNUSED_VAR(lParam)
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ g_Path_HWND = GetDlgItem(hwnd, IDE_EXTRACT_PATH);
+ g_InfoLine_HWND = GetDlgItem(hwnd, IDT_CUR_FILE);
+ g_Progress_HWND = GetDlgItem(hwnd, IDC_PROGRESS);
+
+ SetWindowTextW(hwnd, k_7zip_Setup);
+ SetDlgItemTextW(hwnd, IDE_EXTRACT_PATH, path);
+
+ ShowWindow(g_Progress_HWND, SW_HIDE);
+ ShowWindow(g_InfoLine_HWND, SW_HIDE);
+
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ if (g_Finished)
+ {
+ OnClose();
+ break;
+ }
+ if (!g_Install_was_Pressed)
+ {
+ SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDCANCEL), TRUE);
+
+ EnableWindow(g_Path_HWND, FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDB_EXTRACT_SET_PATH), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
+
+ g_Install_was_Pressed = True;
+ return TRUE;
+ }
+ break;
+ }
+
+ case IDCANCEL:
+ {
+ OnClose();
+ break;
+ }
+
+ case IDB_EXTRACT_SET_PATH:
+ {
+ #ifndef UNDER_CE
+
+ WCHAR s[MAX_PATH];
+ WCHAR s2[MAX_PATH];
+ GetDlgItemTextW(hwnd, IDE_EXTRACT_PATH, s, MAX_PATH);
+ if (MyBrowseForFolder(hwnd, L"Select the folder for installation:" ,
+ 0
+ | BIF_NEWDIALOGSTYLE // 5.0 of ?.dll ?
+ | BIF_RETURNONLYFSDIRS
+ // | BIF_STATUSTEXT // doesn't work for BIF_NEWDIALOGSTYLE
+ , s, s2))
+ {
+ Set7zipPostfix(s2);
+ SetDlgItemTextW(hwnd, IDE_EXTRACT_PATH, s2);
+ }
+
+ #endif
+ break;
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ OnClose();
+ break;
+ /*
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return TRUE;
+ */
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+static LONG SetRegKey_Path2(HKEY parentKey)
+{
+ HKEY destKey = 0;
+ LONG res = MyRegistry_CreateKey(parentKey, k_Reg_Software_7zip, &destKey);
+ if (res == ERROR_SUCCESS)
+ {
+ res = MyRegistry_SetString(destKey, k_Reg_Path32, path);
+ res = MyRegistry_SetString(destKey, k_Reg_Path, path);
+ res = RegCloseKey(destKey);
+ }
+ return res;
+}
+
+static void SetRegKey_Path()
+{
+ SetRegKey_Path2(HKEY_CURRENT_USER);
+ SetRegKey_Path2(HKEY_LOCAL_MACHINE);
+}
+
+
+static HRESULT CreateShellLink(LPCWSTR srcPath, LPCWSTR targetPath)
+{
+ IShellLinkW* sl;
+
+ // CoInitialize has already been called.
+ HRESULT hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID*)&sl);
+
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* pf;
+
+ sl->lpVtbl->SetPath(sl, targetPath);
+ // sl->lpVtbl->SetDescription(sl, description);
+ hres = sl->lpVtbl->QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
+
+ if (SUCCEEDED(hres))
+ {
+ hres = pf->lpVtbl->Save(pf, srcPath, TRUE);
+ pf->lpVtbl->Release(pf);
+ }
+ sl->lpVtbl->Release(sl);
+ }
+
+ return hres;
+}
+
+static void SetShellProgramsGroup(HWND hwndOwner)
+{
+ #ifdef UNDER_CE
+
+ // wcscpy(link, L"\\Program Files\\");
+ UNUSED_VAR(hwndOwner)
+
+ #else
+
+ unsigned i = (g_AllUsers ? 0 : 2);
+
+ for (; i < 3; i++)
+ {
+ Bool isOK = True;
+ WCHAR link[MAX_PATH + 40];
+ WCHAR destPath[MAX_PATH + 40];
+
+ link[0] = 0;
+
+ if (SHGetFolderPathW(hwndOwner,
+ i == 1 ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS,
+ NULL, SHGFP_TYPE_CURRENT, link) != S_OK)
+ continue;
+
+ NormalizePrefix(link);
+ wcscat(link, k_7zip);
+ // wcscat(link, L"2");
+
+ if (i != 0)
+ MyCreateDir(link);
+
+ NormalizePrefix(link);
+
+ {
+ unsigned baseLen = (unsigned)wcslen(link);
+ unsigned k;
+
+ for (k = 0; k < 2; k++)
+ {
+ wcscpy(link + baseLen, k == 0 ?
+ L"7-Zip File Manager.lnk" :
+ L"7-Zip Help.lnk"
+ );
+ wcscpy(destPath, path);
+ wcscat(destPath, k == 0 ?
+ L"7zFM.exe" :
+ L"7-zip.chm");
+
+ if (i == 0)
+ DeleteFileW(link);
+ else if (CreateShellLink(link, destPath) != S_OK)
+ isOK = False;
+ }
+ }
+
+ if (i != 0 && isOK)
+ break;
+ }
+
+ #endif
+}
+
+static const WCHAR *k_Shell_Approved = L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
+static const WCHAR *k_7zip_ShellExtension = L"7-Zip Shell Extension";
+
+static void WriteCLSID()
+{
+ HKEY destKey;
+ LONG res;
+
+ #ifdef _64BIT_INSTALLER
+
+ MyRegistry_CreateKeyAndVal_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip, NULL, k_7zip_ShellExtension);
+
+ res = MyRegistry_CreateKey_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc, &destKey);
+
+ if (res == ERROR_SUCCESS)
+ {
+ WCHAR destPath[MAX_PATH + 10];
+ wcscpy(destPath, path);
+ wcscat(destPath, L"7-zip32.dll");
+ res = MyRegistry_SetString(destKey, NULL, destPath);
+ res = MyRegistry_SetString(destKey, L"ThreadingModel", L"Apartment");
+ // DeleteRegValue(destKey, L"InprocServer32");
+ res = RegCloseKey(destKey);
+ }
+
+ #endif
+
+
+ MyRegistry_CreateKeyAndVal(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip, NULL, k_7zip_ShellExtension);
+
+ destKey = 0;
+ res = MyRegistry_CreateKey(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc, &destKey);
+
+ if (res == ERROR_SUCCESS)
+ {
+ WCHAR destPath[MAX_PATH + 10];
+ wcscpy(destPath, path);
+ wcscat(destPath, L"7-zip.dll");
+ res = MyRegistry_SetString(destKey, NULL, destPath);
+ res = MyRegistry_SetString(destKey, L"ThreadingModel", L"Apartment");
+ // DeleteRegValue(destKey, L"InprocServer32");
+ res = RegCloseKey(destKey);
+ }
+}
+
+static const WCHAR * const k_ShellEx_Items[] =
+{
+ L"*\\shellex\\ContextMenuHandlers"
+ , L"Directory\\shellex\\ContextMenuHandlers"
+ , L"Folder\\shellex\\ContextMenuHandlers"
+ , L"Directory\\shellex\\DragDropHandlers"
+ , L"Drive\\shellex\\DragDropHandlers"
+};
+
+static void WriteShellEx()
+{
+ unsigned i;
+ WCHAR destPath[MAX_PATH + 40];
+
+ for (i = 0; i < sizeof(k_ShellEx_Items) / sizeof(k_ShellEx_Items[0]); i++)
+ {
+ wcscpy(destPath, k_ShellEx_Items[i]);
+ wcscat(destPath, L"\\7-Zip");
+
+ #ifdef _64BIT_INSTALLER
+ MyRegistry_CreateKeyAndVal_32(HKEY_CLASSES_ROOT, destPath, NULL, k_7zip_CLSID);
+ #endif
+ MyRegistry_CreateKeyAndVal (HKEY_CLASSES_ROOT, destPath, NULL, k_7zip_CLSID);
+ }
+
+ #ifdef _64BIT_INSTALLER
+ MyRegistry_CreateKeyAndVal_32(HKEY_LOCAL_MACHINE, k_Shell_Approved, k_7zip_CLSID, k_7zip_ShellExtension);
+ #endif
+ MyRegistry_CreateKeyAndVal (HKEY_LOCAL_MACHINE, k_Shell_Approved, k_7zip_CLSID, k_7zip_ShellExtension);
+
+
+ {
+ HKEY destKey = 0;
+ LONG res = MyRegistry_CreateKey(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\7zFM.exe", &destKey);
+ if (res == ERROR_SUCCESS)
+ {
+ wcscpy(destPath, path);
+ wcscat(destPath, L"7zFM.exe");
+
+ MyRegistry_SetString(destKey, NULL, destPath);
+ MyRegistry_SetString(destKey, L"Path", path);
+ RegCloseKey(destKey);
+ }
+
+ }
+
+ {
+ HKEY destKey = 0;
+ LONG res = MyRegistry_CreateKey(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\7-Zip", &destKey);
+ if (res == ERROR_SUCCESS)
+ {
+ // wcscpy(destPath, path);
+ // wcscat(destPath, L"7zFM.exe");
+ MyRegistry_SetString(destKey, L"DisplayName", k_7zip_with_Ver_str);
+
+ MyRegistry_SetString(destKey, L"DisplayIcon", destPath);
+
+ wcscpy(destPath, path);
+ // MyRegistry_SetString(destKey, L"InstallLocation", destPath);
+ wcscat(destPath, L"Uninstall.exe");
+ // wcscat(destPath, L"\"");
+ MyRegistry_SetString(destKey, L"UninstallString", destPath);
+ MyRegistry_SetDWORD(destKey, L"NoModify", 1);
+ MyRegistry_SetDWORD(destKey, L"NoRepair", 1);
+ RegCloseKey(destKey);
+ }
+ }
+}
+
+
+static const wchar_t *GetCmdParam(const wchar_t *s)
+{
+ Bool quoteMode = False;
+ for (;; s++)
+ {
+ wchar_t c = *s;
+ if (c == L'\"')
+ quoteMode = !quoteMode;
+ else if (c == 0 || (c == L' ' && !quoteMode))
+ return s;
+ }
+}
+
+static void RemoveQuotes(wchar_t *s)
+{
+ const wchar_t *src = s;
+ for (;;)
+ {
+ wchar_t c = *src++;
+ if (c == '\"')
+ continue;
+ *s++ = c;
+ if (c == 0)
+ return;
+ }
+}
+
+#define IS_LIMIT_CHAR(c) (c == 0 || c == ' ')
+
+
+typedef BOOL (WINAPI *Func_IsWow64Process)(HANDLE, PBOOL);
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ #ifdef UNDER_CE
+ LPWSTR
+ #else
+ LPSTR
+ #endif
+ lpCmdLine, int nCmdShow)
+{
+
+ UNUSED_VAR(hPrevInstance)
+ UNUSED_VAR(lpCmdLine)
+ UNUSED_VAR(nCmdShow)
+
+ #ifndef UNDER_CE
+ CoInitialize(NULL);
+ #endif
+
+ CrcGenerateTable();
+
+ {
+ const wchar_t *s = GetCommandLineW();
+
+ #ifndef UNDER_CE
+ s = GetCmdParam(s);
+ #endif
+
+ for (;;)
+ {
+ {
+ wchar_t c = *s;
+ if (c == 0)
+ break;
+ if (c == ' ')
+ {
+ s++;
+ continue;
+ }
+ }
+
+ {
+ const wchar_t *s2 = GetCmdParam(s);
+ if (s[0] == '/')
+ {
+ if (s[1] == 'S' && IS_LIMIT_CHAR(s[2]))
+ g_SilentMode = True;
+ else if (s[1] == 'D' && s[2] == '=')
+ {
+ size_t num;
+ s += 3;
+ num = s2 - s;
+ if (num > MAX_PATH)
+ num = MAX_PATH;
+ wcsncpy(path, s, num);
+ RemoveQuotes(path);
+ }
+ }
+ s = s2;
+ }
+ }
+ }
+
+ #if defined(_64BIT_INSTALLER) && !defined(_WIN64)
+ {
+ BOOL isWow64 = FALSE;
+ Func_IsWow64Process func_IsWow64Process = (Func_IsWow64Process)
+ GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "IsWow64Process");
+
+ if (func_IsWow64Process)
+ func_IsWow64Process(GetCurrentProcess(), &isWow64);
+
+ if (!isWow64)
+ {
+ if (!g_SilentMode)
+ PrintErrorMessage("This installation requires Windows x64");
+ return 1;
+ }
+ }
+ #endif
+
+
+ if (path[0] == 0)
+ {
+ HKEY key = 0;
+ Bool ok = False;
+ LONG res = RegOpenKeyExW(HKEY_CURRENT_USER, k_Reg_Software_7zip, 0, KEY_READ | k_Reg_WOW_Flag, &key);
+ if (res == ERROR_SUCCESS)
+ {
+ ok = MyRegistry_QueryString(key, k_Reg_Path32, path);
+ // ok = MyRegistry_QueryString(key, k_Reg_Path, path);
+ RegCloseKey(key);
+ }
+
+ // ok = False;
+ if (!ok)
+ {
+ /*
+ #ifdef UNDER_CE
+ wcscpy(path, L"\\Program Files\\");
+ #else
+
+ #ifdef _64BIT_INSTALLER
+ {
+ DWORD ttt = GetEnvironmentVariableW(L"ProgramW6432", path, MAX_PATH);
+ if (ttt == 0 || ttt > MAX_PATH)
+ wcscpy(path, L"C:\\");
+ }
+ #else
+ if (!SHGetSpecialFolderPathW(0, path, CSIDL_PROGRAM_FILES, FALSE))
+ wcscpy(path, L"C:\\");
+ #endif
+ #endif
+ */
+ if (!MyRegistry_QueryString2(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion", L"ProgramFilesDir", path))
+ wcscpy(path,
+ #ifdef UNDER_CE
+ L"\\Program Files\\"
+ #else
+ L"C:\\"
+ #endif
+ );
+
+ Set7zipPostfix(path);
+ }
+ }
+
+ NormalizePrefix(path);
+
+ if (g_SilentMode)
+ return Install();
+
+ {
+ int retCode = 1;
+ // INT_PTR res = DialogBox(
+ g_HWND = CreateDialog(
+ hInstance,
+ // GetModuleHandle(NULL),
+ MAKEINTRESOURCE(IDD_INSTALL), NULL, MyDlgProc);
+ if (!g_HWND)
+ return 1;
+
+ {
+ HICON hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
+ // SendMessage(g_HWND, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
+ SendMessage(g_HWND, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hIcon);
+ }
+
+
+ {
+ BOOL bRet;
+ MSG msg;
+
+ while ((bRet = GetMessage(&msg, g_HWND, 0, 0)) != 0)
+ {
+ if (bRet == -1)
+ return retCode;
+ if (!g_HWND)
+ return retCode;
+
+ if (!IsDialogMessage(g_HWND, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ if (!g_HWND)
+ return retCode;
+
+ if (g_Install_was_Pressed && !g_Finished)
+ {
+ retCode = Install();
+ g_Finished = True;
+ if (retCode != 0)
+ break;
+ if (!g_HWND)
+ break;
+ {
+ SetDlgItemTextW(g_HWND, IDOK, L"Close");
+ EnableWindow(GetDlgItem(g_HWND, IDOK), TRUE);
+ EnableWindow(GetDlgItem(g_HWND, IDCANCEL), FALSE);
+ SendMessage(g_HWND, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(g_HWND, IDOK), TRUE);
+ }
+ }
+ }
+
+ if (g_HWND)
+ {
+ DestroyWindow(g_HWND);
+ g_HWND = NULL;
+ }
+ }
+
+ return retCode;
+ }
+}
+
+static Bool GetErrorMessage(DWORD errorCode, WCHAR *message)
+{
+ LPVOID msgBuf;
+ if (FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)
+ return False;
+ wcscpy(message, msgBuf);
+ LocalFree(msgBuf);
+ return True;
+}
+
+static int Install()
+{
+ CFileInStream archiveStream;
+ CLookToRead lookStream;
+ CSzArEx db;
+
+ SRes res = SZ_OK;
+ WRes winRes = 0;
+ const char *errorMessage = NULL;
+
+ ISzAlloc allocImp;
+ ISzAlloc allocTempImp;
+ WCHAR sfxPath[MAX_PATH + 2];
+
+ Bool needReboot = False;
+ size_t pathLen;
+
+ allocImp.Alloc = SzAlloc;
+ allocImp.Free = SzFree;
+
+ allocTempImp.Alloc = SzAllocTemp;
+ allocTempImp.Free = SzFreeTemp;
+
+ {
+ DWORD len = GetModuleFileNameW(NULL, sfxPath, MAX_PATH);
+ if (len == 0 || len > MAX_PATH)
+ return 1;
+ }
+
+ winRes = InFile_OpenW(&archiveStream.file, sfxPath);
+
+ if (winRes == 0)
+ {
+ UInt64 pos = 0;
+ if (!FindSignature(&archiveStream.file, &pos))
+ errorMessage = "Can't find 7z archive";
+ else
+ winRes = File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET);
+ }
+
+ if (winRes != 0)
+ res = SZ_ERROR_FAIL;
+
+ if (errorMessage)
+ res = SZ_ERROR_FAIL;
+
+if (res == SZ_OK)
+{
+ if (!g_SilentMode)
+ {
+ GetDlgItemTextW(g_HWND, IDE_EXTRACT_PATH, path, MAX_PATH);
+ }
+
+ FileInStream_CreateVTable(&archiveStream);
+ LookToRead_CreateVTable(&lookStream, False);
+
+ NormalizePrefix(path);
+ winRes = CreateComplexDir();
+
+ if (winRes != 0)
+ res = E_FAIL;
+
+ pathLen = wcslen(path);
+ SzArEx_Init(&db);
+
+ if (res == SZ_OK)
+ {
+ lookStream.realStream = &archiveStream.s;
+ LookToRead_Init(&lookStream);
+
+ res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
+ }
+
+ if (res == SZ_OK)
+ {
+ UInt32 i;
+ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call, if(!outBuf) */
+ Byte *outBuf = NULL; /* it must be NULL before first call for each new archive. */
+ size_t outBufSize = 0; /* it can have any value before first call, if(!outBuf) */
+
+ if (!g_SilentMode)
+ {
+ ShowWindow(g_Progress_HWND, SW_SHOW);
+ ShowWindow(g_InfoLine_HWND, SW_SHOW);
+ SendMessage(g_Progress_HWND, PBM_SETRANGE32, 0, db.NumFiles);
+ }
+
+ for (i = 0; i < db.NumFiles; i++)
+ {
+ size_t offset = 0;
+ size_t outSizeProcessed = 0;
+ WCHAR *temp;
+
+ if (!g_SilentMode)
+ {
+ MSG msg;
+
+ // g_HWND
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if (!IsDialogMessage(g_HWND, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ if (!g_HWND)
+ return 1;
+ }
+
+ // Sleep(10);
+ SendMessage(g_Progress_HWND, PBM_SETPOS, i, 0);
+ }
+
+ {
+ size_t len = SzArEx_GetFileNameUtf16(&db, i, NULL);
+ if (len >= MAX_PATH)
+ {
+ res = SZ_ERROR_FAIL;
+ break;
+ }
+ }
+
+ temp = path + pathLen;
+
+ SzArEx_GetFileNameUtf16(&db, i, temp);
+
+ if (!g_SilentMode)
+ SetWindowTextW(g_InfoLine_HWND, temp);
+
+ {
+ res = SzArEx_Extract(&db, &lookStream.s, i,
+ &blockIndex, &outBuf, &outBufSize,
+ &offset, &outSizeProcessed,
+ &allocImp, &allocTempImp);
+ if (res != SZ_OK)
+ break;
+ }
+
+ {
+ CSzFile outFile;
+ size_t processedSize;
+ size_t j;
+ // size_t nameStartPos = 0;
+ UInt32 tempIndex = 0;
+ WCHAR origPath[MAX_PATH * 2 + 10];
+
+ for (j = 0; temp[j] != 0; j++)
+ {
+ if (temp[j] == '/')
+ {
+ temp[j] = 0;
+ MyCreateDir(path);
+ temp[j] = CHAR_PATH_SEPARATOR;
+ // nameStartPos = j + 1;
+ }
+ }
+
+ if (SzArEx_IsDir(&db, i))
+ {
+ MyCreateDir(path);
+ continue;
+ }
+
+ {
+ // Bool skipFile = False;
+
+ wcscpy(origPath, path);
+
+ for (;;)
+ {
+ WRes openRes;
+
+ if (tempIndex != 0)
+ {
+ if (tempIndex > 100)
+ {
+ res = SZ_ERROR_FAIL;
+ break;
+ }
+ wcscpy(path, origPath);
+ wcscat(path, L".tmp");
+ if (tempIndex > 1)
+ HexToString(tempIndex, path + wcslen(path));
+ if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
+ {
+ tempIndex++;
+ continue;
+ }
+ }
+
+ {
+ SetFileAttributesW(path, 0);
+ openRes = OutFile_OpenW(&outFile, path);
+ if (openRes == 0)
+ break;
+ }
+
+ if (tempIndex != 0
+ || FindSubString(temp, "7-zip.dll")
+ #ifdef _64BIT_INSTALLER
+ || FindSubString(temp, "7-zip32.dll")
+ #endif
+ )
+ {
+ tempIndex++;
+ continue;
+ }
+
+ if (g_SilentMode)
+ {
+ tempIndex++;
+ continue;
+ }
+ {
+ WCHAR message[MAX_PATH * 3 + 100];
+ int mbRes;
+
+ wcscpy(message, L"Can't open file\n");
+ wcscat(message, path);
+ wcscat(message, L"\n");
+
+ GetErrorMessage(openRes, message + wcslen(message));
+
+ mbRes = MessageBoxW(g_HWND, message, L"Error", MB_ICONERROR | MB_ABORTRETRYIGNORE | MB_DEFBUTTON3);
+ if (mbRes == IDABORT)
+ {
+ res = SZ_ERROR_ABORT;
+ tempIndex = 0;
+ break;
+ }
+ if (mbRes == IDIGNORE)
+ {
+ // skipFile = True;
+ tempIndex++;
+ }
+ }
+ }
+
+ if (res != SZ_OK)
+ break;
+
+ /*
+ if (skipFile)
+ continue;
+ */
+ }
+
+ // if (res = S_OK)
+ {
+ processedSize = outSizeProcessed;
+ winRes = File_Write(&outFile, outBuf + offset, &processedSize);
+ if (winRes != 0 || processedSize != outSizeProcessed)
+ {
+ errorMessage = "Can't write output file";
+ res = SZ_ERROR_FAIL;
+ }
+
+ #ifdef USE_WINDOWS_FILE
+ if (SzBitWithVals_Check(&db.MTime, i))
+ {
+ const CNtfsFileTime *t = db.MTime.Vals + i;
+ FILETIME mTime;
+ mTime.dwLowDateTime = t->Low;
+ mTime.dwHighDateTime = t->High;
+ SetFileTime(outFile.handle, NULL, NULL, &mTime);
+ }
+ #endif
+
+ {
+ SRes winRes2 = File_Close(&outFile);
+ if (res != SZ_OK)
+ break;
+ if (winRes2 != 0)
+ {
+ winRes = winRes2;
+ break;
+ }
+ }
+
+ #ifdef USE_WINDOWS_FILE
+ if (SzBitWithVals_Check(&db.Attribs, i))
+ SetFileAttributesW(path, db.Attribs.Vals[i]);
+ #endif
+ }
+
+ if (tempIndex != 0)
+ {
+ // is it supported at win2000 ?
+ #ifndef UNDER_CE
+ if (!MoveFileExW(path, origPath, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING))
+ {
+ winRes = GetLastError();
+ break;
+ }
+ needReboot = True;
+ #endif
+ }
+
+ }
+ }
+
+ IAlloc_Free(&allocImp, outBuf);
+
+ if (!g_SilentMode)
+ SendMessage(g_Progress_HWND, PBM_SETPOS, i, 0);
+
+ path[pathLen] = 0;
+
+ if (i == db.NumFiles)
+ {
+ SetRegKey_Path();
+ WriteCLSID();
+ WriteShellEx();
+
+ SetShellProgramsGroup(g_HWND);
+ if (!g_SilentMode)
+ SetWindowTextW(g_InfoLine_HWND, k_7zip_with_Ver L" is installed");
+ }
+ }
+
+ SzArEx_Free(&db, &allocImp);
+
+ File_Close(&archiveStream.file);
+
+}
+
+ if (winRes != 0)
+ res = SZ_ERROR_FAIL;
+
+ if (res == SZ_OK)
+ {
+ if (!g_SilentMode && needReboot)
+ {
+ if (MessageBoxW(g_HWND, L"You must restart your system to complete the installation.\nRestart now?",
+ k_7zip_Setup, MB_YESNO | MB_DEFBUTTON2) == IDYES)
+ {
+ #ifndef UNDER_CE
+
+ // Get a token for this process.
+ HANDLE hToken;
+
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+ {
+ TOKEN_PRIVILEGES tkp;
+ // Get the LUID for the shutdown privilege.
+ LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
+ tkp.PrivilegeCount = 1; // one privilege to set
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ // Get the shutdown privilege for this process.
+ AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
+
+ if (GetLastError() == ERROR_SUCCESS)
+ {
+ if (!ExitWindowsEx(EWX_REBOOT, 0))
+ {
+ }
+ }
+ }
+
+ #endif
+ }
+ }
+
+ if (res == SZ_OK)
+ return 0;
+ }
+
+ if (!g_SilentMode)
+ {
+ if (winRes != 0)
+ {
+ WCHAR m[MAX_PATH + 100];
+ m[0] = 0;
+ GetErrorMessage(winRes, m);
+ MessageBoxW(g_HWND, m, k_7zip_with_Ver_str, MB_ICONERROR);
+ }
+ else
+ {
+ if (res == SZ_ERROR_ABORT)
+ return 2;
+
+ if (res == SZ_ERROR_UNSUPPORTED)
+ errorMessage = "Decoder doesn't support this archive";
+ else if (res == SZ_ERROR_MEM)
+ errorMessage = "Can't allocate required memory";
+ else if (res == SZ_ERROR_CRC)
+ errorMessage = "CRC error";
+ else if (res == SZ_ERROR_DATA)
+ errorMessage = "Data error";
+
+ if (!errorMessage)
+ errorMessage = "ERROR";
+ PrintErrorMessage(errorMessage);
+ }
+ }
+
+ return 1;
+}
diff --git a/C/Util/7zipInstall/7zipInstall.dsp b/C/Util/7zipInstall/7zipInstall.dsp
new file mode 100644
index 00000000..86911b97
--- /dev/null
+++ b/C/Util/7zipInstall/7zipInstall.dsp
@@ -0,0 +1,231 @@
+# Microsoft Developer Studio Project File - Name="7zipInstall" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=7zipInstall - 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 "7zipInstall.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 "7zipInstall.mak" CFG="7zipInstall - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "7zipInstall - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "7zipInstall - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "7zipInstall - 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 Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE2" /D "UNICODE2" /Yu"Precomp.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 /subsystem:windows /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 /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "7zipInstall - 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 /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE2" /D "UNICODE2" /Yu"Precomp.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 /subsystem:windows /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 /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "7zipInstall - Win32 Release"
+# Name "7zipInstall - Win32 Debug"
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\7z.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zAlloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zAlloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zArcIn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zBuf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zBuf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zCrc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zCrcOpt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zFile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zFile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zStream.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zVersion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Bcj2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Bcj2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Bra.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Bra.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Bra86.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\BraIA64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\CpuArch.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\CpuArch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Delta.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Delta.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Lzma2Dec.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Lzma2Dec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\LzmaDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\LzmaDec.h
+# End Source File
+# End Group
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\Precomp.c
+# ADD CPP /Yc"Precomp.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\Precomp.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\7zipInstall.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# End Target
+# End Project
diff --git a/C/Util/7zipInstall/7zipInstall.dsw b/C/Util/7zipInstall/7zipInstall.dsw
new file mode 100644
index 00000000..b7db73f4
--- /dev/null
+++ b/C/Util/7zipInstall/7zipInstall.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "7zipInstall"=.\7zipInstall.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/C/Util/7zipInstall/7zipInstall.manifest b/C/Util/7zipInstall/7zipInstall.manifest
new file mode 100644
index 00000000..f5c3ae5e
--- /dev/null
+++ b/C/Util/7zipInstall/7zipInstall.manifest
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7zipInstall" type="win32"/>
+<description>7-Zip Installer</description>
+<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges>
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
+</requestedPrivileges></security></trustInfo>
+<dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency>
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
+<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+</application></compatibility>
+<asmv3:application><asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
+<dpiAware>true</dpiAware></asmv3:windowsSettings></asmv3:application>
+</assembly>
diff --git a/C/Util/7zipInstall/Precomp.c b/C/Util/7zipInstall/Precomp.c
new file mode 100644
index 00000000..01605e3c
--- /dev/null
+++ b/C/Util/7zipInstall/Precomp.c
@@ -0,0 +1,4 @@
+/* Precomp.c -- StdAfx
+2013-01-21 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
diff --git a/C/Util/7zipInstall/Precomp.h b/C/Util/7zipInstall/Precomp.h
new file mode 100644
index 00000000..4c90d479
--- /dev/null
+++ b/C/Util/7zipInstall/Precomp.h
@@ -0,0 +1,11 @@
+/* Precomp.h -- StdAfx
+2015-05-24 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_PRECOMP_H
+#define __7Z_PRECOMP_H
+
+#include "../../Compiler.h"
+
+#include "../../7zTypes.h"
+
+#endif
diff --git a/C/Util/7zipInstall/makefile b/C/Util/7zipInstall/makefile
new file mode 100644
index 00000000..4da8f7af
--- /dev/null
+++ b/C/Util/7zipInstall/makefile
@@ -0,0 +1,40 @@
+PROG = 7zipInstall.exe
+
+!IFDEF _64BIT_INSTALLER
+CFLAGS = $(CFLAGS) -D_64BIT_INSTALLER
+!ENDIF
+
+CFLAGS = $(CFLAGS) -D_LZMA_SIZE_OPT
+
+CFLAGS = $(CFLAGS) \
+ -D_7Z_NO_METHOD_LZMA2 \
+ -D_7Z_NO_METHODS_FILTERS
+
+MAIN_OBJS = \
+ $O\7zipInstall.obj \
+
+C_OBJS = \
+ $O\7zAlloc.obj \
+ $O\7zArcIn.obj \
+ $O\7zBuf.obj \
+ $O\7zBuf2.obj \
+ $O\7zCrc.obj \
+ $O\7zCrcOpt.obj \
+ $O\7zFile.obj \
+ $O\7zDec.obj \
+ $O\7zStream.obj \
+ $O\Bcj2.obj \
+ $O\CpuArch.obj \
+ $O\LzmaDec.obj \
+
+OBJS = \
+ $(MAIN_OBJS) \
+ $(C_OBJS) \
+ $O\resource.res
+
+!include "../../../CPP/Build.mak"
+
+$(MAIN_OBJS): $(*B).c
+ $(COMPL_O1)
+$(C_OBJS): ../../$(*B).c
+ $(COMPL_O1)
diff --git a/C/Util/7zipInstall/resource.h b/C/Util/7zipInstall/resource.h
new file mode 100644
index 00000000..d78be84c
--- /dev/null
+++ b/C/Util/7zipInstall/resource.h
@@ -0,0 +1,9 @@
+#define IDD_INSTALL 100
+
+#define IDT_EXTRACT_EXTRACT_TO 110
+#define IDE_EXTRACT_PATH 111
+#define IDB_EXTRACT_SET_PATH 112
+#define IDT_CUR_FILE 113
+#define IDC_PROGRESS 114
+
+#define IDI_ICON 1
diff --git a/C/Util/7zipInstall/resource.rc b/C/Util/7zipInstall/resource.rc
new file mode 100644
index 00000000..df6474e3
--- /dev/null
+++ b/C/Util/7zipInstall/resource.rc
@@ -0,0 +1,47 @@
+#include <winnt.h>
+#include <WinUser.h>
+#include <CommCtrl.h>
+
+#define USE_COPYRIGHT_CR
+#include "../../7zVersion.rc"
+#include "resource.h"
+
+MY_VERSION_INFO(MY_VFT_APP, "7-Zip Installer", "7zipInstall", "7zipInstall.exe")
+
+1 ICON "7zip.ico"
+
+#define xc 184
+#define yc 96
+
+#define m 8
+#define bxs 64
+#define bys 16
+#define bxsDots 20
+
+#define xs (xc + m + m)
+#define ys (yc + m + m)
+
+#define bx1 (xs - m - bxs)
+#define bx2 (bx1 - m - bxs)
+
+#define by (ys - m - bys)
+
+IDD_INSTALL DIALOG 0, 0, xs, ys
+STYLE DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
+CAPTION "Install 7-Zip"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Destination folder:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8
+ EDITTEXT IDE_EXTRACT_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL
+ PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, 20, bxsDots, bys, WS_GROUP
+
+ LTEXT "", IDT_CUR_FILE, m, 50, xc, 8
+ CONTROL "", IDC_PROGRESS, "msctls_progress32", WS_BORDER, m, 64, xc, 10
+
+ DEFPUSHBUTTON "&Install", IDOK, bx2, by, bxs, bys, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
+END
+
+#ifndef UNDER_CE
+1 24 MOVEABLE PURE "7zipInstall.manifest"
+#endif
diff --git a/C/Util/7zipUninstall/7zipUninstall.c b/C/Util/7zipUninstall/7zipUninstall.c
new file mode 100644
index 00000000..68a8b029
--- /dev/null
+++ b/C/Util/7zipUninstall/7zipUninstall.c
@@ -0,0 +1,1077 @@
+/* 7zipUninstall.c - 7-Zip Uninstaller
+2015-06-13 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
+
+#define SZ_ERROR_ABORT 100
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+#pragma warning(disable : 4011) // vs2010: identifier truncated to _CRT_SECURE_CPP_OVERLOAD_SECURE
+#endif
+
+#include <windows.h>
+#include <ShlObj.h>
+
+#include "../../7zVersion.h"
+
+#include "resource.h"
+
+#define LLL_(quote) L##quote
+#define LLL(quote) LLL_(quote)
+
+// static const WCHAR *k_7zip = L"7-Zip";
+
+// #define _64BIT_INSTALLER 1
+
+#ifdef _WIN64
+ #define _64BIT_INSTALLER 1
+#endif
+
+#define k_7zip_with_Ver_base L"7-Zip " LLL(MY_VERSION)
+
+#ifdef _64BIT_INSTALLER
+ #define k_7zip_with_Ver k_7zip_with_Ver_base L" x64"
+#else
+ #define k_7zip_with_Ver k_7zip_with_Ver_base
+#endif
+
+// static const WCHAR *k_7zip_with_Ver_str = k_7zip_with_Ver;
+
+static const WCHAR *k_Reg_Software_7zip = L"Software\\7-Zip";
+
+static const WCHAR *k_Reg_Path = L"Path";
+
+static const WCHAR *k_Reg_Path32 = L"Path"
+ #ifdef _64BIT_INSTALLER
+ L"64"
+ #else
+ L"32"
+ #endif
+ ;
+
+#if defined(_64BIT_INSTALLER) && !defined(_WIN64)
+ #define k_Reg_WOW_Flag KEY_WOW64_64KEY
+#else
+ #define k_Reg_WOW_Flag 0
+#endif
+
+#ifdef _WIN64
+ #define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY
+#else
+ #define k_Reg_WOW_Flag_32 0
+#endif
+
+#define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}"
+
+static const WCHAR *k_Reg_CLSID_7zip = L"CLSID\\" k_7zip_CLSID;
+static const WCHAR *k_Reg_CLSID_7zip_Inproc = L"CLSID\\" k_7zip_CLSID L"\\InprocServer32";
+
+
+#define g_AllUsers True
+
+static Bool g_Install_was_Pressed;
+static Bool g_Finished;
+static Bool g_SilentMode;
+
+static HWND g_HWND;
+static HWND g_Path_HWND;
+static HWND g_InfoLine_HWND;
+static HWND g_Progress_HWND;
+
+typedef WINADVAPI LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved);
+static Func_RegDeleteKeyExW func_RegDeleteKeyExW;
+
+static WCHAR path[MAX_PATH * 2 + 40];
+static WCHAR workDir[MAX_PATH + 10];
+static WCHAR modulePath[MAX_PATH + 10];
+static WCHAR modulePrefix[MAX_PATH + 10];
+static WCHAR tempPath[MAX_PATH * 2 + 40];
+static WCHAR cmdLine[MAX_PATH * 3 + 40];
+static WCHAR copyPath[MAX_PATH * 2 + 40];
+
+static const WCHAR *kUninstallExe = L"Uninstall.exe";
+
+#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))
+
+static Bool AreStringsEqual_NoCase(const wchar_t *s1, const wchar_t *s2)
+{
+ for (;;)
+ {
+ wchar_t c1 = *s1++;
+ wchar_t c2 = *s2++;
+ if (c1 != c2 && MAKE_CHAR_UPPER(c1) != MAKE_CHAR_UPPER(c2))
+ return False;
+ if (c2 == 0)
+ return True;
+ }
+}
+
+static Bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2)
+{
+ for (;;)
+ {
+ wchar_t c1;
+ wchar_t c2 = *s2++;
+ if (c2 == 0)
+ return True;
+ c1 = *s1++;
+ if (c1 != c2 && MAKE_CHAR_UPPER(c1) != MAKE_CHAR_UPPER(c2))
+ return False;
+ }
+}
+
+static void NormalizePrefix(WCHAR *s)
+{
+ size_t len = wcslen(s);
+ if (len != 0)
+ if (s[len - 1] != WCHAR_PATH_SEPARATOR)
+ {
+ s[len] = WCHAR_PATH_SEPARATOR;
+ s[len + 1] = 0;
+ }
+}
+
+static int MyRegistry_QueryString(HKEY hKey, LPCWSTR name, LPWSTR dest)
+{
+ DWORD cnt = MAX_PATH * sizeof(name[0]);
+ DWORD type = 0;
+ LONG res = RegQueryValueExW(hKey, name, NULL, &type, (LPBYTE)dest, (DWORD *)&cnt);
+ if (type != REG_SZ)
+ return False;
+ return res == ERROR_SUCCESS;
+}
+
+static int MyRegistry_QueryString2(HKEY hKey, LPCWSTR keyName, LPCWSTR valName, LPWSTR dest)
+{
+ HKEY key = 0;
+ LONG res = RegOpenKeyExW(hKey, keyName, 0, KEY_READ | k_Reg_WOW_Flag, &key);
+ if (res != ERROR_SUCCESS)
+ return False;
+ {
+ Bool res2 = MyRegistry_QueryString(key, valName, dest);
+ RegCloseKey(key);
+ return res2;
+ }
+}
+
+static LONG MyRegistry_OpenKey_ReadWrite(HKEY parentKey, LPCWSTR name, HKEY *destKey)
+{
+ return RegOpenKeyExW(parentKey, name, 0, KEY_READ | KEY_WRITE | k_Reg_WOW_Flag, destKey);
+}
+
+static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCWSTR name)
+{
+ #if k_Reg_WOW_Flag != 0
+ if (func_RegDeleteKeyExW)
+ return func_RegDeleteKeyExW(parentKey, name, k_Reg_WOW_Flag, 0);
+ return E_FAIL;
+ #else
+ return RegDeleteKeyW(parentKey, name);
+ #endif
+}
+
+#ifdef _64BIT_INSTALLER
+
+static int MyRegistry_QueryString2_32(HKEY hKey, LPCWSTR keyName, LPCWSTR valName, LPWSTR dest)
+{
+ HKEY key = 0;
+ LONG res = RegOpenKeyExW(hKey, keyName, 0, KEY_READ | k_Reg_WOW_Flag_32, &key);
+ if (res != ERROR_SUCCESS)
+ return False;
+ {
+ Bool res2 = MyRegistry_QueryString(key, valName, dest);
+ RegCloseKey(key);
+ return res2;
+ }
+}
+
+static LONG MyRegistry_OpenKey_ReadWrite_32(HKEY parentKey, LPCWSTR name, HKEY *destKey)
+{
+ return RegOpenKeyExW(parentKey, name, 0, KEY_READ | KEY_WRITE | k_Reg_WOW_Flag_32, destKey);
+}
+
+static LONG MyRegistry_DeleteKey_32(HKEY parentKey, LPCWSTR name)
+{
+ #if k_Reg_WOW_Flag_32 != 0
+ if (func_RegDeleteKeyExW)
+ return func_RegDeleteKeyExW(parentKey, name, k_Reg_WOW_Flag_32, 0);
+ return E_FAIL;
+ #else
+ return RegDeleteKeyW(parentKey, name);
+ #endif
+}
+
+#endif
+
+
+
+
+static void MyReg_DeleteVal_Path_if_Equal(HKEY hKey, LPCWSTR name)
+{
+ WCHAR s[MAX_PATH + 10];
+ if (MyRegistry_QueryString(hKey, name, s))
+ {
+ NormalizePrefix(s);
+ if (AreStringsEqual_NoCase(s, path))
+ RegDeleteValueW(hKey, name);
+ }
+}
+
+static void SetRegKey_Path2(HKEY parentKey)
+{
+ HKEY key = 0;
+ LONG res = MyRegistry_OpenKey_ReadWrite(parentKey, k_Reg_Software_7zip, &key);
+ if (res == ERROR_SUCCESS)
+ {
+ MyReg_DeleteVal_Path_if_Equal(key, k_Reg_Path32);
+ MyReg_DeleteVal_Path_if_Equal(key, k_Reg_Path);
+
+ RegCloseKey(key);
+ // MyRegistry_DeleteKey(parentKey, k_Reg_Software_7zip);
+ }
+}
+
+static void SetRegKey_Path()
+{
+ SetRegKey_Path2(HKEY_CURRENT_USER);
+ SetRegKey_Path2(HKEY_LOCAL_MACHINE);
+}
+
+static HRESULT CreateShellLink(LPCWSTR srcPath, LPCWSTR targetPath)
+{
+ IShellLinkW *sl;
+
+ // CoInitialize has already been called.
+ HRESULT hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID*)&sl);
+
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile *pf;
+
+ hres = sl->lpVtbl->QueryInterface(sl, &IID_IPersistFile, (LPVOID *)&pf);
+
+ if (SUCCEEDED(hres))
+ {
+ WCHAR s[MAX_PATH + 10];
+ hres = pf->lpVtbl->Load(pf, srcPath, TRUE);
+ pf->lpVtbl->Release(pf);
+
+ if (SUCCEEDED(hres))
+ {
+ hres = sl->lpVtbl->GetPath(sl, s, MAX_PATH, NULL, 0); // SLGP_RAWPATH
+ if (!AreStringsEqual_NoCase(s, targetPath))
+ hres = S_FALSE;
+ }
+ }
+
+ sl->lpVtbl->Release(sl);
+ }
+
+ return hres;
+}
+
+static void SetShellProgramsGroup(HWND hwndOwner)
+{
+ #ifdef UNDER_CE
+
+ UNUSED_VAR(hwndOwner)
+
+ #else
+
+ unsigned i = (g_AllUsers ? 1 : 2);
+
+ for (; i < 3; i++)
+ {
+ // Bool isOK = True;
+ WCHAR link[MAX_PATH + 40];
+ WCHAR destPath[MAX_PATH + 40];
+
+ link[0] = 0;
+
+ if (SHGetFolderPathW(hwndOwner,
+ i == 1 ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS,
+ NULL, SHGFP_TYPE_CURRENT, link) != S_OK)
+ continue;
+
+ NormalizePrefix(link);
+ wcscat(link, L"7-Zip\\");
+
+ {
+ const size_t baseLen = wcslen(link);
+ unsigned k;
+ Bool needDelete = False;
+
+ for (k = 0; k < 2; k++)
+ {
+ wcscpy(link + baseLen, k == 0 ?
+ L"7-Zip File Manager.lnk" :
+ L"7-Zip Help.lnk");
+ wcscpy(destPath, path);
+ wcscat(destPath, k == 0 ?
+ L"7zFM.exe" :
+ L"7-zip.chm");
+
+ if (CreateShellLink(link, destPath) == S_OK)
+ {
+ needDelete = True;
+ DeleteFileW(link);
+ }
+ }
+
+ if (needDelete)
+ {
+ link[baseLen] = 0;
+ RemoveDirectoryW(link);
+ }
+ }
+ }
+
+ #endif
+}
+
+
+static const WCHAR * const k_ShellEx_Items[] =
+{
+ L"*\\shellex\\ContextMenuHandlers"
+ , L"Directory\\shellex\\ContextMenuHandlers"
+ , L"Folder\\shellex\\ContextMenuHandlers"
+ , L"Directory\\shellex\\DragDropHandlers"
+ , L"Drive\\shellex\\DragDropHandlers"
+};
+
+static const WCHAR *k_Shell_Approved = L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
+
+static const WCHAR *k_AppPaths_7zFm = L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\7zFM.exe";
+#define k_REG_Uninstall L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
+static const WCHAR *k_Uninstall_7zip = k_REG_Uninstall L"7-Zip";
+
+
+static Bool AreEqual_Path_PrefixName(const wchar_t *s, const wchar_t *prefix, const wchar_t *name)
+{
+ if (!IsString1PrefixedByString2_NoCase(s, prefix))
+ return False;
+ return AreStringsEqual_NoCase(s + wcslen(prefix), name);
+}
+
+static void WriteCLSID()
+{
+ WCHAR s[MAX_PATH + 30];
+
+ if (MyRegistry_QueryString2(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc, NULL, s))
+ {
+ if (AreEqual_Path_PrefixName(s, path, L"7-zip.dll"))
+ {
+ LONG res = MyRegistry_DeleteKey(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc);
+ if (res == ERROR_SUCCESS)
+ MyRegistry_DeleteKey(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip);
+
+ {
+ unsigned i;
+ for (i = 0; i < sizeof(k_ShellEx_Items) / sizeof(k_ShellEx_Items[0]); i++)
+ {
+ WCHAR destPath[MAX_PATH];
+ wcscpy(destPath, k_ShellEx_Items[i]);
+ wcscat(destPath, L"\\7-Zip");
+
+ MyRegistry_DeleteKey(HKEY_CLASSES_ROOT, destPath);
+ }
+ }
+
+ {
+ HKEY destKey = 0;
+ LONG res = MyRegistry_OpenKey_ReadWrite(HKEY_LOCAL_MACHINE, k_Shell_Approved, &destKey);
+ if (res == ERROR_SUCCESS)
+ {
+ RegDeleteValueW(destKey, k_7zip_CLSID);
+ res = RegCloseKey(destKey);
+ }
+ }
+ }
+ }
+
+
+ #ifdef _64BIT_INSTALLER
+
+ if (MyRegistry_QueryString2_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc, NULL, s))
+ {
+ if (AreEqual_Path_PrefixName(s, path, L"7-zip32.dll"))
+ {
+ LONG res = MyRegistry_DeleteKey_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip_Inproc);
+ if (res == ERROR_SUCCESS)
+ MyRegistry_DeleteKey_32(HKEY_CLASSES_ROOT, k_Reg_CLSID_7zip);
+
+ {
+ unsigned i;
+ for (i = 0; i < sizeof(k_ShellEx_Items) / sizeof(k_ShellEx_Items[0]); i++)
+ {
+ WCHAR destPath[MAX_PATH];
+ wcscpy(destPath, k_ShellEx_Items[i]);
+ wcscat(destPath, L"\\7-Zip");
+
+ MyRegistry_DeleteKey_32(HKEY_CLASSES_ROOT, destPath);
+ }
+ }
+
+ {
+ HKEY destKey = 0;
+ LONG res = MyRegistry_OpenKey_ReadWrite_32(HKEY_LOCAL_MACHINE, k_Shell_Approved, &destKey);
+ if (res == ERROR_SUCCESS)
+ {
+ RegDeleteValueW(destKey, k_7zip_CLSID);
+ res = RegCloseKey(destKey);
+ }
+ }
+ }
+ }
+
+ #endif
+
+
+ if (MyRegistry_QueryString2(HKEY_LOCAL_MACHINE, k_AppPaths_7zFm, NULL, s))
+ if (AreEqual_Path_PrefixName(s, path, L"7zFM.exe"))
+ MyRegistry_DeleteKey(HKEY_LOCAL_MACHINE, k_AppPaths_7zFm);
+
+ if (MyRegistry_QueryString2(HKEY_LOCAL_MACHINE, k_Uninstall_7zip, L"UninstallString", s))
+ if (AreEqual_Path_PrefixName(s, path, kUninstallExe))
+ MyRegistry_DeleteKey(HKEY_LOCAL_MACHINE, k_Uninstall_7zip);
+}
+
+
+static const wchar_t *GetCmdParam(const wchar_t *s)
+{
+ Bool quoteMode = False;
+ for (;; s++)
+ {
+ wchar_t c = *s;
+ if (c == L'\"')
+ quoteMode = !quoteMode;
+ else if (c == 0 || (c == L' ' && !quoteMode))
+ return s;
+ }
+}
+
+static void RemoveQuotes(wchar_t *s)
+{
+ const wchar_t *src = s;
+ for (;;)
+ {
+ wchar_t c = *src++;
+ if (c == '\"')
+ continue;
+ *s++ = c;
+ if (c == 0)
+ return;
+ }
+}
+
+static Bool DoesFileOrDirExist()
+{
+ return (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES);
+}
+
+static BOOL RemoveFileAfterReboot2(const WCHAR *s)
+{
+ #ifndef UNDER_CE
+ return MoveFileExW(s, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+ #else
+ UNUSED_VAR(s)
+ return TRUE;
+ #endif
+}
+
+static BOOL RemoveFileAfterReboot()
+{
+ return RemoveFileAfterReboot2(path);
+}
+
+#define IS_LIMIT_CHAR(c) (c == 0 || c == ' ')
+
+static Bool IsThereSpace(const wchar_t *s)
+{
+ for (;;)
+ {
+ wchar_t c = *s++;
+ if (c == 0)
+ return False;
+ if (c == ' ')
+ return True;
+ }
+}
+
+static void AddPathParam(wchar_t *dest, const wchar_t *src)
+{
+ Bool needQuote = IsThereSpace(src);
+ if (needQuote)
+ wcscat(dest, L"\"");
+ wcscat(dest, src);
+ if (needQuote)
+ wcscat(dest, L"\"");
+}
+
+
+
+static Bool GetErrorMessage(DWORD errorCode, WCHAR *message)
+{
+ LPVOID msgBuf;
+ if (FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)
+ return False;
+ wcscpy(message, msgBuf);
+ LocalFree(msgBuf);
+ return True;
+}
+
+static BOOL RemoveDir()
+{
+ DWORD attrib = GetFileAttributesW(path);
+ if (attrib == INVALID_FILE_ATTRIBUTES)
+ return TRUE;
+ if (RemoveDirectoryW(path))
+ return TRUE;
+ return RemoveFileAfterReboot();
+}
+
+
+
+
+
+#define k_Lang L"Lang"
+
+// NUM_LANG_TXT_FILES files are placed before en.ttt
+#define NUM_LANG_TXT_FILES 86
+
+#ifdef _64BIT_INSTALLER
+ #define NUM_EXTRA_FILES_64BIT 1
+#else
+ #define NUM_EXTRA_FILES_64BIT 0
+#endif
+
+#define NUM_FILES (NUM_LANG_TXT_FILES + 1 + 13 + NUM_EXTRA_FILES_64BIT)
+
+static const char *k_Names =
+ "af an ar ast az ba be bg bn br ca co cs cy da de el eo es et eu ext"
+ " fa fi fr fur fy ga gl gu he hi hr hu hy id io is it ja ka kaa kk ko ku ku-ckb ky"
+ " lij lt lv mk mn mng mng2 mr ms nb ne nl nn pa-in pl ps pt pt-br ro ru"
+ " sa si sk sl sq sr-spc sr-spl sv ta th tr tt ug uk uz va vi zh-cn zh-tw"
+ " en.ttt"
+ " descript.ion"
+ " History.txt"
+ " License.txt"
+ " readme.txt"
+ " 7-zip.chm"
+ " 7z.sfx"
+ " 7zCon.sfx"
+ " 7z.exe"
+ " 7zG.exe"
+ " 7z.dll"
+ " 7zFM.exe"
+ #ifdef _64BIT_INSTALLER
+ " 7-zip32.dll"
+ #endif
+ " 7-zip.dll"
+ " Uninstall.exe";
+
+
+
+static int Install()
+{
+ SRes res = SZ_OK;
+ WRes winRes = 0;
+
+ // Bool needReboot = False;
+ const size_t pathLen = wcslen(path);
+
+ if (!g_SilentMode)
+ {
+ ShowWindow(g_Progress_HWND, SW_SHOW);
+ ShowWindow(g_InfoLine_HWND, SW_SHOW);
+ SendMessage(g_Progress_HWND, PBM_SETRANGE32, 0, NUM_FILES);
+ }
+
+ {
+ unsigned i;
+ const char *curName = k_Names;
+
+ for (i = 0; *curName != 0; i++)
+ {
+ WCHAR *temp;
+
+ if (!g_SilentMode)
+ {
+ MSG msg;
+
+ // g_HWND
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if (!IsDialogMessage(g_HWND, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ if (!g_HWND)
+ return 1;
+ }
+
+ // Sleep(1);
+ SendMessage(g_Progress_HWND, PBM_SETPOS, i, 0);
+ }
+
+ path[pathLen] = 0;
+ temp = path + pathLen;
+
+ if (i <= NUM_LANG_TXT_FILES)
+ wcscpy(temp, k_Lang L"\\");
+
+ {
+ WCHAR *dest = temp + wcslen(temp);
+
+ for (;;)
+ {
+ char c = *curName;
+ if (c == 0)
+ break;
+ curName++;
+ if (c == ' ')
+ break;
+ *dest++ = (Byte)c;
+ }
+
+ *dest = 0;
+ }
+
+ if (i < NUM_LANG_TXT_FILES)
+ wcscat(temp, L".txt");
+
+ if (!g_SilentMode)
+ SetWindowTextW(g_InfoLine_HWND, temp);
+
+ {
+ DWORD attrib = GetFileAttributesW(path);
+ if (attrib == INVALID_FILE_ATTRIBUTES)
+ continue;
+ if (attrib & FILE_ATTRIBUTE_READONLY)
+ SetFileAttributesW(path, 0);
+ if (!DeleteFileW(path))
+ {
+ if (!RemoveFileAfterReboot())
+ {
+ winRes = GetLastError();
+ }
+ /*
+ else
+ needReboot = True;
+ */
+ }
+ }
+ }
+
+ wcscpy(path + pathLen, k_Lang);
+ RemoveDir();
+
+ path[pathLen] = 0;
+ RemoveDir();
+
+ if (!g_SilentMode)
+ SendMessage(g_Progress_HWND, PBM_SETPOS, i, 0);
+
+ if (*curName == 0)
+ {
+ SetRegKey_Path();
+ WriteCLSID();
+ SetShellProgramsGroup(g_HWND);
+ if (!g_SilentMode)
+ SetWindowTextW(g_InfoLine_HWND, k_7zip_with_Ver L" is uninstalled");
+ }
+ }
+
+ if (winRes != 0)
+ res = SZ_ERROR_FAIL;
+
+ if (res == SZ_OK)
+ {
+ // if (!g_SilentMode && needReboot);
+ return 0;
+ }
+
+ if (!g_SilentMode)
+ {
+ WCHAR m[MAX_PATH + 100];
+ m[0] = 0;
+ if (winRes == 0 || !GetErrorMessage(winRes, m))
+ wcscpy(m, L"ERROR");
+ MessageBoxW(g_HWND, m, L"Error", MB_ICONERROR | MB_OK);
+ }
+
+ return 1;
+}
+
+
+static void OnClose()
+{
+ if (g_Install_was_Pressed && !g_Finished)
+ {
+ if (MessageBoxW(g_HWND,
+ L"Do you want to cancel uninstallation?",
+ k_7zip_with_Ver,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) != IDYES)
+ return;
+ }
+ DestroyWindow(g_HWND);
+ g_HWND = NULL;
+}
+
+static INT_PTR CALLBACK MyDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ UNUSED_VAR(lParam)
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ g_Path_HWND = GetDlgItem(hwnd, IDE_EXTRACT_PATH);
+ g_InfoLine_HWND = GetDlgItem(hwnd, IDT_CUR_FILE);
+ g_Progress_HWND = GetDlgItem(hwnd, IDC_PROGRESS);
+
+ SetWindowTextW(hwnd, k_7zip_with_Ver L" Uninstall");
+ SetDlgItemTextW(hwnd, IDE_EXTRACT_PATH, path);
+
+ ShowWindow(g_Progress_HWND, SW_HIDE);
+ ShowWindow(g_InfoLine_HWND, SW_HIDE);
+
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ if (g_Finished)
+ {
+ OnClose();
+ break;
+ }
+ if (!g_Install_was_Pressed)
+ {
+ SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDCANCEL), TRUE);
+
+ EnableWindow(g_Path_HWND, FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
+
+ g_Install_was_Pressed = True;
+ return TRUE;
+ }
+ break;
+ }
+
+ case IDCANCEL:
+ {
+ OnClose();
+ break;
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ OnClose();
+ break;
+ /*
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return TRUE;
+ */
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ #ifdef UNDER_CE
+ LPWSTR
+ #else
+ LPSTR
+ #endif
+ lpCmdLine, int nCmdShow)
+{
+ const wchar_t *cmdParams;
+ Bool useTemp = True;
+
+ UNUSED_VAR(hPrevInstance)
+ UNUSED_VAR(lpCmdLine)
+ UNUSED_VAR(nCmdShow)
+
+ #ifndef UNDER_CE
+ CoInitialize(NULL);
+ #endif
+
+ #ifndef UNDER_CE
+ func_RegDeleteKeyExW = (Func_RegDeleteKeyExW)
+ GetProcAddress(GetModuleHandleW(L"advapi32.dll"), "RegDeleteKeyExW");
+ #endif
+
+ {
+ const wchar_t *s = GetCommandLineW();
+
+ #ifndef UNDER_CE
+ s = GetCmdParam(s);
+ #endif
+
+ cmdParams = s;
+
+ for (;;)
+ {
+ {
+ wchar_t c = *s;
+ if (c == 0)
+ break;
+ if (c == ' ')
+ {
+ s++;
+ continue;
+ }
+ }
+
+ {
+ const wchar_t *s2 = GetCmdParam(s);
+ if (s[0] == '/')
+ {
+ if (s[1] == 'S' && IS_LIMIT_CHAR(s[2]))
+ g_SilentMode = True;
+ else if (s[1] == 'N' && IS_LIMIT_CHAR(s[2]))
+ useTemp = False;
+ else if (s[1] == 'D' && s[2] == '=')
+ {
+ size_t num;
+ s += 3;
+ num = s2 - s;
+ if (num <= MAX_PATH)
+ {
+ wcsncpy(workDir, s, num);
+ workDir[num] = 0;
+ RemoveQuotes(workDir);
+ useTemp = False;
+ }
+ }
+ }
+ s = s2;
+ }
+ }
+ }
+
+
+ {
+ wchar_t *name;
+ DWORD len = GetModuleFileNameW(NULL, modulePath, MAX_PATH);
+ if (len == 0 || len > MAX_PATH)
+ return 1;
+
+ name = NULL;
+ wcscpy(modulePrefix, modulePath);
+
+ {
+ wchar_t *s = modulePrefix;
+ for (;;)
+ {
+ wchar_t c = *s++;
+ if (c == 0)
+ break;
+ if (c == WCHAR_PATH_SEPARATOR)
+ name = s;
+ }
+ }
+
+ if (!name)
+ return 1;
+
+ if (!AreStringsEqual_NoCase(name, kUninstallExe))
+ useTemp = False;
+
+ *name = 0; // keep only prefix for modulePrefix
+ }
+
+
+ if (useTemp)
+ {
+ DWORD winRes = GetTempPathW(MAX_PATH, path);
+
+ // GetTempPath: the returned string ends with a backslash
+ /*
+ {
+ WCHAR s[MAX_PATH + 1];
+ wcscpy(s, path);
+ GetLongPathNameW(s, path, MAX_PATH);
+ }
+ */
+
+ if (winRes != 0 && winRes <= MAX_PATH + 1
+ && !IsString1PrefixedByString2_NoCase(modulePrefix, path))
+ {
+ unsigned i;
+ DWORD d;
+
+ const size_t pathLen = wcslen(path);
+ d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
+
+ for (i = 0; i < 100; i++, d += GetTickCount())
+ {
+ wcscpy(path + pathLen, L"7z");
+
+ {
+ wchar_t *s = path + wcslen(path);
+ UInt32 value = d;
+ unsigned k;
+ for (k = 0; k < 8; k++)
+ {
+ unsigned t = value & 0xF;
+ value >>= 4;
+ s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ }
+ s[k] = 0;
+ }
+
+ if (DoesFileOrDirExist())
+ continue;
+ if (CreateDirectoryW(path, NULL))
+ {
+ wcscat(path, WSTRING_PATH_SEPARATOR);
+ wcscpy(tempPath, path);
+ break;
+ }
+ if (GetLastError() != ERROR_ALREADY_EXISTS)
+ break;
+ }
+
+ if (tempPath[0] != 0)
+ {
+ wcscpy(copyPath, tempPath);
+ wcscat(copyPath, L"Uninst.exe"); // we need not "Uninstall.exe" here
+
+ if (CopyFileW(modulePath, copyPath, TRUE))
+ {
+ RemoveFileAfterReboot2(copyPath);
+ RemoveFileAfterReboot2(tempPath);
+
+ {
+ STARTUPINFOW si;
+ PROCESS_INFORMATION pi;
+ cmdLine[0] = 0;
+
+ // maybe CreateProcess supports path with spaces even without quotes.
+ AddPathParam(cmdLine, copyPath);
+ wcscat(cmdLine, L" /N /D=");
+ AddPathParam(cmdLine, modulePrefix);
+
+ if (cmdParams[0] != 0 && wcslen(cmdParams) < MAX_PATH * 2 + 10)
+ wcscat(cmdLine, cmdParams);
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+
+ if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, tempPath, &si, &pi))
+ {
+ CloseHandle(pi.hThread);
+ if (pi.hProcess)
+ {
+ CloseHandle(pi.hProcess);
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ wcscpy(path, modulePrefix);
+
+ if (workDir[0] != 0)
+ {
+ wcscpy(path, workDir);
+ NormalizePrefix(path);
+ }
+
+ /*
+ if (path[0] == 0)
+ {
+ HKEY key = 0;
+ Bool ok = False;
+ LONG res = RegOpenKeyExW(HKEY_CURRENT_USER, k_Reg_Software_7zip, 0, KEY_READ | k_Reg_WOW_Flag, &key);
+ if (res == ERROR_SUCCESS)
+ {
+ ok = MyRegistry_QueryString(key, k_Reg_Path32, path);
+ // ok = MyRegistry_QueryString(key, k_Reg_Path, path);
+ RegCloseKey(key);
+ }
+ }
+ */
+
+
+ if (g_SilentMode)
+ return Install();
+
+ {
+ int retCode = 1;
+ g_HWND = CreateDialog(
+ hInstance,
+ // GetModuleHandle(NULL),
+ MAKEINTRESOURCE(IDD_INSTALL), NULL, MyDlgProc);
+ if (!g_HWND)
+ return 1;
+
+ {
+ HICON hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
+ // SendMessage(g_HWND, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
+ SendMessage(g_HWND, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hIcon);
+ }
+
+ {
+ BOOL bRet;
+ MSG msg;
+
+ while ((bRet = GetMessage(&msg, g_HWND, 0, 0)) != 0)
+ {
+ if (bRet == -1)
+ return retCode;
+ if (!g_HWND)
+ return retCode;
+
+ if (!IsDialogMessage(g_HWND, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ if (!g_HWND)
+ return retCode;
+
+ if (g_Install_was_Pressed && !g_Finished)
+ {
+ retCode = Install();
+ g_Finished = True;
+ if (retCode != 0)
+ break;
+ if (!g_HWND)
+ break;
+ {
+ SetDlgItemTextW(g_HWND, IDOK, L"Close");
+ EnableWindow(GetDlgItem(g_HWND, IDOK), TRUE);
+ EnableWindow(GetDlgItem(g_HWND, IDCANCEL), FALSE);
+ SendMessage(g_HWND, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(g_HWND, IDOK), TRUE);
+ }
+ }
+ }
+
+ if (g_HWND)
+ {
+ DestroyWindow(g_HWND);
+ g_HWND = NULL;
+ }
+ }
+
+ return retCode;
+ }
+}
diff --git a/C/Util/7zipUninstall/7zipUninstall.dsp b/C/Util/7zipUninstall/7zipUninstall.dsp
new file mode 100644
index 00000000..06afc672
--- /dev/null
+++ b/C/Util/7zipUninstall/7zipUninstall.dsp
@@ -0,0 +1,124 @@
+# Microsoft Developer Studio Project File - Name="7zipUninstall" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=7zipUninstall - 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 "7zipUninstall.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 "7zipUninstall.mak" CFG="7zipUninstall - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "7zipUninstall - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "7zipUninstall - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "7zipUninstall - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE2" /D "UNICODE2" /Yu"Precomp.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 /subsystem:windows /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 /subsystem:windows /machine:I386 /out:"Release/Uninstall.exe"
+
+!ELSEIF "$(CFG)" == "7zipUninstall - 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 /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE2" /D "UNICODE2" /Yu"Precomp.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 /subsystem:windows /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 /subsystem:windows /debug /machine:I386 /out:"Debug/Uninstall.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "7zipUninstall - Win32 Release"
+# Name "7zipUninstall - Win32 Debug"
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\7zTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zVersion.h
+# End Source File
+# End Group
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\Precomp.c
+# ADD CPP /Yc"Precomp.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\Precomp.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\7zipUninstall.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# End Target
+# End Project
diff --git a/C/Util/7zipUninstall/7zipUninstall.dsw b/C/Util/7zipUninstall/7zipUninstall.dsw
new file mode 100644
index 00000000..2873eda6
--- /dev/null
+++ b/C/Util/7zipUninstall/7zipUninstall.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "7zipUninstall"=.\7zipUninstall.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/C/Util/7zipUninstall/7zipUninstall.ico b/C/Util/7zipUninstall/7zipUninstall.ico
new file mode 100644
index 00000000..19eb20ca
--- /dev/null
+++ b/C/Util/7zipUninstall/7zipUninstall.ico
Binary files differ
diff --git a/C/Util/7zipUninstall/7zipUninstall.manifest b/C/Util/7zipUninstall/7zipUninstall.manifest
new file mode 100644
index 00000000..a6014434
--- /dev/null
+++ b/C/Util/7zipUninstall/7zipUninstall.manifest
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.Uninstall" type="win32"/>
+<description>7-Zip Uninstaller</description>
+<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges>
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
+</requestedPrivileges></security></trustInfo>
+<dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly></dependency>
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
+<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+</application></compatibility>
+<asmv3:application><asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
+<dpiAware>true</dpiAware></asmv3:windowsSettings></asmv3:application>
+</assembly>
diff --git a/C/Util/7zipUninstall/Precomp.c b/C/Util/7zipUninstall/Precomp.c
new file mode 100644
index 00000000..01605e3c
--- /dev/null
+++ b/C/Util/7zipUninstall/Precomp.c
@@ -0,0 +1,4 @@
+/* Precomp.c -- StdAfx
+2013-01-21 : Igor Pavlov : Public domain */
+
+#include "Precomp.h"
diff --git a/C/Util/7zipUninstall/Precomp.h b/C/Util/7zipUninstall/Precomp.h
new file mode 100644
index 00000000..4c90d479
--- /dev/null
+++ b/C/Util/7zipUninstall/Precomp.h
@@ -0,0 +1,11 @@
+/* Precomp.h -- StdAfx
+2015-05-24 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_PRECOMP_H
+#define __7Z_PRECOMP_H
+
+#include "../../Compiler.h"
+
+#include "../../7zTypes.h"
+
+#endif
diff --git a/C/Util/7zipUninstall/makefile b/C/Util/7zipUninstall/makefile
new file mode 100644
index 00000000..6c7a22ee
--- /dev/null
+++ b/C/Util/7zipUninstall/makefile
@@ -0,0 +1,17 @@
+PROG = 7zipUninstall.exe
+
+!IFDEF _64BIT_INSTALLER
+CFLAGS = $(CFLAGS) -D_64BIT_INSTALLER
+!ENDIF
+
+MAIN_OBJS = \
+ $O\7zipUninstall.obj \
+
+OBJS = \
+ $(MAIN_OBJS) \
+ $O\resource.res
+
+!include "../../../CPP/Build.mak"
+
+$(MAIN_OBJS): $(*B).c
+ $(COMPL_O1)
diff --git a/C/Util/7zipUninstall/resource.h b/C/Util/7zipUninstall/resource.h
new file mode 100644
index 00000000..701babdb
--- /dev/null
+++ b/C/Util/7zipUninstall/resource.h
@@ -0,0 +1,9 @@
+#define IDD_INSTALL 100
+
+#define IDT_EXTRACT_EXTRACT_TO 110
+#define IDE_EXTRACT_PATH 111
+
+#define IDT_CUR_FILE 113
+#define IDC_PROGRESS 114
+
+#define IDI_ICON 1
diff --git a/C/Util/7zipUninstall/resource.rc b/C/Util/7zipUninstall/resource.rc
new file mode 100644
index 00000000..00bdcc07
--- /dev/null
+++ b/C/Util/7zipUninstall/resource.rc
@@ -0,0 +1,47 @@
+#include <winnt.h>
+#include <WinUser.h>
+#include <CommCtrl.h>
+
+#define USE_COPYRIGHT_CR
+#include "../../7zVersion.rc"
+#include "resource.h"
+
+MY_VERSION_INFO(MY_VFT_APP, "7-Zip Uninstaller", "Uninstall", "Uninstall.exe")
+
+1 ICON "7zipUninstall.ico"
+
+#define xc 184
+#define yc 96
+
+#define m 8
+#define bxs 64
+#define bys 16
+
+
+#define xs (xc + m + m)
+#define ys (yc + m + m)
+
+#define bx1 (xs - m - bxs)
+#define bx2 (bx1 - m - bxs)
+
+#define by (ys - m - bys)
+
+IDD_INSTALL DIALOG 0, 0, xs, ys
+STYLE DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
+CAPTION "Uninstall 7-Zip"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Uninstall from:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8
+ EDITTEXT IDE_EXTRACT_PATH, m, 21, xc, 14, ES_AUTOHSCROLL | WS_DISABLED
+
+
+ LTEXT "", IDT_CUR_FILE, m, 50, xc, 8
+ CONTROL "", IDC_PROGRESS, "msctls_progress32", WS_BORDER, m, 64, xc, 10
+
+ DEFPUSHBUTTON "&Uninstall", IDOK, bx2, by, bxs, bys, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
+END
+
+#ifndef UNDER_CE
+1 24 MOVEABLE PURE "7zipUninstall.manifest"
+#endif
diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c
index 4606107e..2e386b4f 100644
--- a/C/Util/Lzma/LzmaUtil.c
+++ b/C/Util/Lzma/LzmaUtil.c
@@ -1,5 +1,5 @@
/* LzmaUtil.c -- Test application for LZMA compression
-2014-12-31 : Igor Pavlov : Public domain */
+2015-06-13 : Igor Pavlov : Public domain */
#include "../../Precomp.h"
@@ -18,10 +18,6 @@ const char *kCantWriteMessage = "Can not write output file";
const char *kCantAllocateMessage = "Can not allocate memory";
const char *kDataErrorMessage = "Data error";
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
void PrintHelp(char *buffer)
{
strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c
index 570bd70f..d4d441f8 100644
--- a/C/Util/SfxSetup/SfxSetup.c
+++ b/C/Util/SfxSetup/SfxSetup.c
@@ -1,5 +1,5 @@
/* SfxSetup.c - 7z SFX Setup
-2014-12-07 : Igor Pavlov : Public domain */
+2015-03-25 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -23,7 +23,7 @@
#define k_EXE_ExtIndex 2
-static const char *kExts[] =
+static const char * const kExts[] =
{
"bat"
, "cmd"
@@ -37,7 +37,7 @@ static const char *kExts[] =
, "htm"
};
-static const char *kNames[] =
+static const char * const kNames[] =
{
"setup"
, "install"
@@ -63,7 +63,7 @@ static unsigned FindExt(const wchar_t *s, unsigned *extLen)
#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c)))
-static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len)
+static unsigned FindItem(const char * const *items, unsigned num, const wchar_t *s, unsigned len)
{
unsigned i;
for (i = 0; i < num; i++)
@@ -75,7 +75,7 @@ static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, uns
continue;
for (j = 0; j < len; j++)
{
- unsigned c = item[j];
+ unsigned c = (Byte)item[j];
if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j])
break;
}
@@ -182,6 +182,7 @@ static WRes RemoveDirWithSubItems(WCHAR *path)
path[len] = L'\0';
if (handle == INVALID_HANDLE_VALUE)
return GetLastError();
+
for (;;)
{
if (wcscmp(fd.cFileName, L".") != 0 &&
@@ -199,9 +200,11 @@ static WRes RemoveDirWithSubItems(WCHAR *path)
if (DeleteFileW(path) == 0)
res = GetLastError();
}
+
if (res != 0)
break;
}
+
if (!FindNextFileW(handle, &fd))
{
res = GetLastError();
@@ -210,6 +213,7 @@ static WRes RemoveDirWithSubItems(WCHAR *path)
break;
}
}
+
path[len] = L'\0';
FindClose(handle);
if (res == 0)
@@ -248,6 +252,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
const wchar_t *cmdLineParams;
const char *errorMessage = NULL;
Bool useShellExecute = True;
+ DWORD exitCode = 0;
#ifdef _CONSOLE
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
@@ -315,7 +320,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
{
unsigned t = value & 0xF;
value >>= 4;
- s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
s[k] = '\0';
}
@@ -584,6 +589,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if (hProcess != 0)
{
WaitForSingleObject(hProcess, INFINITE);
+ if (!GetExitCodeProcess(hProcess, &exitCode))
+ exitCode = 1;
CloseHandle(hProcess);
}
@@ -596,7 +603,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
RemoveDirWithSubItems(path);
if (res == SZ_OK)
- return 0;
+ return (int)exitCode;
{
if (res == SZ_ERROR_UNSUPPORTED)
@@ -610,6 +617,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if (!errorMessage)
errorMessage = "ERROR";
}
+
if (errorMessage)
PrintErrorMessage(errorMessage);
}
diff --git a/C/Util/SfxSetup/SfxSetup.dsp b/C/Util/SfxSetup/SfxSetup.dsp
index 5ce7195b..50e012f0 100644
--- a/C/Util/SfxSetup/SfxSetup.dsp
+++ b/C/Util/SfxSetup/SfxSetup.dsp
@@ -167,6 +167,10 @@ SOURCE=..\..\Bra86.c
# End Source File
# Begin Source File
+SOURCE=..\..\BraIA64.c
+# End Source File
+# Begin Source File
+
SOURCE=..\..\CpuArch.c
# End Source File
# Begin Source File
@@ -175,6 +179,14 @@ SOURCE=..\..\CpuArch.h
# End Source File
# Begin Source File
+SOURCE=..\..\Delta.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Delta.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Lzma2Dec.c
# End Source File
# Begin Source File
diff --git a/C/Util/SfxSetup/makefile b/C/Util/SfxSetup/makefile
index 5b519807..b2944793 100644
--- a/C/Util/SfxSetup/makefile
+++ b/C/Util/SfxSetup/makefile
@@ -13,7 +13,9 @@ C_OBJS = \
$O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
+ $O\BraIA64.obj \
$O\CpuArch.obj \
+ $O\Delta.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
diff --git a/C/Util/SfxSetup/makefile_con b/C/Util/SfxSetup/makefile_con
index 492191f5..7a96fd36 100644
--- a/C/Util/SfxSetup/makefile_con
+++ b/C/Util/SfxSetup/makefile_con
@@ -14,7 +14,9 @@ C_OBJS = \
$O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
+ $O\BraIA64.obj \
$O\CpuArch.obj \
+ $O\Delta.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
diff --git a/C/Xz.c b/C/Xz.c
index fbc732a8..1ef68782 100644
--- a/C/Xz.c
+++ b/C/Xz.c
@@ -1,5 +1,5 @@
/* Xz.c - Xz
-2009-04-15 : Igor Pavlov : Public domain */
+2015-05-01 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -8,8 +8,8 @@
#include "Xz.h"
#include "XzCrc64.h"
-Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };
-Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };
+const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };
+const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)
{
@@ -40,11 +40,11 @@ void Xz_Free(CXzStream *p, ISzAlloc *alloc)
unsigned XzFlags_GetCheckSize(CXzStreamFlags f)
{
- int t = XzFlags_GetCheckType(f);
+ unsigned t = XzFlags_GetCheckType(f);
return (t == 0) ? 0 : (4 << ((t - 1) / 3));
}
-void XzCheck_Init(CXzCheck *p, int mode)
+void XzCheck_Init(CXzCheck *p, unsigned mode)
{
p->mode = mode;
switch (mode)
diff --git a/C/Xz.h b/C/Xz.h
index 7e6fc564..be3a1c36 100644
--- a/C/Xz.h
+++ b/C/Xz.h
@@ -1,5 +1,5 @@
/* Xz.h - Xz interface
-2014-12-30 : Igor Pavlov : Public domain */
+2015-05-01 : Igor Pavlov : Public domain */
#ifndef __XZ_H
#define __XZ_H
@@ -59,8 +59,8 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt
#define XZ_SIG_SIZE 6
#define XZ_FOOTER_SIG_SIZE 2
-extern Byte XZ_SIG[XZ_SIG_SIZE];
-extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
+extern const Byte XZ_SIG[XZ_SIG_SIZE];
+extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
#define XZ_STREAM_FLAGS_SIZE 2
#define XZ_STREAM_CRC_SIZE 4
@@ -76,13 +76,13 @@ extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
typedef struct
{
- int mode;
+ unsigned mode;
UInt32 crc;
UInt64 crc64;
CSha256 sha;
} CXzCheck;
-void XzCheck_Init(CXzCheck *p, int mode);
+void XzCheck_Init(CXzCheck *p, unsigned mode);
void XzCheck_Update(CXzCheck *p, const void *data, size_t size);
int XzCheck_Final(CXzCheck *p, Byte *digest);
@@ -163,7 +163,7 @@ typedef struct
{
ISzAlloc *alloc;
Byte *buf;
- int numCoders;
+ unsigned numCoders;
int finished[MIXCODER_NUM_FILTERS_MAX - 1];
size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
@@ -174,7 +174,7 @@ typedef struct
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
void MixCoder_Free(CMixCoder *p);
void MixCoder_Init(CMixCoder *p);
-SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId);
+SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId);
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcWasFinished,
ECoderFinishMode finishMode, ECoderStatus *status);
diff --git a/C/XzCrc64.c b/C/XzCrc64.c
index aa812548..e2da63b6 100644
--- a/C/XzCrc64.c
+++ b/C/XzCrc64.c
@@ -1,5 +1,5 @@
/* XzCrc64.c -- CRC64 calculation
-2011-06-28 : Igor Pavlov : Public domain */
+2015-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -13,14 +13,15 @@
#else
#define CRC_NUM_TABLES 5
#define CRC_UINT64_SWAP(v) \
- ((v >> 56) | \
- ((v >> 40) & ((UInt64)0xFF << 8)) | \
- ((v >> 24) & ((UInt64)0xFF << 16)) | \
- ((v >> 8) & ((UInt64)0xFF << 24)) | \
- ((v << 8) & ((UInt64)0xFF << 32)) | \
- ((v << 24) & ((UInt64)0xFF << 40)) | \
- ((v << 40) & ((UInt64)0xFF << 48)) | \
- (v << 56))
+ ((v >> 56) \
+ | ((v >> 40) & ((UInt64)0xFF << 8)) \
+ | ((v >> 24) & ((UInt64)0xFF << 16)) \
+ | ((v >> 8) & ((UInt64)0xFF << 24)) \
+ | ((v << 8) & ((UInt64)0xFF << 32)) \
+ | ((v << 24) & ((UInt64)0xFF << 40)) \
+ | ((v << 40) & ((UInt64)0xFF << 48)) \
+ | ((v << 56)))
+
UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table);
#endif
@@ -64,11 +65,6 @@ void MY_FAST_CALL Crc64GenerateTable()
g_Crc64Update = XzCrc64UpdateT4;
-
-
-
-
-
#else
{
#ifndef MY_CPU_BE
diff --git a/C/XzCrc64Opt.c b/C/XzCrc64Opt.c
index dccae1c1..c4fde65a 100644
--- a/C/XzCrc64Opt.c
+++ b/C/XzCrc64Opt.c
@@ -1,14 +1,14 @@
/* XzCrc64Opt.c -- CRC64 calculation
-2011-06-28 : Igor Pavlov : Public domain */
+2015-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "CpuArch.h"
-#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
-
#ifndef MY_CPU_BE
+#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
+
UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table)
{
const Byte *p = (const Byte *)data;
@@ -17,11 +17,11 @@ UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, con
for (; size >= 4; size -= 4, p += 4)
{
UInt32 d = (UInt32)v ^ *(const UInt32 *)p;
- v = (v >> 32) ^
- table[0x300 + ((d ) & 0xFF)] ^
- table[0x200 + ((d >> 8) & 0xFF)] ^
- table[0x100 + ((d >> 16) & 0xFF)] ^
- table[0x000 + ((d >> 24))];
+ v = (v >> 32)
+ ^ table[0x300 + ((d ) & 0xFF)]
+ ^ table[0x200 + ((d >> 8) & 0xFF)]
+ ^ table[0x100 + ((d >> 16) & 0xFF)]
+ ^ table[0x000 + ((d >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
@@ -34,36 +34,36 @@ UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, con
#ifndef MY_CPU_LE
#define CRC_UINT64_SWAP(v) \
- ((v >> 56) | \
- ((v >> 40) & ((UInt64)0xFF << 8)) | \
- ((v >> 24) & ((UInt64)0xFF << 16)) | \
- ((v >> 8) & ((UInt64)0xFF << 24)) | \
- ((v << 8) & ((UInt64)0xFF << 32)) | \
- ((v << 24) & ((UInt64)0xFF << 40)) | \
- ((v << 40) & ((UInt64)0xFF << 48)) | \
- (v << 56))
+ ((v >> 56) \
+ | ((v >> 40) & ((UInt64)0xFF << 8)) \
+ | ((v >> 24) & ((UInt64)0xFF << 16)) \
+ | ((v >> 8) & ((UInt64)0xFF << 24)) \
+ | ((v << 8) & ((UInt64)0xFF << 32)) \
+ | ((v << 24) & ((UInt64)0xFF << 40)) \
+ | ((v << 40) & ((UInt64)0xFF << 48)) \
+ | ((v << 56)))
+
+#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8))
UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table)
{
const Byte *p = (const Byte *)data;
- for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
- v = CRC_UPDATE_BYTE_2(v, *p);
- v = CRC_UINT64_SWAP(v);
table += 0x100;
+ v = CRC_UINT64_SWAP(v);
+ for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
+ v = CRC_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 4; size -= 4, p += 4)
{
UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p;
- v = (v << 32) ^
- table[0x000 + ((d ) & 0xFF)] ^
- table[0x100 + ((d >> 8) & 0xFF)] ^
- table[0x200 + ((d >> 16) & 0xFF)] ^
- table[0x300 + ((d >> 24))];
+ v = (v << 32)
+ ^ table[0x000 + ((d ) & 0xFF)]
+ ^ table[0x100 + ((d >> 8) & 0xFF)]
+ ^ table[0x200 + ((d >> 16) & 0xFF)]
+ ^ table[0x300 + ((d >> 24))];
}
- table -= 0x100;
- v = CRC_UINT64_SWAP(v);
for (; size > 0; size--, p++)
- v = CRC_UPDATE_BYTE_2(v, *p);
- return v;
+ v = CRC_UPDATE_BYTE_2_BE(v, *p);
+ return CRC_UINT64_SWAP(v);
}
#endif
diff --git a/C/XzDec.c b/C/XzDec.c
index a5698e86..6e404a16 100644
--- a/C/XzDec.c
+++ b/C/XzDec.c
@@ -1,5 +1,5 @@
/* XzDec.c -- Xz Decode
-2014-12-30 : Igor Pavlov : Public domain */
+2015-05-01 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -32,9 +32,9 @@
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
{
- int i, limit;
+ unsigned i, limit;
*value = 0;
- limit = (maxSize > 9) ? 9 : (int)maxSize;
+ limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
for (i = 0; i < limit;)
{
@@ -66,12 +66,12 @@ typedef struct
Byte buf[BRA_BUF_SIZE];
} CBraState;
-void BraState_Free(void *pp, ISzAlloc *alloc)
+static void BraState_Free(void *pp, ISzAlloc *alloc)
{
alloc->Free(alloc, pp);
}
-SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
+static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{
CBraState *p = ((CBraState *)pp);
alloc = alloc;
@@ -87,7 +87,7 @@ SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *a
if (propSize == 4)
{
UInt32 v = GetUi32(props);
- switch(p->methodId)
+ switch (p->methodId)
{
case XZ_ID_PPC:
case XZ_ID_ARM:
@@ -112,7 +112,7 @@ SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *a
return SZ_OK;
}
-void BraState_Init(void *pp)
+static void BraState_Init(void *pp)
{
CBraState *p = ((CBraState *)pp);
p->bufPos = p->bufConv = p->bufTotal = 0;
@@ -163,7 +163,7 @@ static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src,
}
if (p->bufTotal == 0)
break;
- switch(p->methodId)
+ switch (p->methodId)
{
case XZ_ID_Delta:
if (p->encodeMode)
@@ -235,7 +235,7 @@ static void SbState_Free(void *pp, ISzAlloc *alloc)
static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
{
- pp = pp;
+ UNUSED_VAR(pp);
props = props;
alloc = alloc;
return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
@@ -330,9 +330,9 @@ static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
{
- int i;
+ unsigned i;
p->alloc = alloc;
- p->buf = 0;
+ p->buf = NULL;
p->numCoders = 0;
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
p->coders[i].p = NULL;
@@ -340,7 +340,7 @@ void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
void MixCoder_Free(CMixCoder *p)
{
- int i;
+ unsigned i;
for (i = 0; i < p->numCoders; i++)
{
IStateCoder *sc = &p->coders[i];
@@ -351,14 +351,14 @@ void MixCoder_Free(CMixCoder *p)
if (p->buf)
{
p->alloc->Free(p->alloc, p->buf);
- p->buf = 0; /* 9.31: the BUG was fixed */
+ p->buf = NULL; /* 9.31: the BUG was fixed */
}
}
void MixCoder_Init(CMixCoder *p)
{
- int i;
- for (i = 0; i < p->numCoders - 1; i++)
+ unsigned i;
+ for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
{
p->size[i] = 0;
p->pos[i] = 0;
@@ -371,11 +371,11 @@ void MixCoder_Init(CMixCoder *p)
}
}
-SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)
+SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId)
{
IStateCoder *sc = &p->coders[coderIndex];
p->ids[coderIndex] = methodId;
- switch(methodId)
+ switch (methodId)
{
case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);
#ifdef USE_SUBBLOCK
@@ -398,10 +398,10 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
*srcLen = 0;
*status = CODER_STATUS_NOT_FINISHED;
- if (p->buf == 0)
+ if (!p->buf)
{
p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
- if (p->buf == 0)
+ if (!p->buf)
return SZ_ERROR_MEM;
}
@@ -411,7 +411,7 @@ SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
for (;;)
{
Bool processed = False;
- int i;
+ unsigned i;
/*
if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
break;
@@ -520,8 +520,8 @@ static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *b
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
{
unsigned pos;
- int numFilters, i;
- UInt32 headerSize = (UInt32)header[0] << 2;
+ unsigned numFilters, i;
+ unsigned headerSize = (unsigned)header[0] << 2;
if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
return SZ_ERROR_ARCHIVE;
@@ -557,7 +557,7 @@ SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
#ifdef XZ_DUMP
printf("\nf[%d] = %2X: ", i, filter->id);
{
- int i;
+ unsigned i;
for (i = 0; i < size; i++)
printf(" %2X", filter->props[i]);
}
@@ -572,9 +572,10 @@ SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
{
- int i;
+ unsigned i;
Bool needReInit = True;
- int numFilters = XzBlock_GetNumFilters(block);
+ unsigned numFilters = XzBlock_GetNumFilters(block);
+
if (numFilters == p->numCoders)
{
for (i = 0; i < numFilters; i++)
@@ -582,6 +583,7 @@ SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
break;
needReInit = (i != numFilters);
}
+
if (needReInit)
{
MixCoder_Free(p);
@@ -592,12 +594,14 @@ SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
RINOK(MixCoder_SetFromMethod(p, i, f->id));
}
}
+
for (i = 0; i < numFilters; i++)
{
const CXzFilter *f = &block->filters[numFilters - 1 - i];
IStateCoder *sc = &p->coders[i];
RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
}
+
MixCoder_Init(p);
return SZ_OK;
}
diff --git a/C/XzEnc.c b/C/XzEnc.c
index ed6e1ba6..4dd3f9e4 100644
--- a/C/XzEnc.c
+++ b/C/XzEnc.c
@@ -1,5 +1,5 @@
/* XzEnc.c -- Xz Encode
-2014-12-30 : Igor Pavlov : Public domain */
+2015-05-01 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -18,14 +18,6 @@
#include "XzEnc.h"
-static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); }
-static void SzBigFree(void *p, void *address) { p = p; BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
#define XzBlock_ClearFlags(p) (p)->flags = 0;
#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);
#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE;
@@ -59,12 +51,13 @@ SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
unsigned pos = 1;
- int numFilters, i;
+ unsigned numFilters, i;
header[pos++] = p->flags;
if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);
if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);
numFilters = XzBlock_GetNumFilters(p);
+
for (i = 0; i < numFilters; i++)
{
const CXzFilter *f = &p->filters[i];
@@ -73,8 +66,10 @@ SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
memcpy(header + pos, f->props, f->propsSize);
pos += f->propsSize;
}
- while((pos & 3) != 0)
+
+ while ((pos & 3) != 0)
header[pos++] = 0;
+
header[0] = (Byte)(pos >> 2);
SetUi32(header + pos, CrcCalc(header, pos));
return WriteBytes(s, header, pos + 4);
@@ -163,13 +158,13 @@ typedef struct
CXzCheck check;
} CSeqCheckInStream;
-void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode)
+static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned mode)
{
p->processed = 0;
XzCheck_Init(&p->check, mode);
}
-void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)
+static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)
{
XzCheck_Final(&p->check, digest);
}
@@ -408,7 +403,7 @@ static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf,
CSeqCheckInStream checkInStream;
CSeqSizeOutStream seqSizeOutStream;
CXzBlock block;
- int filterIndex = 0;
+ unsigned filterIndex = 0;
CXzFilter *filter = NULL;
const CXzFilterProps *fp = props->filterProps;
diff --git a/C/XzIn.c b/C/XzIn.c
index 05b4a5f0..d60f4c8d 100644
--- a/C/XzIn.c
+++ b/C/XzIn.c
@@ -1,5 +1,5 @@
/* XzIn.c - Xz input
-2014-12-30 : Igor Pavlov : Public domain */
+2015-04-21 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -134,55 +134,58 @@ static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize,
return res;
}
-static SRes SeekFromCur(ILookInStream *inStream, Int64 *res)
+static SRes LookInStream_SeekRead_ForArc(ILookInStream *stream, UInt64 offset, void *buf, size_t size)
{
- return inStream->Seek(inStream, res, SZ_SEEK_CUR);
+ RINOK(LookInStream_SeekTo(stream, offset));
+ return LookInStream_Read(stream, buf, size);
+ /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */
}
static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc)
{
UInt64 indexSize;
Byte buf[XZ_STREAM_FOOTER_SIZE];
+ UInt64 pos = *startOffset;
- if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE)
+ if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE)
return SZ_ERROR_NO_ARCHIVE;
- *startOffset = -XZ_STREAM_FOOTER_SIZE;
- RINOK(SeekFromCur(stream, startOffset));
- RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));
+ pos -= XZ_STREAM_FOOTER_SIZE;
+ RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
{
UInt32 total = 0;
- *startOffset += XZ_STREAM_FOOTER_SIZE;
+ pos += XZ_STREAM_FOOTER_SIZE;
+
for (;;)
{
size_t i;
#define TEMP_BUF_SIZE (1 << 10)
- Byte tempBuf[TEMP_BUF_SIZE];
- if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))
- return SZ_ERROR_NO_ARCHIVE;
- i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;
+ Byte temp[TEMP_BUF_SIZE];
+
+ i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos;
+ pos -= i;
+ RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i));
total += (UInt32)i;
- *startOffset = -(Int64)i;
- RINOK(SeekFromCur(stream, startOffset));
- RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE));
for (; i != 0; i--)
- if (tempBuf[i - 1] != 0)
+ if (temp[i - 1] != 0)
break;
if (i != 0)
{
if ((i & 3) != 0)
return SZ_ERROR_NO_ARCHIVE;
- *startOffset += i;
+ pos += i;
break;
}
+ if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16))
+ return SZ_ERROR_NO_ARCHIVE;
}
- if (*startOffset < XZ_STREAM_FOOTER_SIZE)
+
+ if (pos < XZ_STREAM_FOOTER_SIZE)
return SZ_ERROR_NO_ARCHIVE;
- *startOffset -= XZ_STREAM_FOOTER_SIZE;
- RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));
- RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));
+ pos -= XZ_STREAM_FOOTER_SIZE;
+ RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE));
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
return SZ_ERROR_NO_ARCHIVE;
}
@@ -197,20 +200,22 @@ static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOff
indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2;
- *startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE);
- RINOK(SeekFromCur(stream, startOffset));
+ if (pos < indexSize)
+ return SZ_ERROR_ARCHIVE;
+ pos -= indexSize;
+ RINOK(LookInStream_SeekTo(stream, pos));
RINOK(Xz_ReadIndex(p, stream, indexSize, alloc));
{
UInt64 totalSize = Xz_GetPackSize(p);
- UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize;
- if (totalSize == XZ_SIZE_OVERFLOW ||
- sum >= ((UInt64)1 << 63) ||
- totalSize >= ((UInt64)1 << 63))
+ if (totalSize == XZ_SIZE_OVERFLOW
+ || totalSize >= ((UInt64)1 << 63)
+ || pos < totalSize + XZ_STREAM_HEADER_SIZE)
return SZ_ERROR_ARCHIVE;
- *startOffset = -(Int64)sum;
- RINOK(SeekFromCur(stream, startOffset));
+ pos -= (totalSize + XZ_STREAM_HEADER_SIZE);
+ RINOK(LookInStream_SeekTo(stream, pos));
+ *startOffset = pos;
}
{
CXzStreamFlags headerFlags;
@@ -299,7 +304,7 @@ SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompr
p->streams[p->num++] = st;
if (*startOffset == 0)
break;
- RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));
+ RINOK(LookInStream_SeekTo(stream, *startOffset));
if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)
return SZ_ERROR_PROGRESS;
}
diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp
index 53913f77..7fd1ccdc 100644
--- a/CPP/7zip/Archive/7z/7z.dsp
+++ b/CPP/7zip/Archive/7z/7z.dsp
@@ -350,14 +350,6 @@ SOURCE=..\Common\CoderMixer2.h
# End Source File
# Begin Source File
-SOURCE=..\Common\CoderMixer2MT.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\Common\CoderMixer2MT.h
-# End Source File
-# Begin Source File
-
SOURCE=..\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index 5cde97c3..8105ff04 100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -9,37 +9,62 @@
namespace NArchive {
namespace N7z {
-struct CMethodFull: public CProps
+struct CMethodFull: public CMethodProps
{
CMethodId Id;
- UInt32 NumInStreams;
- UInt32 NumOutStreams;
+ UInt32 NumStreams;
- bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+ bool IsSimpleCoder() const { return NumStreams == 1; }
};
-struct CBind
+struct CBond2
{
- UInt32 InCoder;
- UInt32 InStream;
UInt32 OutCoder;
UInt32 OutStream;
+ UInt32 InCoder;
};
struct CCompressionMethodMode
{
+ /*
+ if (Bonds.Empty()), then default bonds must be created
+ if (Filter_was_Inserted)
+ {
+ Methods[0] is filter method
+ Bonds don't contain bonds for filter (these bonds must be created)
+ }
+ */
+
CObjectVector<CMethodFull> Methods;
- CRecordVector<CBind> Binds;
+ CRecordVector<CBond2> Bonds;
+
+ bool IsThereBond_to_Coder(unsigned coderIndex) const
+ {
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].InCoder == coderIndex)
+ return true;
+ return false;
+ }
+
+ bool DefaultMethod_was_Inserted;
+ bool Filter_was_Inserted;
+
#ifndef _7ZIP_ST
UInt32 NumThreads;
+ bool MultiThreadMixer;
#endif
+
bool PasswordIsDefined;
UString Password;
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
- CCompressionMethodMode(): PasswordIsDefined(false)
+ CCompressionMethodMode():
+ DefaultMethod_was_Inserted(false),
+ Filter_was_Inserted(false),
+ PasswordIsDefined(false)
#ifndef _7ZIP_ST
, NumThreads(1)
+ , MultiThreadMixer(true)
#endif
{}
};
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index 7f0e45d1..d1a810cb 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -3,7 +3,6 @@
#include "StdAfx.h"
#include "../../Common/LimitedStreams.h"
-#include "../../Common/LockedStream.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
@@ -12,50 +11,70 @@
namespace NArchive {
namespace N7z {
-static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
- CBindInfoEx &bindInfo)
+class CDecProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
{
- bindInfo.Clear();
- bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());
+ CMyComPtr<ICompressProgressInfo> _progress;
+public:
+ CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)
+{
+ return _progress->SetRatioInfo(NULL, outSize);
+}
+
+static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
+{
+ bi.Clear();
+
+ bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
unsigned i;
- for (i = 0; i < folder.BindPairs.Size(); i++)
+ for (i = 0; i < folder.Bonds.Size(); i++)
{
- NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];
- bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
- bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
+ NCoderMixer2::CBond &bond = bi.Bonds[i];
+ const N7z::CBond &folderBond = folder.Bonds[i];
+ bond.PackIndex = folderBond.PackIndex;
+ bond.UnpackIndex = folderBond.UnpackIndex;
}
- bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());
- bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
-
- UInt32 outStreamIndex = 0;
+ bi.Coders.ClearAndSetSize(folder.Coders.Size());
+ bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
for (i = 0; i < folder.Coders.Size(); i++)
{
- NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
const CCoderInfo &coderInfo = folder.Coders[i];
- coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
- coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
- bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;
- for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
- if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
- bindInfo.OutStreams.Add(outStreamIndex);
+ bi.Coders[i].NumStreams = coderInfo.NumStreams;
+ bi.CoderMethodIDs[i] = coderInfo.MethodID;
}
- bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());
+
+ /*
+ if (!bi.SetUnpackCoder())
+ throw 1112;
+ */
+ bi.UnpackCoder = folder.UnpackCoder;
+ bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
for (i = 0; i < folder.PackStreams.Size(); i++)
- bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];
+ bi.PackStreams[i] = folder.PackStreams[i];
}
-static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
- const NCoderMixer::CCoderStreamsInfo &a2)
+static inline bool AreCodersEqual(
+ const NCoderMixer2::CCoderStreamsInfo &a1,
+ const NCoderMixer2::CCoderStreamsInfo &a2)
{
- return (a1.NumInStreams == a2.NumInStreams) &&
- (a1.NumOutStreams == a2.NumOutStreams);
+ return (a1.NumStreams == a2.NumStreams);
}
-static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
+static inline bool AreBondsEqual(
+ const NCoderMixer2::CBond &a1,
+ const NCoderMixer2::CBond &a2)
{
- return (a1.InIndex == a2.InIndex) &&
- (a1.OutIndex == a2.OutIndex);
+ return
+ (a1.PackIndex == a2.PackIndex) &&
+ (a1.UnpackIndex == a2.UnpackIndex);
}
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
@@ -66,186 +85,284 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
for (i = 0; i < a1.Coders.Size(); i++)
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
return false;
- if (a1.BindPairs.Size() != a2.BindPairs.Size())
+
+ if (a1.Bonds.Size() != a2.Bonds.Size())
return false;
- for (i = 0; i < a1.BindPairs.Size(); i++)
- if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
+ for (i = 0; i < a1.Bonds.Size(); i++)
+ if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
return false;
+
for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
return false;
- if (a1.InStreams.Size() != a2.InStreams.Size())
+
+ if (a1.PackStreams.Size() != a2.PackStreams.Size())
return false;
- if (a1.OutStreams.Size() != a2.OutStreams.Size())
+ for (i = 0; i < a1.PackStreams.Size(); i++)
+ if (a1.PackStreams[i] != a2.PackStreams[i])
+ return false;
+
+ /*
+ if (a1.UnpackCoder != a2.UnpackCoder)
return false;
+ */
return true;
}
-CDecoder::CDecoder(bool multiThread)
+CDecoder::CDecoder(bool useMixerMT):
+ _bindInfoPrev_Defined(false),
+ _useMixerMT(useMixerMT)
+{}
+
+
+struct CLockedInStream:
+ public IUnknown,
+ public CMyUnknownImp
{
- #ifndef _ST_MODE
- multiThread = true;
+ CMyComPtr<IInStream> Stream;
+ UInt64 Pos;
+
+ MY_UNKNOWN_IMP
+
+ #ifdef USE_MIXER_MT
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
- _multiThread = multiThread;
- _bindInfoExPrevIsDefined = false;
+};
+
+
+#ifdef USE_MIXER_MT
+
+class CLockedSequentialInStreamMT:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CLockedInStream *_glob;
+ UInt64 _pos;
+ CMyComPtr<IUnknown> _globRef;
+public:
+ void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+ {
+ _globRef = lockedInStream;
+ _glob = lockedInStream;
+ _pos = startPos;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
+
+ if (_pos != _glob->Pos)
+ {
+ RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+ _glob->Pos = _pos;
+ }
+
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ _glob->Pos = _pos;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
+}
+
+#endif
+
+
+#ifdef USE_MIXER_ST
+
+class CLockedSequentialInStreamST:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CLockedInStream *_glob;
+ UInt64 _pos;
+ CMyComPtr<IUnknown> _globRef;
+public:
+ void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+ {
+ _globRef = lockedInStream;
+ _glob = lockedInStream;
+ _pos = startPos;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (_pos != _glob->Pos)
+ {
+ RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+ _glob->Pos = _pos;
+ }
+
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ _glob->Pos = _pos;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
}
+#endif
+
+
+
HRESULT CDecoder::Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
- const CFolders &folders, int folderIndex,
- ISequentialOutStream *outStream,
- ICompressProgressInfo *compressProgress
+ const CFolders &folders, unsigned folderIndex,
+ const UInt64 *unpackSize
+
+ , ISequentialOutStream *outStream
+ , ICompressProgressInfo *compressProgress
+ , ISequentialInStream **
+
+ #ifdef USE_MIXER_ST
+ inStreamMainRes
+ #endif
+
_7Z_DECODER_CRYPRO_VARS_DECL
+
#if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads
#endif
)
{
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
- CFolder folderInfo;
- folders.ParseFolderInfo(folderIndex, folderInfo);
+ CFolderEx folderInfo;
+ folders.ParseFolderEx(folderIndex, folderInfo);
- if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))
+ if (!folderInfo.IsDecodingSupported())
+ return E_NOTIMPL;
+
+ CBindInfoEx bindInfo;
+ Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
+ if (!bindInfo.CalcMapsAndCheck())
return E_NOTIMPL;
+ UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
+ bool fullUnpack = true;
+ if (unpackSize)
+ {
+ if (*unpackSize > folderUnpackSize)
+ return E_FAIL;
+ fullUnpack = (*unpackSize == folderUnpackSize);
+ }
+
/*
We don't need to init isEncrypted and passwordIsDefined
We must upgrade them only
+
#ifndef _NO_CRYPTO
isEncrypted = false;
passwordIsDefined = false;
#endif
*/
-
- CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
- CLockedInStream lockedInStream;
- lockedInStream.Init(inStream);
-
- for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
+ if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
{
- CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;
- CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
- lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
- CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
- CMyComPtr<ISequentialInStream> inStream = streamSpec;
- streamSpec->SetStream(lockedStreamImp);
- streamSpec->Init(packPositions[j + 1] - packPositions[j]);
- inStreams.Add(inStream);
- }
-
- unsigned numCoders = folderInfo.Coders.Size();
-
- CBindInfoEx bindInfo;
- ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
- bool createNewCoders;
- if (!_bindInfoExPrevIsDefined)
- createNewCoders = true;
- else
- createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
- if (createNewCoders)
- {
- unsigned i;
- _decoders.Clear();
- // _decoders2.Clear();
-
- _mixerCoder.Release();
+ _mixerRef.Release();
- if (_multiThread)
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT)
+ #endif
{
- _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
- _mixerCoder = _mixerCoderMTSpec;
- _mixerCoderCommon = _mixerCoderMTSpec;
+ _mixerMT = new NCoderMixer2::CMixerMT(false);
+ _mixerRef = _mixerMT;
+ _mixer = _mixerMT;
}
+ #ifdef USE_MIXER_ST
else
+ #endif
+ #endif
{
- #ifdef _ST_MODE
- _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
- _mixerCoder = _mixerCoderSTSpec;
- _mixerCoderCommon = _mixerCoderSTSpec;
+ #ifdef USE_MIXER_ST
+ _mixerST = new NCoderMixer2::CMixerST(false);
+ _mixerRef = _mixerST;
+ _mixer = _mixerST;
#endif
}
- RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
- for (i = 0; i < numCoders; i++)
+ RINOK(_mixer->SetBindInfo(bindInfo));
+
+ FOR_VECTOR(i, folderInfo.Coders)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
-
- CMyComPtr<ICompressCoder> decoder;
- CMyComPtr<ICompressCoder2> decoder2;
+ CCreatedCoder cod;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- coderInfo.MethodID, decoder, decoder2, false));
- CMyComPtr<IUnknown> decoderUnknown;
+ coderInfo.MethodID, false, cod));
+
if (coderInfo.IsSimpleCoder())
{
- if (decoder == 0)
+ if (!cod.Coder)
return E_NOTIMPL;
-
- decoderUnknown = (IUnknown *)decoder;
-
- if (_multiThread)
- _mixerCoderMTSpec->AddCoder(decoder);
- #ifdef _ST_MODE
- else
- _mixerCoderSTSpec->AddCoder(decoder, false);
- #endif
+ // CMethodId m = coderInfo.MethodID;
+ // isFilter = (IsFilterMethod(m) || m == k_AES);
}
else
{
- if (decoder2 == 0)
+ if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
return E_NOTIMPL;
- decoderUnknown = (IUnknown *)decoder2;
- if (_multiThread)
- _mixerCoderMTSpec->AddCoder2(decoder2);
- #ifdef _ST_MODE
- else
- _mixerCoderSTSpec->AddCoder2(decoder2, false);
- #endif
}
- _decoders.Add(decoderUnknown);
+ _mixer->AddCoder(cod);
+
+ // now there is no codec that uses another external codec
+ /*
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
+ // we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
}
#endif
+ */
}
- _bindInfoExPrev = bindInfo;
- _bindInfoExPrevIsDefined = true;
+
+ _bindInfoPrev = bindInfo;
+ _bindInfoPrev_Defined = true;
}
- unsigned i;
- _mixerCoderCommon->ReInit();
+
+ _mixer->ReInit();
UInt32 packStreamIndex = 0;
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
- UInt32 unpackStreamIndex = unpackStreamIndexStart;
- UInt32 coderIndex = 0;
- // UInt32 coder2Index = 0;
-
- for (i = 0; i < numCoders; i++)
+
+ unsigned i;
+
+ for (i = 0; i < folderInfo.Coders.Size(); i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
- CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
-
+ IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
+
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
- decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+ decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
if (setDecoderProperties)
{
const CByteBuffer &props = coderInfo.Props;
size_t size = props.Size();
if (size > 0xFFFFFFFF)
return E_NOTIMPL;
- // if (size > 0)
- {
- RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
- }
+ HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
+ if (res == E_INVALIDARG)
+ res = E_NOTIMPL;
+ RINOK(res);
}
}
@@ -253,7 +370,7 @@ HRESULT CDecoder::Decode(
if (mtMode)
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
- decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
@@ -264,7 +381,7 @@ HRESULT CDecoder::Decode(
#ifndef _NO_CRYPTO
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
- decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+ decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
if (cryptoSetPassword)
{
isEncrypted = true;
@@ -273,9 +390,13 @@ HRESULT CDecoder::Decode(
CMyComBSTR passwordBSTR;
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
passwordIsDefined = true;
+ password.Empty();
size_t len = 0;
if (passwordBSTR)
- len = MyStringLen((BSTR)passwordBSTR);
+ {
+ password = passwordBSTR;
+ len = password.Len();
+ }
CByteBuffer buffer(len * 2);
for (size_t i = 0; i < len; i++)
{
@@ -288,56 +409,129 @@ HRESULT CDecoder::Decode(
}
#endif
- coderIndex++;
+ {
+ CMyComPtr<ICompressSetFinishMode> setFinishMode;
+ decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
+ if (setFinishMode)
+ {
+ RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
+ }
+ }
- UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
- UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
- CObjArray<UInt64> packSizes(numInStreams);
- CObjArray<const UInt64 *> packSizesPointers(numInStreams);
- CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
- UInt32 j;
-
- for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
- unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];
+ UInt32 numStreams = (UInt32)coderInfo.NumStreams;
- for (j = 0; j < numInStreams; j++, packStreamIndex++)
+ CObjArray<UInt64> packSizes(numStreams);
+ CObjArray<const UInt64 *> packSizesPointers(numStreams);
+
+ for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
{
- int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
- if (bindPairIndex >= 0)
- packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];
+ int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
+
+ if (bond >= 0)
+ packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
else
{
- int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
+ int index = folderInfo.Find_in_PackStreams(packStreamIndex);
if (index < 0)
- return S_FALSE; // check it
- packSizes[j] = packPositions[index + 1] - packPositions[index];
+ return E_NOTIMPL;
+ packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
packSizesPointers[j] = &packSizes[j];
}
}
+
+ const UInt64 *unpackSizesPointer =
+ (unpackSize && i == bindInfo.UnpackCoder) ?
+ unpackSize :
+ &folders.CoderUnpackSizes[unpackStreamIndexStart + i];
- _mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);
+ _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
}
- UInt32 mainCoder, temp;
- bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
- if (_multiThread)
- _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
- /*
- else
- _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
- */
+ if (outStream)
+ {
+ _mixer->SelectMainCoder(!fullUnpack);
+ }
+
+ CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
+
+ CLockedInStream *lockedInStreamSpec = new CLockedInStream;
+ CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
+
+ bool needMtLock = false;
+
+ if (folderInfo.PackStreams.Size() > 1)
+ {
+ // lockedInStream.Pos = (UInt64)(Int64)-1;
+ // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
+ RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
+ lockedInStreamSpec->Stream = inStream;
+
+ #ifdef USE_MIXER_ST
+ if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
+ #endif
+ needMtLock = true;
+ }
+
+ for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
+ {
+ CMyComPtr<ISequentialInStream> packStream;
+ UInt64 packPos = startPos + packPositions[j];
+
+ if (folderInfo.PackStreams.Size() == 1)
+ {
+ RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
+ packStream = inStream;
+ }
+ else
+ {
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT || needMtLock)
+ #endif
+ {
+ CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
+ packStream = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
+ }
+ #ifdef USE_MIXER_ST
+ else
+ #endif
+ #endif
+ {
+ #ifdef USE_MIXER_ST
+ CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
+ packStream = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
+ #endif
+ }
+ }
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ inStreams.AddNew() = streamSpec;
+ streamSpec->SetStream(packStream);
+ streamSpec->Init(packPositions[j + 1] - packPositions[j]);
+ }
- if (numCoders == 0)
- return 0;
unsigned num = inStreams.Size();
CObjArray<ISequentialInStream *> inStreamPointers(num);
for (i = 0; i < num; i++)
inStreamPointers[i] = inStreams[i];
- ISequentialOutStream *outStreamPointer = outStream;
- return _mixerCoder->Code(
- inStreamPointers, NULL, num,
- &outStreamPointer, NULL, 1,
- compressProgress);
+
+ if (outStream)
+ {
+ CMyComPtr<ICompressProgressInfo> progress2;
+ if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
+ progress2 = new CDecProgress(compressProgress);
+
+ ISequentialOutStream *outStreamPointer = outStream;
+ return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
+ }
+
+ #ifdef USE_MIXER_ST
+ return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
+ #else
+ return E_FAIL;
+ #endif
}
}}
diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
index 1361772c..5b729f6c 100644
--- a/CPP/7zip/Archive/7z/7zDecode.h
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -3,25 +3,17 @@
#ifndef __7Z_DECODE_H
#define __7Z_DECODE_H
-#include "../../IStream.h"
-#include "../../IPassword.h"
-
#include "../Common/CoderMixer2.h"
-#include "../Common/CoderMixer2MT.h"
-#ifdef _ST_MODE
-#include "../Common/CoderMixer2ST.h"
-#endif
-
-#include "../../Common/CreateCoder.h"
#include "7zIn.h"
namespace NArchive {
namespace N7z {
-struct CBindInfoEx: public NCoderMixer::CBindInfo
+struct CBindInfoEx: public NCoderMixer2::CBindInfo
{
CRecordVector<CMethodId> CoderMethodIDs;
+
void Clear()
{
CBindInfo::Clear();
@@ -31,29 +23,40 @@ struct CBindInfoEx: public NCoderMixer::CBindInfo
class CDecoder
{
- bool _bindInfoExPrevIsDefined;
- CBindInfoEx _bindInfoExPrev;
+ bool _bindInfoPrev_Defined;
+ CBindInfoEx _bindInfoPrev;
+
+ bool _useMixerMT;
- bool _multiThread;
- #ifdef _ST_MODE
- NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;
+ #ifdef USE_MIXER_ST
+ NCoderMixer2::CMixerST *_mixerST;
#endif
- NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;
- NCoderMixer::CCoderMixer2 *_mixerCoderCommon;
- CMyComPtr<ICompressCoder2> _mixerCoder;
- CObjectVector<CMyComPtr<IUnknown> > _decoders;
- // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;
+ #ifdef USE_MIXER_MT
+ NCoderMixer2::CMixerMT *_mixerMT;
+ #endif
+
+ NCoderMixer2::CMixer *_mixer;
+ CMyComPtr<IUnknown> _mixerRef;
+
public:
- CDecoder(bool multiThread);
+
+ CDecoder(bool useMixerMT);
+
HRESULT Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
- const CFolders &folders, int folderIndex,
- ISequentialOutStream *outStream,
- ICompressProgressInfo *compressProgress
+ const CFolders &folders, unsigned folderIndex,
+ const UInt64 *unpackSize // if (!unpackSize), then full folder is required
+ // if (unpackSize), then only *unpackSize bytes from folder are required
+
+ , ISequentialOutStream *outStream
+ , ICompressProgressInfo *compressProgress
+ , ISequentialInStream **inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS_DECL
+
#if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads
#endif
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 36ff5177..ab251711 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -12,43 +12,80 @@
#include "7zEncode.h"
#include "7zSpecStream.h"
-static const UInt64 k_Delta = 0x03;
-static const UInt64 k_BCJ = 0x03030103;
-static const UInt64 k_BCJ2 = 0x0303011B;
-
namespace NArchive {
namespace N7z {
-static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,
- const CRecordVector<CMethodId> decompressionMethods,
- CFolder &folder)
+void CEncoder::InitBindConv()
+{
+ unsigned numIn = _bindInfo.Coders.Size();
+
+ _SrcIn_to_DestOut.ClearAndSetSize(numIn);
+ _DestOut_to_SrcIn.ClearAndSetSize(numIn);
+
+ unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
+ _SrcOut_to_DestIn.ClearAndSetSize(numOut);
+ // _DestIn_to_SrcOut.ClearAndSetSize(numOut);
+
+ UInt32 destIn = 0;
+ UInt32 destOut = 0;
+
+ for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
+ {
+ i--;
+
+ const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
+
+ numIn--;
+ numOut -= coder.NumStreams;
+
+ _SrcIn_to_DestOut[numIn] = destOut;
+ _DestOut_to_SrcIn[destOut] = numIn;
+
+ destOut++;
+
+ for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
+ {
+ UInt32 index = numOut + j;
+ _SrcOut_to_DestIn[index] = destIn;
+ // _DestIn_to_SrcOut[destIn] = index;
+ }
+ }
+}
+
+void CEncoder::SetFolder(CFolder &folder)
{
- // bindInfo.CoderMethodIDs.Clear();
- // folder.OutStreams.Clear();
- folder.BindPairs.SetSize(bindInfo.BindPairs.Size());
+ folder.Bonds.SetSize(_bindInfo.Bonds.Size());
+
unsigned i;
- for (i = 0; i < bindInfo.BindPairs.Size(); i++)
+
+ for (i = 0; i < _bindInfo.Bonds.Size(); i++)
{
- CBindPair &bp = folder.BindPairs[i];
- const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];
- bp.InIndex = mixerBp.InIndex;
- bp.OutIndex = mixerBp.OutIndex;
+ CBond &fb = folder.Bonds[i];
+ const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
+ fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex];
+ fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex];
}
- folder.Coders.SetSize(bindInfo.Coders.Size());
- for (i = 0; i < bindInfo.Coders.Size(); i++)
+
+ folder.Coders.SetSize(_bindInfo.Coders.Size());
+
+ for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
CCoderInfo &coderInfo = folder.Coders[i];
- const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
- coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
- coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
- coderInfo.MethodID = decompressionMethods[i];
- // coderInfo.Props can be nonFree;
+ const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
+
+ coderInfo.NumStreams = coderStreamsInfo.NumStreams;
+ coderInfo.MethodID = _decompressionMethods[i];
+ // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
}
- folder.PackStreams.SetSize(bindInfo.InStreams.Size());
- for (i = 0; i < bindInfo.InStreams.Size(); i++)
- folder.PackStreams[i] = bindInfo.InStreams[i];
+
+ folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
+
+ for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
+ folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
}
+
+
static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
{
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
@@ -58,30 +95,75 @@ static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce,
return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
}
+
+
+void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
+{
+ _progress = progress;
+ OutSize = 0;
+}
+
+STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ UInt64 outSize2;
+ {
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
+ #endif
+ outSize2 = OutSize;
+ }
+
+ if (_progress)
+ return _progress->SetRatioInfo(inSize, &outSize2);
+
+ return S_OK;
+}
+
+
+
HRESULT CEncoder::CreateMixerCoder(
DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce)
{
- _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
- _mixerCoder = _mixerCoderSpec;
- RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_options.MultiThreadMixer)
+ #endif
+ {
+ _mixerMT = new NCoderMixer2::CMixerMT(true);
+ _mixerRef = _mixerMT;
+ _mixer = _mixerMT;
+ }
+ #ifdef USE_MIXER_ST
+ else
+ #endif
+ #endif
+ {
+ #ifdef USE_MIXER_ST
+ _mixerST = new NCoderMixer2::CMixerST(true);
+ _mixerRef = _mixerST;
+ _mixer = _mixerST;
+ #endif
+ }
+
+ RINOK(_mixer->SetBindInfo(_bindInfo));
+
FOR_VECTOR (i, _options.Methods)
{
const CMethodFull &methodFull = _options.Methods[i];
- CCoderInfo &encodingInfo = _codersInfo.AddNew();
- encodingInfo.MethodID = methodFull.Id;
- CMyComPtr<ICompressCoder> encoder;
- CMyComPtr<ICompressCoder2> encoder2;
-
+ CCreatedCoder cod;
+
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- methodFull.Id, encoder, encoder2, true));
+ methodFull.Id, true, cod));
- if (!encoder && !encoder2)
+ if (cod.NumStreams != methodFull.NumStreams)
+ return E_FAIL;
+ if (!cod.Coder && !cod.Coder2)
return E_FAIL;
- CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
+ CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
#ifndef _7ZIP_ST
{
@@ -105,21 +187,25 @@ HRESULT CEncoder::CreateMixerCoder(
}
*/
+ // now there is no codec that uses another external codec
+ /*
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
+ // we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
}
#endif
+ */
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
if (cryptoSetPassword)
{
- const UInt32 sizeInBytes = _options.Password.Len() * 2;
+ const unsigned sizeInBytes = _options.Password.Len() * 2;
CByteBuffer buffer(sizeInBytes);
for (unsigned i = 0; i < _options.Password.Len(); i++)
{
@@ -127,21 +213,79 @@ HRESULT CEncoder::CreateMixerCoder(
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
- RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes));
}
- if (encoder)
- _mixerCoderSpec->AddCoder(encoder);
- else
- _mixerCoderSpec->AddCoder2(encoder2);
+ _mixer->AddCoder(cod);
}
return S_OK;
}
+
+
+class CSequentialOutTempBufferImp2:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CInOutTempBuffer *_buf;
+public:
+ CMtEncMultiProgress *_mtProgresSpec;
+
+ CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {}
+ void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)
+{
+ if (!_buf->Write(data, size))
+ {
+ if (processed)
+ *processed = 0;
+ return E_FAIL;
+ }
+ if (processed)
+ *processed = size;
+ if (_mtProgresSpec)
+ _mtProgresSpec->AddOutSize(size);
+ return S_OK;
+}
+
+
+class CSequentialOutMtNotify:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<ISequentialOutStream> _stream;
+ CMtEncMultiProgress *_mtProgresSpec;
+
+ CSequentialOutMtNotify(): _mtProgresSpec(NULL) {}
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed)
+{
+ UInt32 realProcessed = 0;
+ HRESULT res = _stream->Write(data, size, &realProcessed);
+ if (processed)
+ *processed = realProcessed;
+ if (_mtProgresSpec)
+ _mtProgresSpec->AddOutSize(size);
+ return res;
+}
+
+
+
HRESULT CEncoder::Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
- const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ // const UInt64 *inStreamSize,
+ const UInt64 *inSizeForReduce,
CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize,
@@ -151,27 +295,37 @@ HRESULT CEncoder::Encode(
{
RINOK(EncoderConstr());
- if (!_mixerCoderSpec)
+ if (!_mixerRef)
{
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
}
- _mixerCoderSpec->ReInit();
- // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
+
+ _mixer->ReInit();
+
+ CMtEncMultiProgress *mtProgressSpec = NULL;
+ CMyComPtr<ICompressProgressInfo> mtProgress;
+
+ CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
+ CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
- CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
+ CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
+
unsigned numMethods = _bindInfo.Coders.Size();
+
unsigned i;
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
iotb.Create();
iotb.InitWriting();
}
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
- CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;
+ CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;
CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
tempBuffers.Add(tempBuffer);
@@ -179,94 +333,111 @@ HRESULT CEncoder::Encode(
}
for (i = 0; i < numMethods; i++)
- _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
+ _mixer->SetCoderInfo(i, NULL, NULL);
- if (_bindInfo.InStreams.IsEmpty())
- return E_FAIL;
- UInt32 mainCoderIndex, mainStreamIndex;
- _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
-
+
+ /* inStreamSize can be used by BCJ2 to set optimal range of conversion.
+ But current BCJ2 encoder uses also another way to check exact size of current file.
+ So inStreamSize is not required. */
+
+ /*
if (inStreamSize)
- {
- CRecordVector<const UInt64 *> sizePointers;
- for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
- if (i == mainStreamIndex)
- sizePointers.Add(inStreamSize);
- else
- sizePointers.Add(NULL);
- _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
- }
+ _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
+ */
- // UInt64 outStreamStartPos;
- // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
-
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
+
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
CMyComPtr<ISequentialOutStream> outStreamSizeCount;
inStreamSizeCountSpec->Init(inStream);
- CRecordVector<ISequentialInStream *> inStreamPointers;
+ ISequentialInStream *inStreamPointer = inStreamSizeCount;
CRecordVector<ISequentialOutStream *> outStreamPointers;
- inStreamPointers.Add(inStreamSizeCount);
- if (_bindInfo.OutStreams.Size() != 0)
- {
- outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
- outStreamSizeCount = outStreamSizeCountSpec;
- outStreamSizeCountSpec->SetStream(outStream);
- outStreamSizeCountSpec->Init();
- outStreamPointers.Add(outStreamSizeCount);
- }
+ SetFolder(folderItem);
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
- outStreamPointers.Add(tempBuffers[i - 1]);
-
- for (i = 0; i < _codersInfo.Size(); i++)
+ for (i = 0; i < numMethods; i++)
{
- CCoderInfo &encodingInfo = _codersInfo[i];
-
+ IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
+
CMyComPtr<ICryptoResetInitVector> resetInitVector;
- _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
+ coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
if (resetInitVector)
{
resetInitVector->ResetInitVector();
}
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
- _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+ coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+
+ CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;
+
if (writeCoderProperties)
{
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
- CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
outStreamSpec->Init();
- writeCoderProperties->WriteCoderProperties(outStream);
- outStreamSpec->CopyToBuffer(encodingInfo.Props);
+ writeCoderProperties->WriteCoderProperties(dynOutStream);
+ outStreamSpec->CopyToBuffer(props);
}
+ else
+ props.Free();
}
- UInt32 progressIndex = mainCoderIndex;
+ _mixer->SelectMainCoder(false);
+ UInt32 mainCoder = _mixer->MainCoderIndex;
- for (i = 0; i + 1 < _codersInfo.Size(); i++)
+ bool useMtProgress = false;
+ if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
{
- UInt64 m = _codersInfo[i].MethodID;
- if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
- progressIndex = i + 1;
+ #ifdef _7ZIP_ST
+ if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
+ #endif
+ useMtProgress = true;
}
- _mixerCoderSpec->SetProgressCoderIndex(progressIndex);
+ if (useMtProgress)
+ {
+ mtProgressSpec = new CMtEncMultiProgress;
+ mtProgress = mtProgressSpec;
+ mtProgressSpec->Init(compressProgress);
+
+ mtOutStreamNotifySpec = new CSequentialOutMtNotify;
+ mtOutStreamNotify = mtOutStreamNotifySpec;
+ mtOutStreamNotifySpec->_stream = outStream;
+ mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
+
+ FOR_VECTOR(i, tempBufferSpecs)
+ {
+ tempBufferSpecs[i]->_mtProgresSpec = mtProgressSpec;
+ }
+ }
- RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
- &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
- ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
+ if (_bindInfo.PackStreams.Size() != 0)
+ {
+ outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
+ outStreamSizeCount = outStreamSizeCountSpec;
+ outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
+ outStreamSizeCountSpec->Init();
+ outStreamPointers.Add(outStreamSizeCount);
+ }
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
+ outStreamPointers.Add(tempBuffers[i - 1]);
+
+ RINOK(_mixer->Code(
+ &inStreamPointer,
+ &outStreamPointers.Front(),
+ mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
- if (_bindInfo.OutStreams.Size() != 0)
+ if (_bindInfo.PackStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize());
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
RINOK(inOutTempBuffer.WriteToStream(outStream));
@@ -274,37 +445,45 @@ HRESULT CEncoder::Encode(
}
unpackSize = 0;
- for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
+
+ for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
- int binder = _bindInfo.FindBinderForInStream(
- _bindReverseConverter->DestOutToSrcInMap[i]);
+ int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);
UInt64 streamSize;
- if (binder < 0)
+ if (bond < 0)
{
streamSize = inStreamSizeCountSpec->GetSize();
unpackSize = streamSize;
}
else
- streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
+ streamSize = _mixer->GetBondStreamSize(bond);
coderUnpackSizes.Add(streamSize);
}
- for (i = 0; i < numMethods; i++)
- folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;
+
return S_OK;
}
CEncoder::CEncoder(const CCompressionMethodMode &options):
- _bindReverseConverter(0),
- _constructed(false)
+ _constructed(false)
{
if (options.IsEmpty())
throw 1;
_options = options;
- _mixerCoderSpec = NULL;
+
+ #ifdef USE_MIXER_ST
+ _mixerST = NULL;
+ #endif
+
+ #ifdef USE_MIXER_MT
+ _mixerMT = NULL;
+ #endif
+
+ _mixer = NULL;
}
+
HRESULT CEncoder::EncoderConstr()
{
if (_constructed)
@@ -314,112 +493,125 @@ HRESULT CEncoder::EncoderConstr()
// it has only password method;
if (!_options.PasswordIsDefined)
throw 1;
- if (!_options.Binds.IsEmpty())
+ if (!_options.Bonds.IsEmpty())
throw 1;
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+
CMethodFull method;
-
- method.NumInStreams = 1;
- method.NumOutStreams = 1;
- coderStreamsInfo.NumInStreams = 1;
- coderStreamsInfo.NumOutStreams = 1;
method.Id = k_AES;
-
+ method.NumStreams = 1;
_options.Methods.Add(method);
+
+ NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
+ coderStreamsInfo.NumStreams = 1;
_bindInfo.Coders.Add(coderStreamsInfo);
- _bindInfo.InStreams.Add(0);
- _bindInfo.OutStreams.Add(0);
+ _bindInfo.PackStreams.Add(0);
+ _bindInfo.UnpackCoder = 0;
}
else
{
- UInt32 numInStreams = 0, numOutStreams = 0;
+ UInt32 numOutStreams = 0;
unsigned i;
+
for (i = 0; i < _options.Methods.Size(); i++)
{
const CMethodFull &methodFull = _options.Methods[i];
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
- coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
- coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
- if (_options.Binds.IsEmpty())
+ NCoderMixer2::CCoderStreamsInfo cod;
+
+ cod.NumStreams = methodFull.NumStreams;
+
+ if (_options.Bonds.IsEmpty())
{
- if (i < _options.Methods.Size() - 1)
+ // if there are no bonds in options, we create bonds via first streams of coders
+ if (i != _options.Methods.Size() - 1)
{
- NCoderMixer::CBindPair bindPair;
- bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
- bindPair.OutIndex = numOutStreams;
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond bond;
+ bond.PackIndex = numOutStreams;
+ bond.UnpackIndex = i + 1; // it's next coder
+ _bindInfo.Bonds.Add(bond);
}
- else if (coderStreamsInfo.NumOutStreams != 0)
- _bindInfo.OutStreams.Insert(0, numOutStreams);
- for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
- _bindInfo.OutStreams.Add(numOutStreams + j);
+ else if (cod.NumStreams != 0)
+ _bindInfo.PackStreams.Insert(0, numOutStreams);
+
+ for (UInt32 j = 1; j < cod.NumStreams; j++)
+ _bindInfo.PackStreams.Add(numOutStreams + j);
}
- numInStreams += coderStreamsInfo.NumInStreams;
- numOutStreams += coderStreamsInfo.NumOutStreams;
+ numOutStreams += cod.NumStreams;
- _bindInfo.Coders.Add(coderStreamsInfo);
+ _bindInfo.Coders.Add(cod);
}
- if (!_options.Binds.IsEmpty())
+ if (!_options.Bonds.IsEmpty())
{
- for (i = 0; i < _options.Binds.Size(); i++)
+ for (i = 0; i < _options.Bonds.Size(); i++)
{
- NCoderMixer::CBindPair bindPair;
- const CBind &bind = _options.Binds[i];
- bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
- bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond mixerBond;
+ const CBond2 &bond = _options.Bonds[i];
+ if (bond.InCoder >= _bindInfo.Coders.Size()
+ || bond.OutCoder >= _bindInfo.Coders.Size()
+ || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
+ return E_INVALIDARG;
+ mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
+ mixerBond.UnpackIndex = bond.InCoder;
+ _bindInfo.Bonds.Add(mixerBond);
}
- for (i = 0; i < (int)numOutStreams; i++)
- if (_bindInfo.FindBinderForOutStream(i) == -1)
- _bindInfo.OutStreams.Add(i);
+
+ for (i = 0; i < numOutStreams; i++)
+ if (_bindInfo.FindBond_for_PackStream(i) == -1)
+ _bindInfo.PackStreams.Add(i);
}
- for (i = 0; i < (int)numInStreams; i++)
- if (_bindInfo.FindBinderForInStream(i) == -1)
- _bindInfo.InStreams.Add(i);
+ if (!_bindInfo.SetUnpackCoder())
+ return E_INVALIDARG;
- if (_bindInfo.InStreams.IsEmpty())
- throw 1; // this is error
+ if (!_bindInfo.CalcMapsAndCheck())
+ return E_INVALIDARG;
- // Make main stream first in list
- int inIndex = _bindInfo.InStreams[0];
- for (;;)
+ if (_bindInfo.PackStreams.Size() != 1)
{
- UInt32 coderIndex, coderStreamIndex;
- _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
- UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
- int binder = _bindInfo.FindBinderForOutStream(outIndex);
- if (binder >= 0)
+ /* main_PackStream is pack stream of main path of coders tree.
+ We find main_PackStream, and place to start of list of out streams.
+ It allows to use more optimal memory usage for temp buffers,
+ if main_PackStream is largest stream. */
+
+ UInt32 ci = _bindInfo.UnpackCoder;
+
+ for (;;)
{
- inIndex = _bindInfo.BindPairs[binder].InIndex;
- continue;
- }
- for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
- if (_bindInfo.OutStreams[i] == outIndex)
- {
- _bindInfo.OutStreams.Delete(i);
- _bindInfo.OutStreams.Insert(0, outIndex);
+ if (_bindInfo.Coders[ci].NumStreams == 0)
break;
+
+ UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
+ int bond = _bindInfo.FindBond_for_PackStream(outIndex);
+ if (bond >= 0)
+ {
+ ci = _bindInfo.Bonds[bond].UnpackIndex;
+ continue;
}
- break;
+
+ int i = _bindInfo.FindStream_in_PackStreams(outIndex);
+ if (i >= 0)
+ _bindInfo.PackStreams.MoveToFront(i);
+ break;
+ }
}
if (_options.PasswordIsDefined)
{
- unsigned numCryptoStreams = _bindInfo.OutStreams.Size();
+ unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
+ unsigned numInStreams = _bindInfo.Coders.Size();
+
for (i = 0; i < numCryptoStreams; i++)
{
- NCoderMixer::CBindPair bindPair;
- bindPair.InIndex = numInStreams + i;
- bindPair.OutIndex = _bindInfo.OutStreams[i];
- _bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond bond;
+ bond.UnpackIndex = numInStreams + i;
+ bond.PackIndex = _bindInfo.PackStreams[i];
+ _bindInfo.Bonds.Add(bond);
}
- _bindInfo.OutStreams.Clear();
+ _bindInfo.PackStreams.Clear();
/*
if (numCryptoStreams == 0)
@@ -428,37 +620,37 @@ HRESULT CEncoder::EncoderConstr()
for (i = 0; i < numCryptoStreams; i++)
{
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
CMethodFull method;
- method.NumInStreams = 1;
- method.NumOutStreams = 1;
- coderStreamsInfo.NumInStreams = method.NumOutStreams;
- coderStreamsInfo.NumOutStreams = method.NumInStreams;
+ method.NumStreams = 1;
method.Id = k_AES;
-
_options.Methods.Add(method);
- _bindInfo.Coders.Add(coderStreamsInfo);
- _bindInfo.OutStreams.Add(numOutStreams + i);
+
+ NCoderMixer2::CCoderStreamsInfo cod;
+ cod.NumStreams = 1;
+ _bindInfo.Coders.Add(cod);
+
+ _bindInfo.PackStreams.Add(numOutStreams++);
}
}
}
- for (int i = _options.Methods.Size() - 1; i >= 0; i--)
- {
- const CMethodFull &methodFull = _options.Methods[i];
- _decompressionMethods.Add(methodFull.Id);
- }
+ for (unsigned i = _options.Methods.Size(); i != 0;)
+ _decompressionMethods.Add(_options.Methods[--i].Id);
- _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
- _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
+ if (_bindInfo.Coders.Size() > 16)
+ return E_INVALIDARG;
+ if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
+ return E_INVALIDARG;
+
+ if (!_bindInfo.CalcMapsAndCheck())
+ return E_INVALIDARG;
+
+ InitBindConv();
_constructed = true;
return S_OK;
}
-CEncoder::~CEncoder()
-{
- delete _bindReverseConverter;
-}
+CEncoder::~CEncoder() {}
}}
diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h
index 8e20bdb5..f1a9b5ad 100644
--- a/CPP/7zip/Archive/7z/7zEncode.h
+++ b/CPP/7zip/Archive/7z/7zEncode.h
@@ -3,47 +3,82 @@
#ifndef __7Z_ENCODE_H
#define __7Z_ENCODE_H
-// #include "../../Common/StreamObjects.h"
-
#include "7zCompressionMode.h"
#include "../Common/CoderMixer2.h"
-#include "../Common/CoderMixer2MT.h"
-#ifdef _ST_MODE
-#include "../Common/CoderMixer2ST.h"
-#endif
-#include "7zItem.h"
-#include "../../Common/CreateCoder.h"
+#include "7zItem.h"
namespace NArchive {
namespace N7z {
-class CEncoder
+class CMtEncMultiProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
{
- NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;
- CMyComPtr<ICompressCoder2> _mixerCoder;
+ CMyComPtr<ICompressProgressInfo> _progress;
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
+ #endif
+
+public:
+ UInt64 OutSize;
+
+ CMtEncMultiProgress(): OutSize(0) {}
+
+ void Init(ICompressProgressInfo *progress);
- CObjectVector<CCoderInfo> _codersInfo;
+ void AddOutSize(UInt64 addOutSize)
+ {
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
+ #endif
+ OutSize += addOutSize;
+ }
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+class CEncoder
+{
+ #ifdef USE_MIXER_ST
+ NCoderMixer2::CMixerST *_mixerST;
+ #endif
+ #ifdef USE_MIXER_MT
+ NCoderMixer2::CMixerMT *_mixerMT;
+ #endif
+
+ NCoderMixer2::CMixer *_mixer;
+ CMyComPtr<IUnknown> _mixerRef;
CCompressionMethodMode _options;
- NCoderMixer::CBindInfo _bindInfo;
- NCoderMixer::CBindInfo _decompressBindInfo;
- NCoderMixer::CBindReverseConverter *_bindReverseConverter;
+ NCoderMixer2::CBindInfo _bindInfo;
CRecordVector<CMethodId> _decompressionMethods;
+ CRecordVector<UInt32> _SrcIn_to_DestOut;
+ CRecordVector<UInt32> _SrcOut_to_DestIn;
+ // CRecordVector<UInt32> _DestIn_to_SrcOut;
+ CRecordVector<UInt32> _DestOut_to_SrcIn;
+
+ void InitBindConv();
+ void SetFolder(CFolder &folder);
+
HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
const UInt64 *inSizeForReduce);
bool _constructed;
public:
+
CEncoder(const CCompressionMethodMode &options);
~CEncoder();
HRESULT EncoderConstr();
HRESULT Encode(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream,
- const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ // const UInt64 *inStreamSize,
+ const UInt64 *inSizeForReduce,
CFolder &folderItem,
CRecordVector<UInt64> &coderUnpackSizes,
UInt64 &unpackSize,
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index 6d2c5b06..d21bafdb 100644
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -2,205 +2,327 @@
#include "StdAfx.h"
+#include "../../../../C/7zCrc.h"
+
#include "../../../Common/ComTry.h"
#include "../../Common/ProgressUtils.h"
#include "7zDecode.h"
-// #include "7z1Decode.h"
-#include "7zFolderOutStream.h"
#include "7zHandler.h"
+// EXTERN_g_ExternalCodecs
+
namespace NArchive {
namespace N7z {
-struct CExtractFolderInfo
+class CFolderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
{
- #ifdef _7Z_VOL
- int VolumeIndex;
- #endif
- CNum FileIndex;
- CNum FolderIndex;
- CBoolVector ExtractStatuses;
- UInt64 UnpackSize;
- CExtractFolderInfo(
- #ifdef _7Z_VOL
- int volumeIndex,
- #endif
- CNum fileIndex, CNum folderIndex):
- #ifdef _7Z_VOL
- VolumeIndex(volumeIndex),
- #endif
- FileIndex(fileIndex),
- FolderIndex(folderIndex),
- UnpackSize(0)
+ CMyComPtr<ISequentialOutStream> _stream;
+public:
+ bool TestMode;
+ bool CheckCrc;
+private:
+ bool _fileIsOpen;
+ bool _calcCrc;
+ UInt32 _crc;
+ UInt64 _rem;
+
+ const UInt32 *_indexes;
+ unsigned _numFiles;
+ unsigned _fileIndex;
+
+ HRESULT OpenFile(bool isCorrupted = false);
+ HRESULT CloseFile_and_SetResult(Int32 res);
+ HRESULT CloseFile();
+ HRESULT ProcessEmptyFiles();
+
+public:
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+
+ const CDbEx *_db;
+ CMyComPtr<IArchiveExtractCallback> ExtractCallback;
+
+ bool ExtraWriteWasCut;
+
+ CFolderOutStream():
+ TestMode(false),
+ CheckCrc(true)
+ {}
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+
+ HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles);
+ HRESULT FlushCorrupted(Int32 callbackOperationResult);
+
+ bool WasWritingFinished() const { return _numFiles == 0; }
+};
+
+
+HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles)
+{
+ _fileIndex = startIndex;
+ _indexes = indexes;
+ _numFiles = numFiles;
+
+ _fileIsOpen = false;
+ ExtraWriteWasCut = false;
+
+ return ProcessEmptyFiles();
+}
+
+HRESULT CFolderOutStream::OpenFile(bool isCorrupted)
+{
+ const CFileItem &fi = _db->Files[_fileIndex];
+ UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex);
+ Int32 askMode = (_fileIndex == nextFileIndex) ?
+ (TestMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract) :
+ NExtract::NAskMode::kSkip;
+
+ if (isCorrupted
+ && askMode == NExtract::NAskMode::kExtract
+ && !_db->IsItemAnti(_fileIndex)
+ && !fi.IsDir)
+ askMode = NExtract::NAskMode::kTest;
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode));
+
+ _stream = realOutStream;
+ _crc = CRC_INIT_VAL;
+ _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir);
+
+ _fileIsOpen = true;
+ _rem = fi.Size;
+
+ if (askMode == NExtract::NAskMode::kExtract
+ && !realOutStream
+ && !_db->IsItemAnti(_fileIndex)
+ && !fi.IsDir)
+ askMode = NExtract::NAskMode::kSkip;
+ return ExtractCallback->PrepareOperation(askMode);
+}
+
+HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res)
+{
+ _stream.Release();
+ _fileIsOpen = false;
+
+ if (!_indexes)
+ _numFiles--;
+ else if (*_indexes == _fileIndex)
+ {
+ _indexes++;
+ _numFiles--;
+ }
+
+ _fileIndex++;
+ return ExtractCallback->SetOperationResult(res);
+}
+
+HRESULT CFolderOutStream::CloseFile()
+{
+ const CFileItem &fi = _db->Files[_fileIndex];
+ return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ?
+ NExtract::NOperationResult::kOK :
+ NExtract::NOperationResult::kCRCError);
+}
+
+HRESULT CFolderOutStream::ProcessEmptyFiles()
+{
+ while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0)
{
- if (fileIndex != kNumNoIndex)
+ RINOK(OpenFile());
+ RINOK(CloseFile());
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ if (_fileIsOpen)
{
- ExtractStatuses.ClearAndSetSize(1);
- ExtractStatuses[0] = true;
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, cur, &cur);
+ if (_calcCrc)
+ _crc = CrcUpdate(_crc, data, cur);
+ if (processedSize)
+ *processedSize += cur;
+ data = (const Byte *)data + cur;
+ size -= cur;
+ _rem -= cur;
+ if (_rem == 0)
+ {
+ RINOK(CloseFile());
+ RINOK(ProcessEmptyFiles());
+ }
+ RINOK(result);
+ if (cur == 0)
+ break;
+ continue;
}
- };
-};
+
+ RINOK(ProcessEmptyFiles());
+ if (_numFiles == 0)
+ {
+ // we support partial extracting
+ /*
+ if (processedSize)
+ *processedSize += size;
+ break;
+ */
+ ExtraWriteWasCut = true;
+ // return S_FALSE;
+ return k_My_HRESULT_WritingWasCut;
+ }
+ RINOK(OpenFile());
+ }
+
+ return S_OK;
+}
+
+HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)
+{
+ while (_numFiles != 0)
+ {
+ if (_fileIsOpen)
+ {
+ RINOK(CloseFile_and_SetResult(callbackOperationResult));
+ }
+ else
+ {
+ RINOK(OpenFile(true));
+ }
+ }
+ return S_OK;
+}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
{
COM_TRY_BEGIN
- bool testMode = (testModeSpec != 0);
+
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+
UInt64 importantTotalUnpacked = 0;
+ // numItems = (UInt32)(Int32)-1;
+
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
- numItems =
- #ifdef _7Z_VOL
- _refs.Size();
- #else
- _db.Files.Size();
- #endif
+ numItems = _db.Files.Size();
- if(numItems == 0)
+ if (numItems == 0)
return S_OK;
- /*
- if(_volumes.Size() != 1)
- return E_FAIL;
- const CVolume &volume = _volumes.Front();
- const CDbEx &_db = volume.Database;
- IInStream *_inStream = volume.Stream;
- */
-
- CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
- for (UInt32 ii = 0; ii < numItems; ii++)
{
- // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
- UInt32 ref2Index = allFilesMode ? ii : indices[ii];
- // const CRef2 &ref2 = _refs[ref2Index];
-
- // for (UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
+ CNum prevFolder = kNumNoIndex;
+ UInt32 nextFile = 0;
+
+ UInt32 i;
+
+ for (i = 0; i < numItems; i++)
{
- #ifdef _7Z_VOL
- // const CRef &ref = ref2.Refs[ri];
- const CRef &ref = _refs[ref2Index];
-
- int volumeIndex = ref.VolumeIndex;
- const CVolume &volume = _volumes[volumeIndex];
- const CDbEx &db = volume.Database;
- UInt32 fileIndex = ref.ItemIndex;
- #else
- const CDbEx &db = _db;
- UInt32 fileIndex = ref2Index;
- #endif
-
- CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex];
+ UInt32 fileIndex = allFilesMode ? i : indices[i];
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
if (folderIndex == kNumNoIndex)
- {
- extractFolderInfoVector.Add(CExtractFolderInfo(
- #ifdef _7Z_VOL
- volumeIndex,
- #endif
- fileIndex, kNumNoIndex));
continue;
- }
- if (extractFolderInfoVector.IsEmpty() ||
- folderIndex != extractFolderInfoVector.Back().FolderIndex
- #ifdef _7Z_VOL
- || volumeIndex != extractFolderInfoVector.Back().VolumeIndex
- #endif
- )
- {
- extractFolderInfoVector.Add(CExtractFolderInfo(
- #ifdef _7Z_VOL
- volumeIndex,
- #endif
- kNumNoIndex, folderIndex));
- UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex);
- importantTotalUnpacked += unpackSize;
- extractFolderInfoVector.Back().UnpackSize = unpackSize;
- }
-
- CExtractFolderInfo &efi = extractFolderInfoVector.Back();
-
- // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
- CNum startIndex = db.FolderStartFileIndex[folderIndex];
- for (CNum index = efi.ExtractStatuses.Size();
- index <= fileIndex - startIndex; index++)
- {
- // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize;
- // Count partial_folder_size
- // efi.UnpackSize += unpackSize;
- // importantTotalUnpacked += unpackSize;
- efi.ExtractStatuses.Add(index == fileIndex - startIndex);
- }
+ if (folderIndex != prevFolder || fileIndex < nextFile)
+ nextFile = _db.FolderStartFileIndex[folderIndex];
+ for (CNum index = nextFile; index <= fileIndex; index++)
+ importantTotalUnpacked += _db.Files[index].Size;
+ nextFile = fileIndex + 1;
+ prevFolder = folderIndex;
}
}
RINOK(extractCallback->SetTotal(importantTotalUnpacked));
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
CDecoder decoder(
- #ifdef _ST_MODE
- false
+ #ifndef USE_MIXER_ST
+ false
#else
- true
+ _useMultiThreadMixer
#endif
);
- // CDecoder1 decoder;
- UInt64 totalPacked = 0;
- UInt64 totalUnpacked = 0;
UInt64 curPacked, curUnpacked;
- CLocalProgress *lps = new CLocalProgress;
- CMyComPtr<ICompressProgressInfo> progress = lps;
- lps->Init(extractCallback, false);
+ CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
+ extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);
+
+ CFolderOutStream *folderOutStream = new CFolderOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
- for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
+ folderOutStream->_db = &_db;
+ folderOutStream->ExtractCallback = extractCallback;
+ folderOutStream->TestMode = (testModeSpec != 0);
+ folderOutStream->CheckCrc = (_crcSize != 0);
+
+ for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)
{
- lps->OutSize = totalUnpacked;
- lps->InSize = totalPacked;
RINOK(lps->SetCur());
- if (i >= extractFolderInfoVector.Size())
+ if (i >= numItems)
break;
-
- const CExtractFolderInfo &efi = extractFolderInfoVector[i];
- curUnpacked = efi.UnpackSize;
+
+ curUnpacked = 0;
curPacked = 0;
- CFolderOutStream *folderOutStream = new CFolderOutStream;
- CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
+ UInt32 fileIndex = allFilesMode ? i : indices[i];
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
- #ifdef _7Z_VOL
- const CVolume &volume = _volumes[efi.VolumeIndex];
- const CDbEx &db = volume.Database;
- #else
- const CDbEx &db = _db;
- #endif
+ UInt32 numSolidFiles = 1;
- CNum startIndex;
- if (efi.FileIndex != kNumNoIndex)
- startIndex = efi.FileIndex;
- else
- startIndex = db.FolderStartFileIndex[efi.FolderIndex];
+ if (folderIndex != kNumNoIndex)
+ {
+ curPacked = _db.GetFolderFullPackSize(folderIndex);
+ UInt32 nextFile = fileIndex + 1;
+ fileIndex = _db.FolderStartFileIndex[folderIndex];
+ UInt32 k;
+
+ for (k = i + 1; k < numItems; k++)
+ {
+ UInt32 fileIndex2 = allFilesMode ? k : indices[k];
+ if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex
+ || fileIndex2 < nextFile)
+ break;
+ nextFile = fileIndex2 + 1;
+ }
+
+ numSolidFiles = k - i;
+
+ for (k = fileIndex; k < nextFile; k++)
+ curUnpacked += _db.Files[k].Size;
+ }
+
+ HRESULT result = folderOutStream->Init(fileIndex,
+ allFilesMode ? NULL : indices + i,
+ numSolidFiles);
- HRESULT result = folderOutStream->Init(&db,
- #ifdef _7Z_VOL
- volume.StartRef2Index,
- #else
- 0,
- #endif
- startIndex,
- &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);
+ i += numSolidFiles;
RINOK(result);
- if (efi.FileIndex != kNumNoIndex)
+ // to test solid block with zero unpacked size we disable that code
+ if (folderOutStream->WasWritingFinished())
continue;
- CNum folderIndex = efi.FolderIndex;
- curPacked = _db.GetFolderFullPackSize(folderIndex);
-
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (extractCallback)
@@ -212,50 +334,64 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
#ifndef _NO_CRYPTO
bool isEncrypted = false;
bool passwordIsDefined = false;
+ UString password;
#endif
+
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS
- #ifdef _7Z_VOL
- volume.Stream,
- #else
- _inStream,
- #endif
- db.ArcInfo.DataStartPosition,
- db, folderIndex,
+ _inStream,
+ _db.ArcInfo.DataStartPosition,
+ _db, folderIndex,
+ &curUnpacked,
+
outStream,
- progress
+ progress,
+ NULL // *inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST) && !defined(_SFX)
, true, _numThreads
#endif
);
- if (result == S_FALSE)
+ if (result == S_FALSE || result == E_NOTIMPL)
{
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
- }
- if (result == E_NOTIMPL)
- {
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod));
+ bool wasFinished = folderOutStream->WasWritingFinished();
+
+ int resOp = (result == S_FALSE ?
+ NExtract::NOperationResult::kDataError :
+ NExtract::NOperationResult::kUnsupportedMethod);
+
+ RINOK(folderOutStream->FlushCorrupted(resOp));
+
+ if (wasFinished)
+ {
+ // we don't show error, if it's after required files
+ if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage)
+ {
+ RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp));
+ }
+ }
continue;
}
+
if (result != S_OK)
return result;
- if (folderOutStream->WasWritingFinished() != S_OK)
- {
- RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
- }
+
+ RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
+ continue;
}
catch(...)
{
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
- continue;
+ // continue;
+ return E_FAIL;
}
}
+
return S_OK;
+
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
index 3f420a51..14cdc436 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -7,96 +7,103 @@
namespace NArchive {
namespace N7z {
-CFolderInStream::CFolderInStream()
-{
- _inStreamWithHashSpec = new CSequentialInStreamWithCRC;
- _inStreamWithHash = _inStreamWithHashSpec;
-}
-
void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
- const UInt32 *fileIndices, UInt32 numFiles)
+ const UInt32 *indexes, unsigned numFiles)
{
_updateCallback = updateCallback;
+ _indexes = indexes;
_numFiles = numFiles;
- _fileIndex = 0;
- _fileIndices = fileIndices;
- Processed.Clear();
- CRCs.Clear();
- Sizes.Clear();
- _fileIsOpen = false;
- _currentSizeIsDefined = false;
+ _index = 0;
+
+ Processed.ClearAndReserve(numFiles);
+ CRCs.ClearAndReserve(numFiles);
+ Sizes.ClearAndReserve(numFiles);
+
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ _stream.Release();
}
HRESULT CFolderInStream::OpenStream()
{
- _filePos = 0;
- while (_fileIndex < _numFiles)
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ while (_index < _numFiles)
{
CMyComPtr<ISequentialInStream> stream;
- HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
- if (result != S_OK && result != S_FALSE)
- return result;
- _fileIndex++;
- _inStreamWithHashSpec->SetStream(stream);
- _inStreamWithHashSpec->Init();
+ HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
+ if (result != S_OK)
+ {
+ if (result != S_FALSE)
+ return result;
+ }
+
+ _stream = stream;
+
if (stream)
{
- _fileIsOpen = true;
CMyComPtr<IStreamGetSize> streamGetSize;
stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
if (streamGetSize)
{
- RINOK(streamGetSize->GetSize(&_currentSize));
- _currentSizeIsDefined = true;
+ if (streamGetSize->GetSize(&_size) == S_OK)
+ _size_Defined = true;
}
return S_OK;
}
+
+ _index++;
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
- Sizes.Add(0);
- Processed.Add(result == S_OK);
- AddDigest();
+ AddFileInfo(result == S_OK);
}
return S_OK;
}
-void CFolderInStream::AddDigest()
+void CFolderInStream::AddFileInfo(bool isProcessed)
{
- CRCs.Add(_inStreamWithHashSpec->GetCRC());
-}
-
-HRESULT CFolderInStream::CloseStream()
-{
- RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
- _inStreamWithHashSpec->ReleaseStream();
- _fileIsOpen = false;
- _currentSizeIsDefined = false;
- Processed.Add(true);
- Sizes.Add(_filePos);
- AddDigest();
- return S_OK;
+ Processed.Add(isProcessed);
+ Sizes.Add(_pos);
+ CRCs.Add(CRC_GET_DIGEST(_crc));
}
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != 0)
+ if (processedSize)
*processedSize = 0;
- while (size > 0)
+ while (size != 0)
{
- if (_fileIsOpen)
+ if (_stream)
{
UInt32 processed2;
- RINOK(_inStreamWithHash->Read(data, size, &processed2));
- if (processed2 == 0)
+ RINOK(_stream->Read(data, size, &processed2));
+ if (processed2 != 0)
{
- RINOK(CloseStream());
- continue;
+ _crc = CrcUpdate(_crc, data, processed2);
+ _pos += processed2;
+ if (processedSize)
+ *processedSize = processed2;
+ return S_OK;
}
- if (processedSize != 0)
- *processedSize = processed2;
- _filePos += processed2;
- break;
+
+ _stream.Release();
+ _index++;
+ AddFileInfo(true);
+
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
- if (_fileIndex >= _numFiles)
+
+ if (_index >= _numFiles)
break;
RINOK(OpenStream());
}
@@ -106,17 +113,23 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
*value = 0;
- unsigned index2 = (unsigned)subStream;
if (subStream > Sizes.Size())
- return E_FAIL;
- if (index2 < Sizes.Size())
+ return S_FALSE; // E_FAIL;
+
+ unsigned index = (unsigned)subStream;
+ if (index < Sizes.Size())
{
- *value = Sizes[index2];
+ *value = Sizes[index];
return S_OK;
}
- if (!_currentSizeIsDefined)
+
+ if (!_size_Defined)
+ {
+ *value = _pos;
return S_FALSE;
- *value = _currentSize;
+ }
+
+ *value = (_pos > _size ? _pos : _size);
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
index 4ed4b2dd..805db54e 100644
--- a/CPP/7zip/Archive/7z/7zFolderInStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -3,11 +3,13 @@
#ifndef __7Z_FOLDER_IN_STREAM_H
#define __7Z_FOLDER_IN_STREAM_H
+#include "../../../../C/7zCrc.h"
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyVector.h"
+
#include "../../ICoder.h"
#include "../IArchive.h"
-#include "../Common/InStreamWithCRC.h"
-
-#include "7zItem.h"
namespace NArchive {
namespace N7z {
@@ -17,33 +19,34 @@ class CFolderInStream:
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
- CSequentialInStreamWithCRC *_inStreamWithHashSpec;
- CMyComPtr<ISequentialInStream> _inStreamWithHash;
- CMyComPtr<IArchiveUpdateCallback> _updateCallback;
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _pos;
+ UInt32 _crc;
+ bool _size_Defined;
+ UInt64 _size;
- bool _currentSizeIsDefined;
- bool _fileIsOpen;
- UInt64 _currentSize;
- UInt64 _filePos;
- const UInt32 *_fileIndices;
- UInt32 _numFiles;
- UInt32 _fileIndex;
+ const UInt32 *_indexes;
+ unsigned _numFiles;
+ unsigned _index;
+
+ CMyComPtr<IArchiveUpdateCallback> _updateCallback;
HRESULT OpenStream();
- HRESULT CloseStream();
- void AddDigest();
+ void AddFileInfo(bool isProcessed);
public:
CRecordVector<bool> Processed;
CRecordVector<UInt32> CRCs;
CRecordVector<UInt64> Sizes;
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
- CFolderInStream();
- void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);
+ void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
+
+ bool WasFinished() const { return _index == _numFiles; }
+
UInt64 GetFullSize() const
{
UInt64 size = 0;
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
index 847f65bf..e63ee925 100644
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
@@ -1,149 +1,3 @@
// 7zFolderOutStream.cpp
#include "StdAfx.h"
-
-#include "7zFolderOutStream.h"
-
-namespace NArchive {
-namespace N7z {
-
-CFolderOutStream::CFolderOutStream()
-{
- _crcStreamSpec = new COutStreamWithCRC;
- _crcStream = _crcStreamSpec;
-}
-
-HRESULT CFolderOutStream::Init(
- const CDbEx *db,
- UInt32 ref2Offset, UInt32 startIndex,
- const CBoolVector *extractStatuses,
- IArchiveExtractCallback *extractCallback,
- bool testMode, bool checkCrc)
-{
- _db = db;
- _ref2Offset = ref2Offset;
- _startIndex = startIndex;
-
- _extractStatuses = extractStatuses;
- _extractCallback = extractCallback;
- _testMode = testMode;
- _checkCrc = checkCrc;
-
- _currentIndex = 0;
- _fileIsOpen = false;
- return ProcessEmptyFiles();
-}
-
-HRESULT CFolderOutStream::OpenFile()
-{
- Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?
- NExtract::NAskMode::kTest :
- NExtract::NAskMode::kExtract) :
- NExtract::NAskMode::kSkip;
- CMyComPtr<ISequentialOutStream> realOutStream;
- UInt32 index = _startIndex + _currentIndex;
- RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
- _crcStreamSpec->SetStream(realOutStream);
- _crcStreamSpec->Init(_checkCrc);
- _fileIsOpen = true;
- const CFileItem &fi = _db->Files[index];
- _rem = fi.Size;
- if (askMode == NExtract::NAskMode::kExtract && !realOutStream &&
- !_db->IsItemAnti(index) && !fi.IsDir)
- askMode = NExtract::NAskMode::kSkip;
- return _extractCallback->PrepareOperation(askMode);
-}
-
-HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)
-{
- _crcStreamSpec->ReleaseStream();
- _fileIsOpen = false;
- _currentIndex++;
- return _extractCallback->SetOperationResult(res);
-}
-
-HRESULT CFolderOutStream::CloseFileAndSetResult()
-{
- const CFileItem &fi = _db->Files[_startIndex + _currentIndex];
- return CloseFileAndSetResult(
- (fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?
- NExtract::NOperationResult::kOK :
- NExtract::NOperationResult::kCRCError);
-}
-
-HRESULT CFolderOutStream::ProcessEmptyFiles()
-{
- while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
- {
- RINOK(OpenFile());
- RINOK(CloseFileAndSetResult());
- }
- return S_OK;
-}
-
-STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
-{
- if (processedSize != NULL)
- *processedSize = 0;
- while (size != 0)
- {
- if (_fileIsOpen)
- {
- UInt32 cur = size < _rem ? size : (UInt32)_rem;
- RINOK(_crcStream->Write(data, cur, &cur));
- if (cur == 0)
- break;
- data = (const Byte *)data + cur;
- size -= cur;
- _rem -= cur;
- if (processedSize != NULL)
- *processedSize += cur;
- if (_rem == 0)
- {
- RINOK(CloseFileAndSetResult());
- RINOK(ProcessEmptyFiles());
- continue;
- }
- }
- else
- {
- RINOK(ProcessEmptyFiles());
- if (_currentIndex == _extractStatuses->Size())
- {
- // we support partial extracting
- if (processedSize != NULL)
- *processedSize += size;
- break;
- }
- RINOK(OpenFile());
- }
- }
- return S_OK;
-}
-
-STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
-{
- *value = 0;
- if ((int)subStream >= _extractStatuses->Size())
- return S_FALSE;
- *value = _db->Files[_startIndex + (int)subStream].Size;
- return S_OK;
-}
-
-HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
-{
- while (_currentIndex < _extractStatuses->Size())
- {
- if (_fileIsOpen)
- {
- RINOK(CloseFileAndSetResult(resultEOperationResult));
- }
- else
- {
- RINOK(OpenFile());
- }
- }
- return S_OK;
-}
-
-}}
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
index cc2d7734..a32b22e0 100644
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h
@@ -3,56 +3,4 @@
#ifndef __7Z_FOLDER_OUT_STREAM_H
#define __7Z_FOLDER_OUT_STREAM_H
-#include "../../IStream.h"
-#include "../IArchive.h"
-#include "../Common/OutStreamWithCRC.h"
-
-#include "7zIn.h"
-
-namespace NArchive {
-namespace N7z {
-
-class CFolderOutStream:
- public ISequentialOutStream,
- public ICompressGetSubStreamSize,
- public CMyUnknownImp
-{
- COutStreamWithCRC *_crcStreamSpec;
- CMyComPtr<ISequentialOutStream> _crcStream;
- const CDbEx *_db;
- const CBoolVector *_extractStatuses;
- CMyComPtr<IArchiveExtractCallback> _extractCallback;
- UInt32 _ref2Offset;
- UInt32 _startIndex;
- unsigned _currentIndex;
- bool _testMode;
- bool _checkCrc;
- bool _fileIsOpen;
- UInt64 _rem;
-
- HRESULT OpenFile();
- HRESULT CloseFileAndSetResult(Int32 res);
- HRESULT CloseFileAndSetResult();
- HRESULT ProcessEmptyFiles();
-public:
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
-
- CFolderOutStream();
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
- STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
-
- HRESULT Init(
- const CDbEx *db,
- UInt32 ref2Offset, UInt32 startIndex,
- const CBoolVector *extractStatuses,
- IArchiveExtractCallback *extractCallback,
- bool testMode, bool checkCrc);
- HRESULT FlushCorrupted(Int32 resultEOperationResult);
- HRESULT WasWritingFinished() const
- { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
-};
-
-}}
-
#endif
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
index 2b86ed22..d397e818 100644
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -150,22 +150,12 @@ static char *AddProp32(char *s, const char *name, UInt32 v)
void CHandler::AddMethodName(AString &s, UInt64 id)
{
- UString methodName;
- FindMethod(EXTERNAL_CODECS_VARS id, methodName);
- if (methodName.IsEmpty())
- {
- for (unsigned i = 0; i < methodName.Len(); i++)
- if (methodName[i] >= 0x80)
- {
- methodName.Empty();
- break;
- }
- }
- if (methodName.IsEmpty())
+ AString name;
+ FindMethod(EXTERNAL_CODECS_VARS id, name);
+ if (name.IsEmpty())
ConvertMethodIdToString(s, id);
else
- for (unsigned i = 0; i < methodName.Len(); i++)
- s += (char)methodName[i];
+ s += name;
}
#endif
@@ -186,8 +176,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
FOR_VECTOR (i, pm.IDs)
{
UInt64 id = pm.IDs[i];
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
char temp[16];
if (id == k_LZMA2)
{
@@ -376,6 +365,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
// numCoders == 0 ???
CNum numCoders = inByte.ReadNum();
bool needSpace = false;
+
for (; numCoders != 0; numCoders--, needSpace = true)
{
if (pos < 32) // max size of property
@@ -500,17 +490,8 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
}
else
{
- UString methodName;
+ AString methodName;
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
- if (methodName.IsEmpty())
- {
- for (unsigned j = 0; j < methodName.Len(); j++)
- if (methodName[j] >= 0x80)
- {
- methodName.Empty();
- break;
- }
- }
if (needSpace)
temp[--pos] = ' ';
if (methodName.IsEmpty())
@@ -522,10 +503,11 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
break;
pos -= len;
for (unsigned i = 0; i < len; i++)
- temp[pos + i] = (char)methodName[i];
+ temp[pos + i] = methodName[i];
}
}
}
+
if (numCoders != 0 && pos >= 4)
{
temp[--pos] = ' ';
@@ -533,6 +515,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
temp[--pos] = '.';
temp[--pos] = '.';
}
+
return PropVarEm_Set_Str(prop, temp + pos);
// }
}
@@ -555,7 +538,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CFileItem &item = _db.Files[index];
UInt32 index2 = index;
- switch(propID)
+ switch (propID)
{
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
case kpidSize:
@@ -608,7 +591,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
*/
case kpidPath: return _db.GetPath_Prop(index, value);
+
#ifndef _SFX
+
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
case kpidBlock:
{
@@ -617,30 +602,29 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
}
break;
+ /*
case kpidPackedSize0:
case kpidPackedSize1:
case kpidPackedSize2:
case kpidPackedSize3:
case kpidPackedSize4:
{
- /*
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
- const CFolder &folderInfo = _db.Folders[folderIndex];
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
- folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
+ _db.FoStartPackStreamIndex[folderIndex + 1] -
+ _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
{
- prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
+ PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
}
- else
- prop = (UInt64)0;
}
else
- prop = (UInt64)0;
- */
+ PropVarEm_Set_UInt64(value, 0);
}
break;
+ */
+
#endif
}
// prop.Detach(value);
@@ -668,7 +652,13 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
#endif
- CInArchive archive;
+ CInArchive archive(
+ #ifdef __7Z_SET_PROPERTIES
+ _useMultiThreadMixer
+ #else
+ true
+ #endif
+ );
_db.IsArc = false;
RINOK(archive.Open(stream, maxCheckStartPosition));
_db.IsArc = true;
@@ -677,7 +667,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
EXTERNAL_CODECS_VARS
_db
#ifndef _NO_CRYPTO
- , getTextPassword, _isEncrypted, _passwordIsDefined
+ , getTextPassword, _isEncrypted, _passwordIsDefined, _password
#endif
);
RINOK(result);
@@ -688,8 +678,9 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
{
Close();
// return E_INVALIDARG;
+ // return S_FALSE;
// we must return out_of_memory here
- return S_FALSE;
+ return E_OUTOFMEMORY;
}
// _inStream = stream;
#ifndef _SFX
@@ -707,6 +698,7 @@ STDMETHODIMP CHandler::Close()
#ifndef _NO_CRYPTO
_isEncrypted = false;
_passwordIsDefined = false;
+ _password.Empty();
#endif
return S_OK;
COM_TRY_END
@@ -715,11 +707,12 @@ STDMETHODIMP CHandler::Close()
#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
_numThreads = numProcessors;
+ _useMultiThreadMixer = true;
for (UInt32 i = 0; i < numProps; i++)
{
@@ -732,7 +725,8 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
int index = ParseStringToUInt32(name, number);
if (index == 0)
{
- if (name.IsPrefixedBy(L"mt"))
+ if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
continue;
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index c33617c4..8a078e19 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -18,16 +18,6 @@
namespace NArchive {
namespace N7z {
-const UInt32 k_Copy = 0x0;
-const UInt32 k_Delta = 3;
-const UInt32 k_LZMA2 = 0x21;
-const UInt32 k_LZMA = 0x030101;
-const UInt32 k_PPMD = 0x030401;
-const UInt32 k_BCJ = 0x03030103;
-const UInt32 k_BCJ2 = 0x0303011B;
-const UInt32 k_Deflate = 0x040108;
-const UInt32 k_BZip2 = 0x040202;
-
#ifndef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
@@ -64,7 +54,9 @@ public:
CBoolPair Write_ATime;
CBoolPair Write_MTime;
- bool _volumeMode;
+ bool _useMultiThreadMixer;
+
+ // bool _volumeMode;
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
@@ -117,7 +109,7 @@ public:
INTERFACE_IArchiveGetRawProps(;)
#ifdef __7Z_SET_PROPERTIES
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
#ifndef EXTRACT_ONLY
@@ -131,28 +123,29 @@ public:
private:
CMyComPtr<IInStream> _inStream;
NArchive::N7z::CDbEx _db;
+
#ifndef _NO_CRYPTO
bool _isEncrypted;
bool _passwordIsDefined;
+ UString _password;
#endif
#ifdef EXTRACT_ONLY
#ifdef __7Z_SET_PROPERTIES
UInt32 _numThreads;
+ bool _useMultiThreadMixer;
#endif
UInt32 _crcSize;
#else
- CRecordVector<CBind> _binds;
+ CRecordVector<CBond2> _bonds;
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
- void AddDefaultMethod();
- HRESULT SetMainMethod(CCompressionMethodMode &method,
- CObjectVector<COneMethodInfo> &methodsInfo
+ HRESULT SetMainMethod(CCompressionMethodMode &method
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 5e113207..5cab6a82 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -18,11 +18,11 @@ using namespace NWindows;
namespace NArchive {
namespace N7z {
-static const wchar_t *k_LZMA_Name = L"LZMA";
-static const wchar_t *kDefaultMethodName = L"LZMA2";
-static const wchar_t *k_Copy_Name = L"Copy";
+static const char *k_LZMA_Name = "LZMA";
+static const char *kDefaultMethodName = "LZMA2";
+static const char *k_Copy_Name = "Copy";
-static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";
+static const char *k_MatchFinder_ForHeaders = "BT2";
static const UInt32 k_NumFastBytes_ForHeaders = 273;
static const UInt32 k_Level_ForHeaders = 5;
static const UInt32 k_Dictionary_ForHeaders =
@@ -42,7 +42,7 @@ HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodI
{
if (!FindMethod(
EXTERNAL_CODECS_VARS
- m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams))
+ m.MethodName, dest.Id, dest.NumStreams))
return E_INVALIDARG;
(CProps &)dest = (CProps &)m;
return S_OK;
@@ -54,48 +54,62 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
return S_OK;
COneMethodInfo m;
m.MethodName = k_LZMA_Name;
- m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
- m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders);
+ m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);
+ m.AddProp_Level(k_Level_ForHeaders);
m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);
m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);
- m.AddNumThreadsProp(1);
+ m.AddProp_NumThreads(1);
- CMethodFull methodFull;
- RINOK(PropsMethod_To_FullMethod(methodFull, m));
- headerMethod.Methods.Add(methodFull);
- return S_OK;
-}
-
-void CHandler::AddDefaultMethod()
-{
- FOR_VECTOR (i, _methods)
- {
- UString &methodName = _methods[i].MethodName;
- if (methodName.IsEmpty())
- methodName = kDefaultMethodName;
- }
- if (_methods.IsEmpty())
- {
- COneMethodInfo m;
- m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
- _methods.Add(m);
- }
+ CMethodFull &methodFull = headerMethod.Methods.AddNew();
+ return PropsMethod_To_FullMethod(methodFull, m);
}
HRESULT CHandler::SetMainMethod(
- CCompressionMethodMode &methodMode,
- CObjectVector<COneMethodInfo> &methods
+ CCompressionMethodMode &methodMode
#ifndef _7ZIP_ST
, UInt32 numThreads
#endif
)
{
- AddDefaultMethod();
+ methodMode.Bonds = _bonds;
+
+ CObjectVector<COneMethodInfo> methods = _methods;
+
+ {
+ FOR_VECTOR (i, methods)
+ {
+ AString &methodName = methods[i].MethodName;
+ if (methodName.IsEmpty())
+ methodName = kDefaultMethodName;
+ }
+ if (methods.IsEmpty())
+ {
+ COneMethodInfo &m = methods.AddNew();
+ m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
+ methodMode.DefaultMethod_was_Inserted = true;
+ }
+ }
+
+ if (!_filterMethod.MethodName.IsEmpty())
+ {
+ // if (methodMode.Bonds.IsEmpty())
+ {
+ FOR_VECTOR (k, methodMode.Bonds)
+ {
+ CBond2 &bond = methodMode.Bonds[k];
+ bond.InCoder++;
+ bond.OutCoder++;
+ }
+ methods.Insert(0, _filterMethod);
+ methodMode.Filter_was_Inserted = true;
+ }
+ }
const UInt64 kSolidBytes_Min = (1 << 24);
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
bool needSolid = false;
+
FOR_VECTOR (i, methods)
{
COneMethodInfo &oneMethodInfo = methods[i];
@@ -105,9 +119,8 @@ HRESULT CHandler::SetMainMethod(
#endif
);
- CMethodFull methodFull;
+ CMethodFull &methodFull = methodMode.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
- methodMode.Methods.Add(methodFull);
if (methodFull.Id != k_Copy)
needSolid = true;
@@ -125,6 +138,7 @@ HRESULT CHandler::SetMainMethod(
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
default: continue;
}
+
_numSolidBytes = (UInt64)dicSize << 7;
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
@@ -517,18 +531,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CCompressionMethodMode methodMode, headerMethod;
- HRESULT res = SetMainMethod(methodMode, _methods
+ HRESULT res = SetMainMethod(methodMode
#ifndef _7ZIP_ST
, _numThreads
#endif
);
RINOK(res);
- methodMode.Binds = _binds;
RINOK(SetHeaderMethod(headerMethod));
+
#ifndef _7ZIP_ST
methodMode.NumThreads = _numThreads;
+ methodMode.MultiThreadMixer = _useMultiThreadMixer;
headerMethod.NumThreads = 1;
+ headerMethod.MultiThreadMixer = _useMultiThreadMixer;
#endif
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
@@ -542,7 +558,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
Int32 passwordIsDefined;
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
- if (methodMode.PasswordIsDefined && (BSTR)password)
+ if (methodMode.PasswordIsDefined && password)
methodMode.Password = password;
}
@@ -550,6 +566,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool encryptHeaders = false;
+ #ifndef _NO_CRYPTO
+ if (!methodMode.PasswordIsDefined && _passwordIsDefined)
+ {
+ // if header is compressed, we use that password for updated archive
+ methodMode.PasswordIsDefined = true;
+ methodMode.Password = _password;
+ }
+ #endif
+
if (methodMode.PasswordIsDefined)
{
if (_encryptHeadersSpecified)
@@ -569,12 +594,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (numItems < 2)
compressMainHeader = false;
+ int level = GetLevel();
+
CUpdateOptions options;
options.Method = &methodMode;
- options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0;
- int level = GetLevel();
- options.UseFilters = level != 0 && _autoFilter;
- options.MaxFilter = level >= 8;
+ options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;
+ options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);
+ options.MaxFilter = (level >= 8);
+ options.AnalysisLevel = GetAnalysisLevel();
options.HeaderOptions.CompressMainHeader = compressMainHeader;
/*
@@ -587,7 +614,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.NumSolidBytes = _numSolidBytes;
options.SolidExtension = _solidExtension;
options.RemoveSfxBlock = _removeSfxBlock;
- options.VolumeMode = _volumeMode;
+ // options.VolumeMode = _volumeMode;
+
+ options.MultiThreadMixer = _useMultiThreadMixer;
COutArchive archive;
CArchiveDatabaseOut newDatabase;
@@ -635,20 +664,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END
}
-static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
+static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
{
stream = 0;
int index = ParseStringToUInt32(srcString, coder);
if (index == 0)
return E_INVALIDARG;
- srcString.Delete(0, index);
+ srcString.DeleteFrontal(index);
if (srcString[0] == 's')
{
srcString.Delete(0);
int index = ParseStringToUInt32(srcString, stream);
if (index == 0)
return E_INVALIDARG;
- srcString.Delete(0, index);
+ srcString.DeleteFrontal(index);
}
return S_OK;
}
@@ -667,7 +696,10 @@ void COutHandler::InitProps()
Write_ATime.Init();
Write_MTime.Init();
- _volumeMode = false;
+ _useMultiThreadMixer = true;
+
+ // _volumeMode = false;
+
InitSolid();
}
@@ -762,7 +794,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
UInt32 number;
int index = ParseStringToUInt32(name, number);
- UString realName = name.Ptr(index);
+ // UString realName = name.Ptr(index);
if (index == 0)
{
if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
@@ -787,15 +819,17 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
- if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
+ if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
+
+ // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
}
return CMultiMethodProps::SetProperty(name, value);
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
- _binds.Clear();
+ _bonds.Clear();
InitProps();
for (UInt32 i = 0; i < numProps; i++)
@@ -812,15 +846,19 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (value.vt != VT_EMPTY)
return E_INVALIDARG;
name.Delete(0);
- CBind bind;
- RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream));
+
+ CBond2 bond;
+ RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));
if (name[0] != ':')
return E_INVALIDARG;
name.Delete(0);
- RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream));
+ UInt32 inStream = 0;
+ RINOK(ParseBond(name, bond.InCoder, inStream));
+ if (inStream != 0)
+ return E_INVALIDARG;
if (!name.IsEmpty())
return E_INVALIDARG;
- _binds.Add(bind);
+ _bonds.Add(bond);
continue;
}
@@ -831,40 +869,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
if (numEmptyMethods > 0)
{
unsigned k;
- for (k = 0; k < _binds.Size(); k++)
+ for (k = 0; k < _bonds.Size(); k++)
{
- const CBind &bind = _binds[k];
- if (bind.InCoder < (UInt32)numEmptyMethods ||
- bind.OutCoder < (UInt32)numEmptyMethods)
+ const CBond2 &bond = _bonds[k];
+ if (bond.InCoder < (UInt32)numEmptyMethods ||
+ bond.OutCoder < (UInt32)numEmptyMethods)
return E_INVALIDARG;
}
- for (k = 0; k < _binds.Size(); k++)
+ for (k = 0; k < _bonds.Size(); k++)
{
- CBind &bind = _binds[k];
- bind.InCoder -= (UInt32)numEmptyMethods;
- bind.OutCoder -= (UInt32)numEmptyMethods;
+ CBond2 &bond = _bonds[k];
+ bond.InCoder -= (UInt32)numEmptyMethods;
+ bond.OutCoder -= (UInt32)numEmptyMethods;
}
_methods.DeleteFrontal(numEmptyMethods);
}
- AddDefaultMethod();
-
- if (!_filterMethod.MethodName.IsEmpty())
- {
- FOR_VECTOR (k, _binds)
- {
- CBind &bind = _binds[k];
- bind.InCoder++;
- bind.OutCoder++;
- }
- _methods.Insert(0, _filterMethod);
- }
-
- FOR_VECTOR (k, _binds)
+ FOR_VECTOR (k, _bonds)
{
- const CBind &bind = _binds[k];
- if (bind.InCoder >= (UInt32)_methods.Size() ||
- bind.OutCoder >= (UInt32)_methods.Size())
+ const CBond2 &bond = _bonds[k];
+ if (bond.InCoder >= (UInt32)_methods.Size() ||
+ bond.OutCoder >= (UInt32)_methods.Size())
return E_INVALIDARG;
}
diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
index d72fdefa..d7f0ae36 100644
--- a/CPP/7zip/Archive/7z/7zHeader.h
+++ b/CPP/7zip/Archive/7z/7zHeader.h
@@ -96,6 +96,53 @@ namespace NID
};
}
+
+const UInt32 k_Copy = 0;
+const UInt32 k_Delta = 3;
+
+const UInt32 k_LZMA2 = 0x21;
+
+const UInt32 k_SWAP2 = 0x20302;
+const UInt32 k_SWAP4 = 0x20304;
+
+const UInt32 k_LZMA = 0x30101;
+const UInt32 k_PPMD = 0x30401;
+
+const UInt32 k_Deflate = 0x40108;
+const UInt32 k_BZip2 = 0x40202;
+
+const UInt32 k_BCJ = 0x3030103;
+const UInt32 k_BCJ2 = 0x303011B;
+const UInt32 k_PPC = 0x3030205;
+const UInt32 k_IA64 = 0x3030401;
+const UInt32 k_ARM = 0x3030501;
+const UInt32 k_ARMT = 0x3030701;
+const UInt32 k_SPARC = 0x3030805;
+
+const UInt32 k_AES = 0x6F10701;
+
+
+static inline bool IsFilterMethod(UInt64 m)
+{
+ if (m > (UInt64)0xFFFFFFFF)
+ return false;
+ switch ((UInt32)m)
+ {
+ case k_Delta:
+ case k_BCJ:
+ case k_BCJ2:
+ case k_PPC:
+ case k_IA64:
+ case k_ARM:
+ case k_ARMT:
+ case k_SPARC:
+ case k_SWAP2:
+ case k_SWAP4:
+ return true;
+ }
+ return false;
+}
+
}}
#endif
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index 4f04aa83..bd6c4d95 100644
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -32,9 +32,6 @@ using namespace NCOM;
namespace NArchive {
namespace N7z {
-static const UInt32 k_LZMA2 = 0x21;
-static const UInt32 k_LZMA = 0x030101;
-
static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
{
v.ClearAndSetSize(size);
@@ -43,78 +40,6 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false;
}
-static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index)
-{
- if (index >= (UInt32)v.Size())
- return true;
- bool res = v[index];
- v[index] = true;
- return res;
-}
-
-bool CFolder::CheckStructure(unsigned numUnpackSizes) const
-{
- const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it
- const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax
- const unsigned kNumBindsMax = 32;
-
- if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax)
- return false;
-
- {
- CBoolVector v;
- BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size());
-
- unsigned i;
- for (i = 0; i < BindPairs.Size(); i++)
- if (BoolVector_GetAndSet(v, BindPairs[i].InIndex))
- return false;
- for (i = 0; i < PackStreams.Size(); i++)
- if (BoolVector_GetAndSet(v, PackStreams[i]))
- return false;
-
- BoolVector_Fill_False(v, numUnpackSizes);
- for (i = 0; i < BindPairs.Size(); i++)
- if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex))
- return false;
- }
-
- UInt32 mask[kMaskSize];
- unsigned i;
- for (i = 0; i < kMaskSize; i++)
- mask[i] = 0;
-
- {
- CUIntVector inStreamToCoder, outStreamToCoder;
- for (i = 0; i < Coders.Size(); i++)
- {
- CNum j;
- const CCoderInfo &coder = Coders[i];
- for (j = 0; j < coder.NumInStreams; j++)
- inStreamToCoder.Add(i);
- for (j = 0; j < coder.NumOutStreams; j++)
- outStreamToCoder.Add(i);
- }
-
- for (i = 0; i < BindPairs.Size(); i++)
- {
- const CBindPair &bp = BindPairs[i];
- mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]);
- }
- }
-
- for (i = 0; i < kMaskSize; i++)
- for (unsigned j = 0; j < kMaskSize; j++)
- if (((1 << j) & mask[i]) != 0)
- mask[i] |= mask[j];
-
- for (i = 0; i < kMaskSize; i++)
- if (((1 << i) & mask[i]) != 0)
- return false;
-
- return true;
-}
-
class CInArchiveException {};
class CUnsupportedFeatureException: public CInArchiveException {};
@@ -193,6 +118,8 @@ Byte CInByte2::ReadByte()
void CInByte2::ReadBytes(Byte *data, size_t size)
{
+ if (size == 0)
+ return;
if (size > _size - _pos)
ThrowEndOfData();
memcpy(data, _buffer + _pos, size);
@@ -218,41 +145,48 @@ static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
processed = 0;
return 0;
}
- Byte firstByte = *p++;
+
+ unsigned b = *p++;
size--;
- if ((firstByte & 0x80) == 0)
+
+ if ((b & 0x80) == 0)
{
processed = 1;
- return firstByte;
+ return b;
}
- Byte mask = 0x40;
+
if (size == 0)
{
processed = 0;
return 0;
}
+
UInt64 value = (UInt64)*p;
p++;
size--;
+
for (unsigned i = 1; i < 8; i++)
{
- if ((firstByte & mask) == 0)
+ unsigned mask = (unsigned)0x80 >> i;
+ if ((b & mask) == 0)
{
- UInt64 highPart = firstByte & (mask - 1);
- value += (highPart << (i * 8));
+ UInt64 high = b & (mask - 1);
+ value |= (high << (i * 8));
processed = i + 1;
return value;
}
+
if (size == 0)
{
processed = 0;
return 0;
}
+
value |= ((UInt64)*p << (i * 8));
p++;
size--;
- mask >>= 1;
}
+
processed = 9;
return value;
}
@@ -344,6 +278,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
for (;;)
{
UInt32 readSize = kBufSize - kHeaderSize;
+ if (searchHeaderSizeLimit)
{
UInt64 rem = *searchHeaderSizeLimit - offset;
if (readSize > rem)
@@ -351,10 +286,12 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
if (readSize == 0)
return S_FALSE;
}
+
UInt32 processed = 0;
RINOK(stream->Read(buf + kHeaderSize, readSize, &processed));
if (processed == 0)
return S_FALSE;
+
for (UInt32 pos = 0;;)
{
const Byte *p = buf + pos + 1;
@@ -376,6 +313,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
}
}
+
offset += processed;
memmove(buf, buf + processed, kHeaderSize);
}
@@ -415,13 +353,15 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
void CInByte2::ParseFolder(CFolder &folder)
{
- CNum numCoders = ReadNum();
+ UInt32 numCoders = ReadNum();
+
+ if (numCoders == 0)
+ ThrowUnsupported();
folder.Coders.SetSize(numCoders);
- CNum numInStreams = 0;
- CNum numOutStreams = 0;
- CNum i;
+ UInt32 numInStreams = 0;
+ UInt32 i;
for (i = 0; i < numCoders; i++)
{
CCoderInfo &coder = folder.Coders[i];
@@ -441,14 +381,14 @@ void CInByte2::ParseFolder(CFolder &folder)
if ((mainByte & 0x10) != 0)
{
- coder.NumInStreams = ReadNum();
- coder.NumOutStreams = ReadNum();
+ coder.NumStreams = ReadNum();
+ /* numOutStreams = */ ReadNum();
}
else
{
- coder.NumInStreams = 1;
- coder.NumOutStreams = 1;
+ coder.NumStreams = 1;
}
+
if ((mainByte & 0x20) != 0)
{
CNum propsSize = ReadNum();
@@ -458,27 +398,27 @@ void CInByte2::ParseFolder(CFolder &folder)
else
coder.Props.Free();
}
- numInStreams += coder.NumInStreams;
- numOutStreams += coder.NumOutStreams;
+ numInStreams += coder.NumStreams;
}
- CNum numBindPairs = numOutStreams - 1;
- folder.BindPairs.SetSize(numBindPairs);
- for (i = 0; i < numBindPairs; i++)
+ UInt32 numBonds = numCoders - 1;
+ folder.Bonds.SetSize(numBonds);
+ for (i = 0; i < numBonds; i++)
{
- CBindPair &bp = folder.BindPairs[i];
- bp.InIndex = ReadNum();
- bp.OutIndex = ReadNum();
+ CBond &bp = folder.Bonds[i];
+ bp.PackIndex = ReadNum();
+ bp.UnpackIndex = ReadNum();
}
- if (numInStreams < numBindPairs)
+ if (numInStreams < numBonds)
ThrowUnsupported();
- CNum numPackStreams = numInStreams - numBindPairs;
+ UInt32 numPackStreams = numInStreams - numBonds;
folder.PackStreams.SetSize(numPackStreams);
+
if (numPackStreams == 1)
{
for (i = 0; i < numInStreams; i++)
- if (folder.FindBindPairForInStream(i) < 0)
+ if (folder.FindBond_for_PackStream(i) < 0)
{
folder.PackStreams[0] = i;
break;
@@ -509,12 +449,12 @@ void CDatabase::GetPath(unsigned index, UString &path) const
return;
size_t offset = NameOffsets[index];
- size_t size = NameOffsets[index + 1] - offset - 1;
+ size_t size = NameOffsets[index + 1] - offset;
- if (size >= (1 << 20))
+ if (size >= (1 << 28))
return;
- wchar_t *s = path.GetBuffer((unsigned)size);
+ wchar_t *s = path.GetBuf((unsigned)size - 1);
const Byte *p = ((const Byte *)NamesBuf + offset * 2);
@@ -533,7 +473,7 @@ void CDatabase::GetPath(unsigned index, UString &path) const
#endif
- path.ReleaseBuffer((unsigned)size);
+ path.ReleaseBuf_SetLen((unsigned)size - 1);
}
HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
@@ -592,7 +532,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
{
unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
- do
+ for (; len != 0; len--)
{
p -= 2;
--s;
@@ -601,7 +541,7 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
c = WCHAR_PATH_SEPARATOR;
*s = c;
}
- while (--len);
+
const CFileItem &file = Files[cur];
cur = file.Parent;
if (cur < 0)
@@ -639,6 +579,9 @@ void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
}
}
+#define k_Scan_NumCoders_MAX 64
+#define k_Scan_NumCodersStreams_in_Folder_MAX 64
+
void CInArchive::ReadPackInfo(CFolders &f)
{
CNum numPackStreams = ReadNum();
@@ -692,27 +635,31 @@ void CInArchive::ReadUnpackInfo(
folders.FoCodersDataOffset.Alloc(numFolders + 1);
folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
- CRecordVector<bool> InStreamUsed;
- CRecordVector<bool> OutStreamUsed;
+ CBoolVector StreamUsed;
+ CBoolVector CoderUsed;
CNum packStreamIndex = 0;
CNum fo;
CInByte2 *inByte = _inByteBack;
+
for (fo = 0; fo < numFolders; fo++)
{
- UInt32 numOutStreams = 0;
UInt32 indexOfMainStream = 0;
UInt32 numPackStreams = 0;
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
- numOutStreams = 0;
CNum numInStreams = 0;
CNum numCoders = inByte->ReadNum();
+
+ if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
+ ThrowUnsupported();
+
for (CNum ci = 0; ci < numCoders; ci++)
{
Byte mainByte = inByte->ReadByte();
if ((mainByte & 0xC0) != 0)
ThrowUnsupported();
+
unsigned idSize = (mainByte & 0xF);
if (idSize > 8)
ThrowUnsupported();
@@ -725,19 +672,21 @@ void CInArchive::ReadUnpackInfo(
inByte->SkipDataNoCheck(idSize);
if (folders.ParsedMethods.IDs.Size() < 128)
folders.ParsedMethods.IDs.AddToUniqueSorted(id);
+
CNum coderInStreams = 1;
- CNum coderOutStreams = 1;
if ((mainByte & 0x10) != 0)
{
coderInStreams = inByte->ReadNum();
- coderOutStreams = inByte->ReadNum();
+ if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
+ ThrowUnsupported();
+ if (inByte->ReadNum() != 1)
+ ThrowUnsupported();
}
+
numInStreams += coderInStreams;
- if (numInStreams < coderInStreams)
- ThrowUnsupported();
- numOutStreams += coderOutStreams;
- if (numOutStreams < coderOutStreams)
+ if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
ThrowUnsupported();
+
if ((mainByte & 0x20) != 0)
{
CNum propsSize = inByte->ReadNum();
@@ -759,7 +708,7 @@ void CInArchive::ReadUnpackInfo(
}
}
- if (numOutStreams == 1 && numInStreams == 1)
+ if (numCoders == 1 && numInStreams == 1)
{
indexOfMainStream = 0;
numPackStreams = 1;
@@ -767,55 +716,55 @@ void CInArchive::ReadUnpackInfo(
else
{
UInt32 i;
- if (numOutStreams == 0)
- ThrowUnsupported();
- CNum numBindPairs = numOutStreams - 1;
- if (numInStreams < numBindPairs)
- ThrowUnsupported();
- if (numInStreams >= 256 || numOutStreams >= 256)
+ CNum numBonds = numCoders - 1;
+ if (numInStreams < numBonds)
ThrowUnsupported();
- InStreamUsed.ClearAndSetSize(numInStreams);
- for (i = 0; i < numInStreams; i++)
- InStreamUsed[i] = false;
+ BoolVector_Fill_False(StreamUsed, numInStreams);
+ BoolVector_Fill_False(CoderUsed, numCoders);
- OutStreamUsed.ClearAndSetSize(numOutStreams);
- for (i = 0; i < numOutStreams; i++)
- OutStreamUsed[i] = false;
-
- for (i = 0; i < numBindPairs; i++)
+ for (i = 0; i < numBonds; i++)
{
CNum index = ReadNum();
- if (index >= numInStreams || InStreamUsed[index])
+ if (index >= numInStreams || StreamUsed[index])
ThrowUnsupported();
- InStreamUsed[index] = true;
+ StreamUsed[index] = true;
+
index = ReadNum();
- if (index >= numOutStreams || OutStreamUsed[index])
+ if (index >= numCoders || CoderUsed[index])
ThrowUnsupported();
- OutStreamUsed[index] = true;
+ CoderUsed[index] = true;
}
- numPackStreams = numInStreams - numBindPairs;
+ numPackStreams = numInStreams - numBonds;
if (numPackStreams != 1)
for (i = 0; i < numPackStreams; i++)
- inByte->ReadNum(); // PackStreams
+ {
+ CNum index = inByte->ReadNum(); // PackStreams
+ if (index >= numInStreams || StreamUsed[index])
+ ThrowUnsupported();
+ StreamUsed[index] = true;
+ }
- for (i = 0; i < numOutStreams; i++)
- if (!OutStreamUsed[i])
+ for (i = 0; i < numCoders; i++)
+ if (!CoderUsed[i])
{
indexOfMainStream = i;
break;
}
- if (i == numOutStreams)
+
+ if (i == numCoders)
ThrowUnsupported();
}
+
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
- numCodersOutStreams += numOutStreams;
+ numCodersOutStreams += numCoders;
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
packStreamIndex += numPackStreams;
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
}
+
size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
@@ -1105,13 +1054,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
unpackSizes,
digests);
- CDecoder decoder(
- #ifdef _ST_MODE
- false
- #else
- true
- #endif
- );
+ CDecoder decoder(_useMixerMT);
for (CNum i = 0; i < folders.NumFolders; i++)
{
@@ -1127,14 +1070,20 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
outStreamSpec->Init(data, unpackSize);
HRESULT result = decoder.Decode(
- EXTERNAL_CODECS_LOC_VARS
- _stream, baseOffset + dataOffset,
- folders, i,
- outStream, NULL
- _7Z_DECODER_CRYPRO_VARS
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- , false, 1
- #endif
+ EXTERNAL_CODECS_LOC_VARS
+ _stream, baseOffset + dataOffset,
+ folders, i,
+ NULL, // *unpackSize
+
+ outStream,
+ NULL, // *compressProgress
+ NULL // **inStreamMainRes
+
+ _7Z_DECODER_CRYPRO_VARS
+ #if !defined(_7ZIP_ST) && !defined(_SFX)
+ , false // mtMode
+ , 1 // numThreads
+ #endif
);
RINOK(result);
@@ -1208,7 +1157,7 @@ HRESULT CInArchive::ReadHeader(
db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
// if (!db.PackSizes.IsEmpty())
db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
- if (numFiles > 0 && !digests.Defs.IsEmpty())
+ if (numFiles > 0 && !digests.Defs.IsEmpty())
db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
CBoolVector emptyStreamVector;
@@ -1396,6 +1345,9 @@ HRESULT CInArchive::ReadHeader(
type = ReadID(); // Read (NID::kEnd) end of headers
+ if (numFiles - numEmptyStreams != unpackSizes.Size())
+ ThrowUnsupported();
+
CNum emptyFileIndex = 0;
CNum sizeIndex = 0;
@@ -1403,7 +1355,7 @@ HRESULT CInArchive::ReadHeader(
for (i = 0; i < numEmptyStreams; i++)
if (antiFileVector[i])
numAntiItems++;
-
+
for (i = 0; i < numFiles; i++)
{
CFileItem &file = db.Files[i];
@@ -1444,13 +1396,13 @@ HRESULT CInArchive::ReadHeader(
void CDbEx::FillLinks()
{
- FolderStartFileIndex.ClearAndSetSize(NumFolders);
-
- FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size());
+ FolderStartFileIndex.Alloc(NumFolders);
+ FileIndexToFolderIndexMap.Alloc(Files.Size());
CNum folderIndex = 0;
CNum indexInFolder = 0;
unsigned i;
+
for (i = 0; i < Files.Size(); i++)
{
bool emptyStream = !Files[i].HasStream;
@@ -1489,6 +1441,7 @@ void CDbEx::FillLinks()
if (indexInFolder != 0)
ThrowIncorrect();
*/
+
for (;;)
{
if (folderIndex >= NumFolders)
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
index 373000f7..ad8ceba5 100644
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -26,8 +26,8 @@ namespace N7z {
#define _7Z_DECODER_CRYPRO_VARS_DECL
#define _7Z_DECODER_CRYPRO_VARS
#else
-#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined
-#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined
+#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password
+#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password
#endif
struct CParsedMethods
@@ -39,6 +39,11 @@ struct CParsedMethods
CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
};
+struct CFolderEx: public CFolder
+{
+ unsigned UnpackCoder;
+};
+
struct CFolders
{
CNum NumPackStreams;
@@ -47,10 +52,10 @@ struct CFolders
CObjArray<UInt64> PackPositions; // NumPackStreams + 1
// CUInt32DefVector PackCRCs; // we don't use PackCRCs now
- CUInt32DefVector FolderCRCs; // NumFolders
+ CUInt32DefVector FolderCRCs; // NumFolders
CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
- CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
+ CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
@@ -61,10 +66,15 @@ struct CFolders
CParsedMethods ParsedMethods;
void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
+ void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const
+ {
+ ParseFolderInfo(folderIndex, folder);
+ folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];
+ }
unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
{
- return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex];
+ return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
}
UInt64 GetFolderUnpackSize(unsigned folderIndex) const
@@ -103,9 +113,9 @@ struct CDatabase: public CFolders
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
- CRecordVector<bool> IsAnti;
+ CBoolVector IsAnti;
/*
- CRecordVector<bool> IsAux;
+ CBoolVector IsAux;
CByteBuffer SecureBuf;
CRecordVector<UInt32> SecureIDs;
*/
@@ -148,13 +158,14 @@ struct CDatabase: public CFolders
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
- const void * GetName(unsigned index) const
+ /*
+ const void* GetName(unsigned index) const
{
if (!NameOffsets || !NamesBuf)
return NULL;
- return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
+ return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
};
-
+ */
void GetPath(unsigned index, UString &path) const;
HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
};
@@ -181,8 +192,9 @@ struct CInArchiveInfo
struct CDbEx: public CDatabase
{
CInArchiveInfo ArcInfo;
- CRecordVector<CNum> FolderStartFileIndex;
- CRecordVector<CNum> FileIndexToFolderIndexMap;
+
+ CObjArray<CNum> FolderStartFileIndex;
+ CObjArray<CNum> FileIndexToFolderIndexMap;
UInt64 HeadersSize;
UInt64 PhySize;
@@ -234,8 +246,8 @@ struct CDbEx: public CDatabase
// SecureOffsets.Clear();
ArcInfo.Clear();
- FolderStartFileIndex.Clear();
- FileIndexToFolderIndexMap.Clear();
+ FolderStartFileIndex.Free();
+ FileIndexToFolderIndexMap.Free();
HeadersSize = 0;
PhySize = 0;
@@ -243,22 +255,22 @@ struct CDbEx: public CDatabase
void FillLinks();
- UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const
+ UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
{
return ArcInfo.DataStartPosition +
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
}
- UInt64 GetFolderFullPackSize(unsigned folderIndex) const
+ UInt64 GetFolderFullPackSize(CNum folderIndex) const
{
return
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
PackPositions[FoStartPackStreamIndex[folderIndex]];
}
- UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const
+ UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
{
- unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex;
+ size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
return PackPositions[i + 1] - PackPositions[i];
}
@@ -327,6 +339,8 @@ class CInArchive
UInt64 HeadersSize;
+ bool _useMixerMT;
+
void AddByteStream(const Byte *buffer, size_t size);
void DeleteByteStream(bool needUpdatePos)
@@ -340,7 +354,6 @@ class CInArchive
}
}
-private:
HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
@@ -396,7 +409,11 @@ private:
_7Z_DECODER_CRYPRO_VARS_DECL
);
public:
- CInArchive(): _numInByteBufs(0) { }
+ CInArchive(bool useMixerMT):
+ _numInByteBufs(0),
+ _useMixerMT(useMixerMT)
+ {}
+
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
void Close();
diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
index 02a86196..5e2b58f2 100644
--- a/CPP/7zip/Archive/7z/7zItem.h
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -13,8 +13,6 @@
namespace NArchive {
namespace N7z {
-const UInt64 k_AES = 0x06F10701;
-
typedef UInt32 CNum;
const CNum kNumMax = 0x7FFFFFFF;
const CNum kNumNoIndex = 0xFFFFFFFF;
@@ -23,71 +21,70 @@ struct CCoderInfo
{
CMethodId MethodID;
CByteBuffer Props;
- CNum NumInStreams;
- CNum NumOutStreams;
+ UInt32 NumStreams;
- bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+ bool IsSimpleCoder() const { return NumStreams == 1; }
};
-struct CBindPair
+struct CBond
{
- CNum InIndex;
- CNum OutIndex;
+ UInt32 PackIndex;
+ UInt32 UnpackIndex;
};
struct CFolder
{
+ CLASS_NO_COPY(CFolder)
+public:
CObjArray2<CCoderInfo> Coders;
- CObjArray2<CBindPair> BindPairs;
- CObjArray2<CNum> PackStreams;
+ CObjArray2<CBond> Bonds;
+ CObjArray2<UInt32> PackStreams;
- CNum GetNumOutStreams() const
- {
- CNum result = 0;
- FOR_VECTOR(i, Coders)
- result += Coders[i].NumOutStreams;
- return result;
- }
+ CFolder() {}
- int FindBindPairForInStream(CNum inStreamIndex) const
+ bool IsDecodingSupported() const { return Coders.Size() <= 32; }
+
+ int Find_in_PackStreams(UInt32 packStream) const
{
- FOR_VECTOR(i, BindPairs)
- if (BindPairs[i].InIndex == inStreamIndex)
+ FOR_VECTOR(i, PackStreams)
+ if (PackStreams[i] == packStream)
return i;
return -1;
}
- int FindBindPairForOutStream(CNum outStreamIndex) const
+
+ int FindBond_for_PackStream(UInt32 packStream) const
{
- FOR_VECTOR(i, BindPairs)
- if (BindPairs[i].OutIndex == outStreamIndex)
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].PackIndex == packStream)
return i;
return -1;
}
- int FindPackStreamArrayIndex(CNum inStreamIndex) const
+
+ /*
+ int FindBond_for_UnpackStream(UInt32 unpackStream) const
{
- FOR_VECTOR(i, PackStreams)
- if (PackStreams[i] == inStreamIndex)
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].UnpackIndex == unpackStream)
return i;
return -1;
}
- int GetIndexOfMainOutStream() const
+ int FindOutCoder() const
{
- for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--)
- if (FindBindPairForOutStream(i) < 0)
+ for (int i = (int)Coders.Size() - 1; i >= 0; i--)
+ if (FindBond_for_UnpackStream(i) < 0)
return i;
- throw 1;
+ return -1;
}
+ */
bool IsEncrypted() const
{
- for (int i = Coders.Size() - 1; i >= 0; i--)
+ FOR_VECTOR(i, Coders)
if (Coders[i].MethodID == k_AES)
return true;
return false;
}
-
- bool CheckStructure(unsigned numUnpackSizes) const;
};
struct CUInt32DefVector
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
index 9ff97595..2f906588 100644
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -199,7 +199,7 @@ void COutArchive::WriteNumber(UInt64 value)
mask >>= 1;
}
WriteByte(firstByte);
- for (;i > 0; i--)
+ for (; i > 0; i--)
{
WriteByte((Byte)value);
value >>= 8;
@@ -254,31 +254,33 @@ void COutArchive::WriteFolder(const CFolder &folder)
{
WriteNumber(folder.Coders.Size());
unsigned i;
+
for (i = 0; i < folder.Coders.Size(); i++)
{
const CCoderInfo &coder = folder.Coders[i];
{
- size_t propsSize = coder.Props.Size();
-
UInt64 id = coder.MethodID;
- int idSize;
+ unsigned idSize;
for (idSize = 1; idSize < sizeof(id); idSize++)
if ((id >> (8 * idSize)) == 0)
break;
- Byte longID[15];
- for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
- longID[t] = (Byte)(id & 0xFF);
- Byte b;
- b = (Byte)(idSize & 0xF);
+ idSize &= 0xF;
+ Byte temp[16];
+ for (unsigned t = idSize; t != 0; t--, id >>= 8)
+ temp[t] = (Byte)(id & 0xFF);
+
+ Byte b = (Byte)(idSize);
bool isComplex = !coder.IsSimpleCoder();
b |= (isComplex ? 0x10 : 0);
- b |= ((propsSize != 0) ? 0x20 : 0 );
- WriteByte(b);
- WriteBytes(longID, idSize);
+
+ size_t propsSize = coder.Props.Size();
+ b |= ((propsSize != 0) ? 0x20 : 0);
+ temp[0] = b;
+ WriteBytes(temp, idSize + 1);
if (isComplex)
{
- WriteNumber(coder.NumInStreams);
- WriteNumber(coder.NumOutStreams);
+ WriteNumber(coder.NumStreams);
+ WriteNumber(1); // NumOutStreams;
}
if (propsSize == 0)
continue;
@@ -286,17 +288,17 @@ void COutArchive::WriteFolder(const CFolder &folder)
WriteBytes(coder.Props, propsSize);
}
}
- for (i = 0; i < folder.BindPairs.Size(); i++)
+
+ for (i = 0; i < folder.Bonds.Size(); i++)
{
- const CBindPair &bindPair = folder.BindPairs[i];
- WriteNumber(bindPair.InIndex);
- WriteNumber(bindPair.OutIndex);
+ const CBond &bond = folder.Bonds[i];
+ WriteNumber(bond.PackIndex);
+ WriteNumber(bond.UnpackIndex);
}
+
if (folder.PackStreams.Size() > 1)
for (i = 0; i < folder.PackStreams.Size(); i++)
- {
WriteNumber(folder.PackStreams[i]);
- }
}
void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
@@ -521,7 +523,10 @@ HRESULT COutArchive::EncodeStream(
UInt64 unpackSize;
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
+ stream,
+ // NULL,
+ &dataSize64,
+ folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
index cead4bce..6c902668 100644
--- a/CPP/7zip/Archive/7z/7zOut.h
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -29,6 +29,8 @@ public:
}
void WriteBytes(const void *data, size_t size)
{
+ if (size == 0)
+ return;
if (size > _size - _pos)
throw 1;
memcpy(_data + _pos, data, size);
@@ -92,7 +94,7 @@ struct COutFolders
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
CRecordVector<CNum> NumUnpackStreamsVector;
- CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
+ CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
void OutFoldersClear()
{
diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp
index 5ed36947..a2c9bf31 100644
--- a/CPP/7zip/Archive/7z/7zProperties.cpp
+++ b/CPP/7zip/Archive/7z/7zProperties.cpp
@@ -13,7 +13,7 @@ namespace N7z {
struct CPropMap
{
- UInt64 FilePropID;
+ UInt32 FilePropID;
STATPROPSTG StatPROPSTG;
};
@@ -35,7 +35,7 @@ static const CPropMap kPropMap[] =
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
{ NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },
- { NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },
+ { NID::kStartPos, { NULL, kpidPosition, VT_UI8 } },
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
@@ -44,20 +44,12 @@ static const CPropMap kPropMap[] =
#ifndef _SFX
,
- { 97, { NULL,kpidEncrypted, VT_BOOL } },
- { 98, { NULL,kpidMethod, VT_BSTR } },
- { 99, { NULL,kpidBlock, VT_UI4 } }
+ { 97, { NULL, kpidEncrypted, VT_BOOL } },
+ { 98, { NULL, kpidMethod, VT_BSTR } },
+ { 99, { NULL, kpidBlock, VT_UI4 } }
#endif
};
-static int FindPropInMap(UInt64 filePropID)
-{
- for (int i = 0; i < ARRAY_SIZE(kPropMap); i++)
- if (kPropMap[i].FilePropID == filePropID)
- return i;
- return -1;
-}
-
static void CopyOneItem(CRecordVector<UInt64> &src,
CRecordVector<UInt64> &dest, UInt32 item)
{
@@ -131,6 +123,7 @@ void CHandler::FillPopIDs()
_fileInfoPopIDs.Add(98);
_fileInfoPopIDs.Add(99);
#endif
+
#ifdef _MULTI_PACK
_fileInfoPopIDs.Add(100);
_fileInfoPopIDs.Add(101);
@@ -155,16 +148,27 @@ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
{
- if ((int)index >= _fileInfoPopIDs.Size())
+ if (index >= _fileInfoPopIDs.Size())
return E_INVALIDARG;
- int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);
- if (indexInMap == -1)
- return E_INVALIDARG;
- const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;
- *propID = srcItem.propid;
- *varType = srcItem.vt;
- *name = 0;
- return S_OK;
+ UInt64 id = _fileInfoPopIDs[index];
+ for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++)
+ {
+ const CPropMap &pr = kPropMap[i];
+ if (pr.FilePropID == id)
+ {
+ const STATPROPSTG &st = pr.StatPROPSTG;
+ *propID = st.propid;
+ *varType = st.vt;
+ /*
+ if (st.lpwstrName)
+ *name = ::SysAllocString(st.lpwstrName);
+ else
+ */
+ *name = NULL;
+ return S_OK;
+ }
+ }
+ return E_INVALIDARG;
}
}}
diff --git a/CPP/7zip/Archive/7z/7zRegister.cpp b/CPP/7zip/Archive/7z/7zRegister.cpp
index 37ea29d3..389b5407 100644
--- a/CPP/7zip/Archive/7z/7zRegister.cpp
+++ b/CPP/7zip/Archive/7z/7zRegister.cpp
@@ -9,17 +9,13 @@
namespace NArchive {
namespace N7z {
-IMP_CreateArcIn
-IMP_CreateArcOut
+static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
-static CArcInfo g_ArcInfo =
- { "7z", "7z", 0, 7,
- 6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C},
+REGISTER_ARC_IO_DECREMENT_SIG(
+ "7z", "7z", NULL, 7,
+ k_Signature_Dec,
0,
NArcInfoFlags::kFindSignature,
- REF_CreateArc_Pair };
-
-REGISTER_ARC_DEC_SIG(7z)
-// REGISTER_ARC(7z)
+ NULL);
}}
diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h
index 2e26efd5..21155069 100644
--- a/CPP/7zip/Archive/7z/7zSpecStream.h
+++ b/CPP/7zip/Archive/7z/7zSpecStream.h
@@ -3,10 +3,10 @@
#ifndef __7Z_SPEC_STREAM_H
#define __7Z_SPEC_STREAM_H
-#include "../../IStream.h"
-#include "../../ICoder.h"
#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+
class CSequentialInStreamSizeCount2:
public ISequentialInStream,
public ICompressGetSubStreamSize,
@@ -18,14 +18,14 @@ class CSequentialInStreamSizeCount2:
public:
void Init(ISequentialInStream *stream)
{
+ _size = 0;
+ _getSubStreamSize.Release();
_stream = stream;
- _getSubStreamSize = 0;
_stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
- _size = 0;
}
UInt64 GetSize() const { return _size; }
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 7875ed5b..e7c9ecc6 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -13,7 +13,6 @@
#include "../../Compress/CopyCoder.h"
#include "../Common/ItemNameUtils.h"
-#include "../Common/OutStreamWithCRC.h"
#include "7zDecode.h"
#include "7zEncode.h"
@@ -25,9 +24,392 @@
namespace NArchive {
namespace N7z {
-#ifdef MY_CPU_X86_OR_AMD64
-#define USE_86_FILTER
-#endif
+
+#define k_X86 k_BCJ
+
+struct CFilterMode
+{
+ UInt32 Id;
+ UInt32 Delta;
+
+ CFilterMode(): Id(0), Delta(0) {}
+
+ void SetDelta()
+ {
+ if (Id == k_IA64)
+ Delta = 16;
+ else if (Id == k_ARM || Id == k_PPC || Id == k_PPC)
+ Delta = 4;
+ else if (Id == k_ARMT)
+ Delta = 2;
+ else
+ Delta = 0;
+ }
+};
+
+
+/* ---------- PE ---------- */
+
+#define MZ_SIG 0x5A4D
+
+#define PE_SIG 0x00004550
+#define PE_OptHeader_Magic_32 0x10B
+#define PE_OptHeader_Magic_64 0x20B
+#define PE_SectHeaderSize 40
+#define PE_SECT_EXECUTE 0x20000000
+
+static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ if (size < 512 || GetUi16(buf) != MZ_SIG)
+ return 0;
+
+ const Byte *p;
+ UInt32 peOffset, optHeaderSize, filterId;
+
+ peOffset = GetUi32(buf + 0x3C);
+ if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)
+ return 0;
+ p = buf + peOffset;
+ if (GetUi32(p) != PE_SIG)
+ return 0;
+ p += 4;
+
+ switch (GetUi16(p))
+ {
+ case 0x014C:
+ case 0x8664: filterId = k_X86; break;
+
+ /*
+ IMAGE_FILE_MACHINE_ARM 0x01C0 // ARM LE
+ IMAGE_FILE_MACHINE_THUMB 0x01C2 // ARM Thumb / Thumb-2 LE
+ IMAGE_FILE_MACHINE_ARMNT 0x01C4 // ARM Thumb-2, LE
+ Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2).
+ */
+
+ case 0x01C0: // WinCE old
+ case 0x01C2: filterId = k_ARM; break; // WinCE new
+ case 0x01C4: filterId = k_ARMT; break; // WinRT
+
+ case 0x0200: filterId = k_IA64; break;
+ default: return 0;
+ }
+
+ optHeaderSize = GetUi16(p + 16);
+ if (optHeaderSize > (1 << 10))
+ return 0;
+
+ p += 20; /* headerSize */
+
+ switch (GetUi16(p))
+ {
+ case PE_OptHeader_Magic_32:
+ case PE_OptHeader_Magic_64:
+ break;
+ default:
+ return 0;
+ }
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+/* ---------- ELF ---------- */
+
+#define ELF_SIG 0x464C457F
+
+#define ELF_CLASS_32 1
+#define ELF_CLASS_64 2
+
+#define ELF_DATA_2LSB 1
+#define ELF_DATA_2MSB 2
+
+static UInt16 Get16(const Byte *p, Bool be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }
+static UInt32 Get32(const Byte *p, Bool be) { if (be) return GetBe32(p); return GetUi32(p); }
+// static UInt64 Get64(const Byte *p, Bool be) { if (be) return GetBe64(p); return GetUi64(p); }
+
+static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ Bool /* is32, */ be;
+ UInt32 filterId;
+
+ if (size < 512 || buf[6] != 1) /* ver */
+ return 0;
+
+ if (GetUi32(buf) != ELF_SIG)
+ return 0;
+
+ switch (buf[4])
+ {
+ case ELF_CLASS_32: /* is32 = True; */ break;
+ case ELF_CLASS_64: /* is32 = False; */ break;
+ default: return 0;
+ }
+
+ switch (buf[5])
+ {
+ case ELF_DATA_2LSB: be = False; break;
+ case ELF_DATA_2MSB: be = True; break;
+ default: return 0;
+ }
+
+ switch (Get16(buf + 0x12, be))
+ {
+ case 3:
+ case 6:
+ case 62: filterId = k_X86; break;
+ case 2:
+ case 18:
+ case 43: filterId = k_SPARC; break;
+ case 20:
+ case 21: if (!be) return 0; filterId = k_PPC; break;
+ case 40: if ( be) return 0; filterId = k_ARM; break;
+
+ /* Some IA-64 ELF exacutable have size that is not aligned for 16 bytes.
+ So we don't use IA-64 filter for IA-64 ELF */
+ // case 50: if ( be) return 0; filterId = k_IA64; break;
+
+ default: return 0;
+ }
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+
+/* ---------- Mach-O ---------- */
+
+#define MACH_SIG_BE_32 0xCEFAEDFE
+#define MACH_SIG_BE_64 0xCFFAEDFE
+#define MACH_SIG_LE_32 0xFEEDFACE
+#define MACH_SIG_LE_64 0xFEEDFACF
+
+#define MACH_ARCH_ABI64 (1 << 24)
+#define MACH_MACHINE_386 7
+#define MACH_MACHINE_ARM 12
+#define MACH_MACHINE_SPARC 14
+#define MACH_MACHINE_PPC 18
+#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)
+#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)
+
+static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ UInt32 filterId, numCommands, commandsSize;
+
+ if (size < 512)
+ return 0;
+
+ Bool /* mode64, */ be;
+ switch (GetUi32(buf))
+ {
+ case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break;
+ case MACH_SIG_BE_64: /* mode64 = True; */ be = True; break;
+ case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break;
+ case MACH_SIG_LE_64: /* mode64 = True; */ be = False; break;
+ default: return 0;
+ }
+
+ switch (Get32(buf + 4, be))
+ {
+ case MACH_MACHINE_386:
+ case MACH_MACHINE_AMD64: filterId = k_X86; break;
+ case MACH_MACHINE_ARM: if ( be) return 0; filterId = k_ARM; break;
+ case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break;
+ case MACH_MACHINE_PPC:
+ case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break;
+ default: return 0;
+ }
+
+ numCommands = Get32(buf + 0x10, be);
+ commandsSize = Get32(buf + 0x14, be);
+
+ if (commandsSize > (1 << 24) || numCommands > (1 << 18))
+ return 0;
+
+ filterMode->Id = filterId;
+ return 1;
+}
+
+
+/* ---------- WAV ---------- */
+
+#define WAV_SUBCHUNK_fmt 0x20746D66
+#define WAV_SUBCHUNK_data 0x61746164
+
+#define RIFF_SIG 0x46464952
+
+static Bool Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ UInt32 subChunkSize, pos;
+ if (size < 0x2C)
+ return False;
+
+ if (GetUi32(buf + 0) != RIFF_SIG ||
+ GetUi32(buf + 8) != 0x45564157 || // WAVE
+ GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt)
+ return False;
+ subChunkSize = GetUi32(buf + 0x10);
+ /* [0x14 = format] = 1 (PCM) */
+ if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1)
+ return False;
+
+ unsigned numChannels = GetUi16(buf + 0x16);
+ unsigned bitsPerSample = GetUi16(buf + 0x22);
+
+ if ((bitsPerSample & 0x7) != 0 || bitsPerSample >= 256 || numChannels >= 256)
+ return False;
+
+ pos = 0x14 + subChunkSize;
+
+ const int kNumSubChunksTests = 10;
+ // Do we need to scan more than 3 sub-chunks?
+ for (int i = 0; i < kNumSubChunksTests; i++)
+ {
+ if (pos + 8 > size)
+ return False;
+ subChunkSize = GetUi32(buf + pos + 4);
+ if (GetUi32(buf + pos) == WAV_SUBCHUNK_data)
+ {
+ unsigned delta = numChannels * (bitsPerSample >> 3);
+ if (delta >= 256)
+ return False;
+ filterMode->Id = k_Delta;
+ filterMode->Delta = delta;
+ return True;
+ }
+ if (subChunkSize > (1 << 16))
+ return False;
+ pos += subChunkSize + 8;
+ }
+ return False;
+}
+
+static Bool ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode)
+{
+ filterMode->Id = 0;
+ filterMode->Delta = 0;
+
+ if (Parse_EXE(buf, size, filterMode)) return True;
+ if (Parse_ELF(buf, size, filterMode)) return True;
+ if (Parse_MACH(buf, size, filterMode)) return True;
+ return Parse_WAV(buf, size, filterMode);
+}
+
+
+
+
+struct CFilterMode2: public CFilterMode
+{
+ bool Encrypted;
+ unsigned GroupIndex;
+
+ CFilterMode2(): Encrypted(false) {}
+
+ int Compare(const CFilterMode2 &m) const
+ {
+ if (!Encrypted)
+ {
+ if (m.Encrypted)
+ return -1;
+ }
+ else if (!m.Encrypted)
+ return 1;
+
+ if (Id < m.Id) return -1;
+ if (Id > m.Id) return 1;
+
+ if (Delta < m.Delta) return -1;
+ if (Delta > m.Delta) return 1;
+
+ return 0;
+ }
+
+ bool operator ==(const CFilterMode2 &m) const
+ {
+ return Id == m.Id && Delta == m.Delta && Encrypted == m.Encrypted;
+ }
+};
+
+static unsigned GetGroup(CRecordVector<CFilterMode2> &filters, const CFilterMode2 &m)
+{
+ unsigned i;
+ for (i = 0; i < filters.Size(); i++)
+ {
+ const CFilterMode2 &m2 = filters[i];
+ if (m == m2)
+ return i;
+ /*
+ if (m.Encrypted != m2.Encrypted)
+ {
+ if (!m.Encrypted)
+ break;
+ continue;
+ }
+
+ if (m.Id < m2.Id) break;
+ if (m.Id != m2.Id) continue;
+
+ if (m.Delta < m2.Delta) break;
+ if (m.Delta != m2.Delta) continue;
+ */
+ }
+ // filters.Insert(i, m);
+ // return i;
+ return filters.Add(m);
+}
+
+static inline bool Is86Filter(CMethodId m)
+{
+ return (m == k_BCJ || m == k_BCJ2);
+}
+
+static inline bool IsExeFilter(CMethodId m)
+{
+ switch (m)
+ {
+ case k_BCJ:
+ case k_BCJ2:
+ case k_ARM:
+ case k_ARMT:
+ case k_PPC:
+ case k_SPARC:
+ case k_IA64:
+ return true;
+ }
+ return false;
+}
+
+static unsigned Get_FilterGroup_for_Folder(CRecordVector<CFilterMode2> &filters, const CFolderEx &f)
+{
+ CFilterMode2 m;
+ m.Id = 0;
+ m.Delta = 0;
+ m.Encrypted = f.IsEncrypted();
+
+ const CCoderInfo &coder = f.Coders[f.UnpackCoder];
+
+ if (coder.MethodID == k_Delta)
+ {
+ if (coder.Props.Size() == 1)
+ {
+ m.Delta = (unsigned)coder.Props[0] + 1;
+ m.Id = k_Delta;
+ }
+ }
+ else if (IsExeFilter(coder.MethodID))
+ {
+ m.Id = (UInt32)coder.MethodID;
+ if (m.Id == k_BCJ2)
+ m.Id = k_BCJ;
+ m.SetDelta();
+ }
+
+ return GetGroup(filters, m);
+}
+
+
+
static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
UInt64 position, UInt64 size, ICompressProgressInfo *progress)
@@ -44,21 +426,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
}
-static int GetReverseSlashPos(const UString &name)
-{
- int slashPos = name.ReverseFind(L'/');
- #ifdef _WIN32
- int slash1Pos = name.ReverseFind(L'\\');
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
- return slashPos;
-}
-
-int CUpdateItem::GetExtensionPos() const
+/*
+unsigned CUpdateItem::GetExtensionPos() const
{
- int slashPos = GetReverseSlashPos(Name);
- int dotPos = Name.ReverseFind(L'.');
- if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
+ int slashPos = Name.ReverseFind_PathSepar();
+ int dotPos = Name.ReverseFind_Dot();
+ if (dotPos <= slashPos)
return Name.Len();
return dotPos + 1;
}
@@ -67,6 +440,7 @@ UString CUpdateItem::GetExtension() const
{
return Name.Ptr(GetExtensionPos());
}
+*/
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
@@ -91,7 +465,7 @@ static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
return CompareBuffers(c1.Props, c2.Props);
}
-static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
+static int CompareBonds(const CBond &b1, const CBond &b2)
{
RINOZ_COMP(b1.InIndex, b2.InIndex);
return MyCompare(b1.OutIndex, b2.OutIndex);
@@ -105,11 +479,11 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2)
int i;
for (i = 0; i < s1; i++)
RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
- s1 = f1.BindPairs.Size();
- s2 = f2.BindPairs.Size();
+ s1 = f1.Bonds.Size();
+ s2 = f2.Bonds.Size();
RINOZ_COMP(s1, s2);
for (i = 0; i < s1; i++)
- RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
+ RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i]));
return 0;
}
*/
@@ -123,36 +497,34 @@ static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
struct CFolderRepack
{
- int FolderIndex;
- int Group;
+ unsigned FolderIndex;
CNum NumCopyFiles;
};
-static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void * /* param */)
+/*
+static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *)
{
- RINOZ_COMP(p1->Group, p2->Group);
int i1 = p1->FolderIndex;
int i2 = p2->FolderIndex;
- /*
// In that version we don't want to parse folders here, so we don't compare folders
// probably it must be improved in future
- const CDbEx &db = *(const CDbEx *)param;
- RINOZ(CompareFolders(
- db.Folders[i1],
- db.Folders[i2]));
- */
+ // const CDbEx &db = *(const CDbEx *)param;
+ // RINOZ(CompareFolders(
+ // db.Folders[i1],
+ // db.Folders[i2]));
+
return MyCompare(i1, i2);
- /*
- RINOZ_COMP(
- db.NumUnpackStreamsVector[i1],
- db.NumUnpackStreamsVector[i2]);
- if (db.NumUnpackStreamsVector[i1] == 0)
- return 0;
- return CompareFiles(
- db.Files[db.FolderStartFileIndex[i1]],
- db.Files[db.FolderStartFileIndex[i2]]);
- */
+
+ // RINOZ_COMP(
+ // db.NumUnpackStreamsVector[i1],
+ // db.NumUnpackStreamsVector[i2]);
+ // if (db.NumUnpackStreamsVector[i1] == 0)
+ // return 0;
+ // return CompareFiles(
+ // db.Files[db.FolderStartFileIndex[i1]],
+ // db.Files[db.FolderStartFileIndex[i2]]);
}
+*/
/*
we sort empty files and dirs in such order:
@@ -162,7 +534,7 @@ static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2
- Dir.Anti (reverse name sorted)
*/
-static int CompareEmptyItems(const int *p1, const int *p2, void *param)
+static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param)
{
const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
const CUpdateItem &u1 = updateItems[*p1];
@@ -211,9 +583,9 @@ static const char *g_Exts =
" exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
" pdb pch idb ncb opt";
-static int GetExtIndex(const char *ext)
+static unsigned GetExtIndex(const char *ext)
{
- int extIndex = 1;
+ unsigned extIndex = 1;
const char *p = g_Exts;
for (;;)
{
@@ -222,7 +594,7 @@ static int GetExtIndex(const char *ext)
return extIndex;
if (c == ' ')
continue;
- int pos = 0;
+ unsigned pos = 0;
for (;;)
{
char c2 = ext[pos++];
@@ -248,8 +620,8 @@ struct CRefItem
{
const CUpdateItem *UpdateItem;
UInt32 Index;
- UInt32 ExtensionPos;
- UInt32 NamePos;
+ unsigned ExtensionPos;
+ unsigned NamePos;
unsigned ExtensionIndex;
CRefItem() {};
@@ -262,10 +634,10 @@ struct CRefItem
{
if (sortByType)
{
- int slashPos = GetReverseSlashPos(ui.Name);
+ int slashPos = ui.Name.ReverseFind_PathSepar();
NamePos = slashPos + 1;
- int dotPos = ui.Name.ReverseFind(L'.');
- if (dotPos < 0 || dotPos < slashPos)
+ int dotPos = ui.Name.ReverseFind_Dot();
+ if (dotPos <= slashPos)
ExtensionPos = ui.Name.Len();
else
{
@@ -396,35 +768,193 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para
struct CSolidGroup
{
CRecordVector<UInt32> Indices;
+
+ CRecordVector<CFolderRepack> folderRefs;
};
-static const wchar_t *g_ExeExts[] =
+static const char *g_ExeExts[] =
{
- L"dll"
- , L"exe"
- , L"ocx"
- , L"sfx"
- , L"sys"
+ "dll"
+ , "exe"
+ , "ocx"
+ , "sfx"
+ , "sys"
};
static bool IsExeExt(const wchar_t *ext)
{
- for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++)
- if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0)
+ for (unsigned i = 0; i < ARRAY_SIZE(g_ExeExts); i++)
+ if (StringsAreEqualNoCase_Ascii(ext, g_ExeExts[i]))
return true;
return false;
}
+struct CAnalysis
+{
+ CMyComPtr<IArchiveUpdateCallbackFile> Callback;
+ CByteBuffer Buffer;
+
+ bool ParseWav;
+ bool ParseExe;
+ bool ParseAll;
-static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m)
+ CAnalysis():
+ ParseWav(true),
+ ParseExe(false),
+ ParseAll(false)
+ {}
+
+ HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode);
+};
+
+static const size_t kAnalysisBufSize = 1 << 14;
+
+HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode)
+{
+ filterMode.Id = 0;
+ filterMode.Delta = 0;
+
+ CFilterMode filterModeTemp = filterMode;
+
+ int slashPos = ui.Name.ReverseFind_PathSepar();
+ int dotPos = ui.Name.ReverseFind_Dot();
+
+ // if (dotPos > slashPos)
+ {
+ bool needReadFile = ParseAll;
+
+ bool probablyIsSameIsa = false;
+
+ if (!needReadFile || !Callback)
+ {
+ const wchar_t *ext;
+ if (dotPos > slashPos)
+ ext = ui.Name.Ptr(dotPos + 1);
+ else
+ ext = ui.Name.RightPtr(0);
+
+ // p7zip uses the trick to store posix attributes in high 16 bits
+ if (ui.Attrib & 0x8000)
+ {
+ unsigned st_mode = ui.Attrib >> 16;
+ // st_mode = 00111;
+ if ((st_mode & 00111) && (ui.Size >= 2048))
+ {
+ #ifndef _WIN32
+ probablyIsSameIsa = true;
+ #endif
+ needReadFile = true;
+ }
+ }
+
+ if (IsExeExt(ext))
+ {
+ needReadFile = true;
+ #ifdef _WIN32
+ probablyIsSameIsa = true;
+ needReadFile = ParseExe;
+ #endif
+ }
+ else if (StringsAreEqualNoCase_Ascii(ext, "wav"))
+ {
+ needReadFile = ParseWav;
+ }
+ /*
+ else if (!needReadFile && ParseUnixExt)
+ {
+ if (StringsAreEqualNoCase_Ascii(ext, "so")
+ || StringsAreEqualNoCase_Ascii(ext, ""))
+
+ needReadFile = true;
+ }
+ */
+ }
+
+ if (needReadFile && Callback)
+ {
+ if (Buffer.Size() != kAnalysisBufSize)
+ {
+ Buffer.Alloc(kAnalysisBufSize);
+ }
+ {
+ CMyComPtr<ISequentialInStream> stream;
+ HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze);
+ if (result == S_OK && stream)
+ {
+ size_t size = kAnalysisBufSize;
+ result = ReadStream(stream, Buffer, &size);
+ stream.Release();
+ // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK));
+ if (result == S_OK)
+ {
+ Bool parseRes = ParseFile(Buffer, size, &filterModeTemp);
+ if (parseRes && filterModeTemp.Delta == 0)
+ {
+ filterModeTemp.SetDelta();
+ if (filterModeTemp.Delta != 0 && filterModeTemp.Id != k_Delta)
+ {
+ if (ui.Size % filterModeTemp.Delta != 0)
+ {
+ parseRes = false;
+ }
+ }
+ }
+ if (!parseRes)
+ {
+ filterModeTemp.Id = 0;
+ filterModeTemp.Delta = 0;
+ }
+ }
+ }
+ }
+ }
+ else if ((needReadFile && !Callback) || probablyIsSameIsa)
+ {
+ #ifdef MY_CPU_X86_OR_AMD64
+ if (probablyIsSameIsa)
+ filterModeTemp.Id = k_X86;
+ #endif
+ }
+ }
+
+ filterMode = filterModeTemp;
+ return S_OK;
+}
+
+static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m)
{
m.Id = methodID;
- m.NumInStreams = numInStreams;
- m.NumOutStreams = 1;
+ m.NumStreams = numStreams;
+}
+
+static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
+{
+ for (unsigned c = 1; c < mode.Methods.Size(); c++)
+ {
+ if (!mode.IsThereBond_to_Coder(c))
+ {
+ CBond2 bond;
+ bond.OutCoder = 0;
+ bond.OutStream = 0;
+ bond.InCoder = c;
+ mode.Bonds.Add(bond);
+ return S_OK;
+ }
+ }
+ return E_INVALIDARG;
}
-static void AddBcj2Methods(CCompressionMethodMode &mode)
+static HRESULT AddFilterBond(CCompressionMethodMode &mode)
{
+ if (!mode.Bonds.IsEmpty())
+ return AddBondForFilter(mode);
+ return S_OK;
+}
+
+static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
+{
+ // mode.Methods[0] must be k_BCJ2 method !
+
CMethodFull m;
GetMethodFull(k_LZMA, 1, m);
@@ -433,54 +963,121 @@ static void AddBcj2Methods(CCompressionMethodMode &mode)
m.AddProp32(NCoderPropID::kNumThreads, 1);
m.AddProp32(NCoderPropID::kLitPosBits, 2);
m.AddProp32(NCoderPropID::kLitContextBits, 0);
- // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2");
+ // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2");
+
+ unsigned methodIndex = mode.Methods.Size();
+
+ if (mode.Bonds.IsEmpty())
+ {
+ for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++)
+ {
+ CBond2 bond;
+ bond.OutCoder = i;
+ bond.OutStream = 0;
+ bond.InCoder = i + 1;
+ mode.Bonds.Add(bond);
+ }
+ }
mode.Methods.Add(m);
mode.Methods.Add(m);
- CBind bind;
- bind.OutCoder = 0;
- bind.InStream = 0;
- bind.InCoder = 1; bind.OutStream = 0; mode.Binds.Add(bind);
- bind.InCoder = 2; bind.OutStream = 1; mode.Binds.Add(bind);
- bind.InCoder = 3; bind.OutStream = 2; mode.Binds.Add(bind);
+ RINOK(AddBondForFilter(mode));
+ CBond2 bond;
+ bond.OutCoder = 0;
+ bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond);
+ bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond);
+ return S_OK;
}
-static void MakeExeMethod(CCompressionMethodMode &mode,
- bool useFilters, bool addFilter, bool bcj2Filter)
+static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
+ const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter)
{
- if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2)
- return;
- if (mode.Methods.Size() == 2)
+ if (mode.Filter_was_Inserted)
{
- if (mode.Methods[0].Id == k_BCJ2)
- AddBcj2Methods(mode);
- return;
+ const CMethodFull &m = mode.Methods[0];
+ CMethodId id = m.Id;
+ if (id == k_BCJ2)
+ return AddBcj2Methods(mode);
+ if (!m.IsSimpleCoder())
+ return E_NOTIMPL;
+ // if (Bonds.IsEmpty()) we can create bonds later
+ return AddFilterBond(mode);
+ }
+
+ if (filterMode.Id == 0)
+ return S_OK;
+
+ CMethodFull &m = mode.Methods.InsertNew(0);
+
+ {
+ FOR_VECTOR(k, mode.Bonds)
+ {
+ CBond2 &bond = mode.Bonds[k];
+ bond.InCoder++;
+ bond.OutCoder++;
+ }
}
- if (!addFilter)
- return;
- bcj2Filter = bcj2Filter;
- #ifdef USE_86_FILTER
- if (bcj2Filter)
+
+ HRESULT res;
+
+ if (bcj2Filter && Is86Filter(filterMode.Id))
{
- CMethodFull m;
GetMethodFull(k_BCJ2, 4, m);
- mode.Methods.Insert(0, m);
- AddBcj2Methods(mode);
+ res = AddBcj2Methods(mode);
}
else
{
- CMethodFull m;
- GetMethodFull(k_BCJ, 1, m);
- mode.Methods.Insert(0, m);
- CBind bind;
- bind.OutCoder = 0;
- bind.InStream = 0;
- bind.InCoder = 1;
- bind.OutStream = 0;
- mode.Binds.Add(bind);
+ GetMethodFull(filterMode.Id, 1, m);
+ if (filterMode.Id == k_Delta)
+ m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);
+ res = AddFilterBond(mode);
+
+ int alignBits = -1;
+ if (filterMode.Id == k_Delta || filterMode.Delta != 0)
+ {
+ if (filterMode.Delta == 1) alignBits = 0;
+ else if (filterMode.Delta == 2) alignBits = 1;
+ else if (filterMode.Delta == 4) alignBits = 2;
+ else if (filterMode.Delta == 8) alignBits = 3;
+ else if (filterMode.Delta == 16) alignBits = 4;
+ }
+ else
+ {
+ // alignBits = GetAlignForFilterMethod(filterMode.Id);
+ }
+
+ if (res == S_OK && alignBits >= 0)
+ {
+ unsigned nextCoder = 1;
+ if (!mode.Bonds.IsEmpty())
+ {
+ nextCoder = mode.Bonds.Back().InCoder;
+ }
+ if (nextCoder < mode.Methods.Size())
+ {
+ CMethodFull &nextMethod = mode.Methods[nextCoder];
+ if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
+ {
+ if (!nextMethod.Are_Lzma_Model_Props_Defined())
+ {
+ if (alignBits != 0)
+ {
+ if (alignBits > 2 || filterMode.Id == k_Delta)
+ nextMethod.AddProp32(NCoderPropID::kPosStateBits, alignBits);
+ unsigned lc = 0;
+ if (alignBits < 3)
+ lc = 3 - alignBits;
+ nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
+ nextMethod.AddProp32(NCoderPropID::kLitPosBits, alignBits);
+ }
+ }
+ }
+ }
+ }
}
- #endif
+
+ return res;
}
@@ -503,133 +1100,336 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui,
// file.IsAltStream = ui.IsAltStream;
}
-class CFolderOutStream2:
- public ISequentialOutStream,
+class CRepackInStreamWithSizes:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
public CMyUnknownImp
{
- COutStreamWithCRC *_crcStreamSpec;
- CMyComPtr<ISequentialOutStream> _crcStream;
- const CDbEx *_db;
+ CMyComPtr<ISequentialInStream> _stream;
+ // UInt64 _size;
const CBoolVector *_extractStatuses;
- CMyComPtr<ISequentialOutStream> _outStream;
UInt32 _startIndex;
- unsigned _currentIndex;
+public:
+ const CDbEx *_db;
+
+ void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses)
+ {
+ _startIndex = startIndex;
+ _extractStatuses = extractStatuses;
+ // _size = 0;
+ _stream = stream;
+ }
+ // UInt64 GetSize() const { return _size; }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+};
+
+STDMETHODIMP CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ return _stream->Read(data, size, processedSize);
+ /*
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return result;
+ */
+}
+
+STDMETHODIMP CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+ *value = 0;
+ if (subStream >= _extractStatuses->Size())
+ return S_FALSE; // E_FAIL;
+ unsigned index = (unsigned)subStream;
+ if ((*_extractStatuses)[index])
+ {
+ const CFileItem &fi = _db->Files[_startIndex + index];
+ if (fi.HasStream)
+ *value = fi.Size;
+ }
+ return S_OK;
+}
+
+
+class CRepackStreamBase
+{
+protected:
+ bool _needWrite;
bool _fileIsOpen;
+ bool _calcCrc;
+ UInt32 _crc;
UInt64 _rem;
- void OpenFile();
- void CloseFile();
- HRESULT CloseFileAndSetResult();
+ const CBoolVector *_extractStatuses;
+ UInt32 _startIndex;
+ unsigned _currentIndex;
+
+ HRESULT OpenFile();
+ HRESULT CloseFile();
HRESULT ProcessEmptyFiles();
+
public:
- MY_UNKNOWN_IMP
-
- CFolderOutStream2()
- {
- _crcStreamSpec = new COutStreamWithCRC;
- _crcStream = _crcStreamSpec;
- }
+ const CDbEx *_db;
+ CMyComPtr<IArchiveUpdateCallbackFile> _opCallback;
+ CMyComPtr<IArchiveExtractCallbackMessage> _extractCallback;
- HRESULT Init(const CDbEx *db, UInt32 startIndex,
- const CBoolVector *extractStatuses, ISequentialOutStream *outStream);
- void ReleaseOutStream();
+ HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses);
HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
-HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex,
- const CBoolVector *extractStatuses, ISequentialOutStream *outStream)
+HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses)
{
- _db = db;
_startIndex = startIndex;
_extractStatuses = extractStatuses;
- _outStream = outStream;
_currentIndex = 0;
_fileIsOpen = false;
+
return ProcessEmptyFiles();
}
-void CFolderOutStream2::ReleaseOutStream()
+HRESULT CRepackStreamBase::OpenFile()
{
- _outStream.Release();
- _crcStreamSpec->ReleaseStream();
-}
+ UInt32 arcIndex = _startIndex + _currentIndex;
+ const CFileItem &fi = _db->Files[arcIndex];
+
+ _needWrite = (*_extractStatuses)[_currentIndex];
+ if (_opCallback)
+ {
+ RINOK(_opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, arcIndex,
+ _needWrite ?
+ NUpdateNotifyOp::kRepack :
+ NUpdateNotifyOp::kSkip));
+ }
+
+ _crc = CRC_INIT_VAL;
+ _calcCrc = (fi.CrcDefined && !fi.IsDir);
-void CFolderOutStream2::OpenFile()
-{
- _crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL);
- _crcStreamSpec->Init(true);
_fileIsOpen = true;
- _rem = _db->Files[_startIndex + _currentIndex].Size;
+ _rem = fi.Size;
+ return S_OK;
}
-void CFolderOutStream2::CloseFile()
+const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002;
+
+HRESULT CRepackStreamBase::CloseFile()
{
- _crcStreamSpec->ReleaseStream();
+ UInt32 arcIndex = _startIndex + _currentIndex;
+ const CFileItem &fi = _db->Files[arcIndex];
_fileIsOpen = false;
_currentIndex++;
-}
+ if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc))
+ return S_OK;
-HRESULT CFolderOutStream2::CloseFileAndSetResult()
-{
- const CFileItem &file = _db->Files[_startIndex + _currentIndex];
- CloseFile();
- return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE;
+ if (_extractCallback)
+ {
+ RINOK(_extractCallback->ReportExtractResult(
+ NEventIndexType::kInArcIndex, arcIndex,
+ NExtract::NOperationResult::kCRCError));
+ }
+ // return S_FALSE;
+ return k_My_HRESULT_CRC_ERROR;
}
-HRESULT CFolderOutStream2::ProcessEmptyFiles()
+HRESULT CRepackStreamBase::ProcessEmptyFiles()
{
while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
{
- OpenFile();
- RINOK(CloseFileAndSetResult());
+ RINOK(OpenFile());
+ RINOK(CloseFile());
}
return S_OK;
}
+
+
+
+#ifndef _7ZIP_ST
+
+class CFolderOutStream2:
+ public CRepackStreamBase,
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<ISequentialOutStream> _stream;
+
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
+
while (size != 0)
{
if (_fileIsOpen)
{
- UInt32 cur = size < _rem ? size : (UInt32)_rem;
- RINOK(_crcStream->Write(data, cur, &cur));
- if (cur == 0)
- break;
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+ HRESULT result = S_OK;
+ if (_needWrite)
+ result = _stream->Write(data, cur, &cur);
+ if (_calcCrc)
+ _crc = CrcUpdate(_crc, data, cur);
+ if (processedSize)
+ *processedSize += cur;
data = (const Byte *)data + cur;
size -= cur;
_rem -= cur;
- if (processedSize != NULL)
- *processedSize += cur;
if (_rem == 0)
{
- RINOK(CloseFileAndSetResult());
+ RINOK(CloseFile());
RINOK(ProcessEmptyFiles());
- continue;
}
+ RINOK(result);
+ if (cur == 0)
+ break;
+ continue;
}
- else
+
+ RINOK(ProcessEmptyFiles());
+ if (_currentIndex == _extractStatuses->Size())
{
- RINOK(ProcessEmptyFiles());
- if (_currentIndex == _extractStatuses->Size())
+ // we don't support write cut here
+ return E_FAIL;
+ }
+ RINOK(OpenFile());
+ }
+
+ return S_OK;
+}
+
+#endif
+
+
+
+static const UInt32 kTempBufSize = 1 << 16;
+
+class CFolderInStream2:
+ public CRepackStreamBase,
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ Byte *_buf;
+public:
+ CMyComPtr<ISequentialInStream> _inStream;
+ HRESULT Result;
+
+ MY_UNKNOWN_IMP
+
+ CFolderInStream2():
+ Result(S_OK)
+ {
+ _buf = new Byte[kTempBufSize];
+ }
+
+ ~CFolderInStream2()
+ {
+ delete []_buf;
+ }
+
+ void Init() { Result = S_OK; }
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ if (_fileIsOpen)
+ {
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+
+ void *buf;
+ if (_needWrite)
+ buf = data;
+ else
{
- // we don't support partial extracting
- return E_FAIL;
+ buf = _buf;
+ if (cur > kTempBufSize)
+ cur = kTempBufSize;
}
- OpenFile();
+
+ HRESULT result = _inStream->Read(buf, cur, &cur);
+ _crc = CrcUpdate(_crc, buf, cur);
+ _rem -= cur;
+
+ if (_needWrite)
+ {
+ data = (Byte *)data + cur;
+ size -= cur;
+ if (processedSize)
+ *processedSize += cur;
+ }
+
+ if (result != S_OK)
+ Result = result;
+
+ if (_rem == 0)
+ {
+ RINOK(CloseFile());
+ RINOK(ProcessEmptyFiles());
+ }
+
+ RINOK(result);
+
+ if (cur == 0)
+ return E_FAIL;
+
+ continue;
}
+
+ RINOK(ProcessEmptyFiles());
+ if (_currentIndex == _extractStatuses->Size())
+ {
+ return S_OK;
+ }
+ RINOK(OpenFile());
}
+
return S_OK;
}
-class CThreadDecoder: public CVirtThread
+
+class CThreadDecoder
+ #ifndef _7ZIP_ST
+ : public CVirtThread
+ #endif
{
public:
+ CDecoder Decoder;
+
+ CThreadDecoder(bool multiThreadMixer):
+ Decoder(multiThreadMixer)
+ {
+ #ifndef _7ZIP_ST
+ if (multiThreadMixer)
+ {
+ MtMode = false;
+ NumThreads = 1;
+ FosSpec = new CFolderOutStream2;
+ Fos = FosSpec;
+ Result = E_FAIL;
+ }
+ #endif
+ // UnpackSize = 0;
+ // send_UnpackSize = false;
+ }
+
+ #ifndef _7ZIP_ST
+
HRESULT Result;
CMyComPtr<IInStream> InStream;
@@ -639,33 +1439,30 @@ public:
UInt64 StartPos;
const CFolders *Folders;
int FolderIndex;
+
+ // bool send_UnpackSize;
+ // UInt64 UnpackSize;
+
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
#endif
DECL_EXTERNAL_CODECS_LOC_VARS2;
- CDecoder Decoder;
#ifndef _7ZIP_ST
bool MtMode;
UInt32 NumThreads;
#endif
- CThreadDecoder():
- Decoder(true)
- {
- #ifndef _7ZIP_ST
- MtMode = false;
- NumThreads = 1;
- #endif
- FosSpec = new CFolderOutStream2;
- Fos = FosSpec;
- Result = E_FAIL;
- }
+
~CThreadDecoder() { CVirtThread::WaitThreadFinish(); }
virtual void Execute();
+
+ #endif
};
+#ifndef _7ZIP_ST
+
void CThreadDecoder::Execute()
{
try
@@ -673,6 +1470,7 @@ void CThreadDecoder::Execute()
#ifndef _NO_CRYPTO
bool isEncrypted = false;
bool passwordIsDefined = false;
+ UString password;
#endif
Result = Decoder.Decode(
@@ -680,8 +1478,14 @@ void CThreadDecoder::Execute()
InStream,
StartPos,
*Folders, FolderIndex,
+
+ // send_UnpackSize ? &UnpackSize : NULL,
+ NULL, // unpackSize : FULL unpack
+
Fos,
- NULL
+ NULL, // compressProgress
+ NULL // *inStreamMainRes
+
_7Z_DECODER_CRYPRO_VARS
#ifndef _7ZIP_ST
, MtMode, NumThreads
@@ -692,21 +1496,15 @@ void CThreadDecoder::Execute()
{
Result = E_FAIL;
}
+
+ /*
if (Result == S_OK)
Result = FosSpec->CheckFinishedState();
- FosSpec->ReleaseOutStream();
+ */
+ FosSpec->_stream.Release();
}
-bool static Is86FilteredFolder(const CFolder &f)
-{
- FOR_VECTOR(i, f.Coders)
- {
- CMethodId m = f.Coders[i].MethodID;
- if (m == k_BCJ || m == k_BCJ2)
- return true;
- }
- return false;
-}
+#endif
#ifndef _NO_CRYPTO
@@ -728,14 +1526,8 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)
#endif
-static const int kNumGroupsMax = 4;
-
-static bool Is86Group(int group) { return (group & 1) != 0; }
-static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }
-static int GetGroupIndex(bool encrypted, int bcjFiltered)
- { return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }
-static void GetFile(const CDatabase &inDb, int index, CFileItem &file, CFileItem2 &file2)
+static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2)
{
file = inDb.Files[index];
file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);
@@ -767,6 +1559,12 @@ HRESULT Update(
if (numSolidFiles == 0)
numSolidFiles = 1;
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+
+ CMyComPtr<IArchiveExtractCallbackMessage> extractCallback;
+ updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback);
+
// size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes();
/*
@@ -783,14 +1581,19 @@ HRESULT Update(
}
CIntArr fileIndexToUpdateIndexMap;
- CRecordVector<CFolderRepack> folderRefs;
UInt64 complexity = 0;
UInt64 inSizeForReduce2 = 0;
bool needEncryptedRepack = false;
+
+ CRecordVector<CFilterMode2> filters;
+ CObjectVector<CSolidGroup> groups;
+ bool thereAreRepacks = false;
+
if (db != 0)
{
fileIndexToUpdateIndexMap.Alloc(db->Files.Size());
unsigned i;
+
for (i = 0; i < db->Files.Size(); i++)
fileIndexToUpdateIndexMap[i] = -1;
@@ -798,15 +1601,16 @@ HRESULT Update(
{
int index = updateItems[i].IndexInArchive;
if (index != -1)
- fileIndexToUpdateIndexMap[index] = i;
+ fileIndexToUpdateIndexMap[(unsigned)index] = i;
}
- for (i = 0; i < (int)db->NumFolders; i++)
+ for (i = 0; i < db->NumFolders; i++)
{
CNum indexInFolder = 0;
CNum numCopyItems = 0;
CNum numUnpackStreams = db->NumUnpackStreamsVector[i];
UInt64 repackSize = 0;
+
for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)
{
const CFileItem &file = db->Files[fi];
@@ -828,23 +1632,30 @@ HRESULT Update(
CFolderRepack rep;
rep.FolderIndex = i;
rep.NumCopyFiles = numCopyItems;
- CFolder f;
- db->ParseFolderInfo(i, f);
+ CFolderEx f;
+ db->ParseFolderEx(i, f);
+
bool isEncrypted = f.IsEncrypted();
- rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));
- folderRefs.Add(rep);
+
+ unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f);
+
+ while (groupIndex >= groups.Size())
+ groups.AddNew();
+
+ groups[groupIndex].folderRefs.Add(rep);
+
if (numCopyItems == numUnpackStreams)
complexity += db->GetFolderFullPackSize(i);
else
{
+ thereAreRepacks = true;
complexity += repackSize;
- if (repackSize > inSizeForReduce2)
+ if (inSizeForReduce2 < repackSize)
inSizeForReduce2 = repackSize;
if (isEncrypted)
needEncryptedRepack = true;
}
}
- folderRefs.Sort(CompareFolderRepacks, (void *)db);
}
UInt64 inSizeForReduce = 0;
@@ -857,12 +1668,12 @@ HRESULT Update(
complexity += ui.Size;
if (numSolidFiles != 1)
inSizeForReduce += ui.Size;
- else if (ui.Size > inSizeForReduce)
+ else if (inSizeForReduce < ui.Size)
inSizeForReduce = ui.Size;
}
}
- if (inSizeForReduce2 > inSizeForReduce)
+ if (inSizeForReduce < inSizeForReduce2)
inSizeForReduce = inSizeForReduce2;
RINOK(updateCallback->SetTotal(complexity));
@@ -871,52 +1682,102 @@ HRESULT Update(
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
+ #ifndef _7ZIP_ST
+
CStreamBinder sb;
- RINOK(sb.CreateEvents());
+ if (options.MultiThreadMixer)
+ {
+ RINOK(sb.CreateEvents());
+ }
+
+ #endif
- CThreadDecoder threadDecoder;
- if (!folderRefs.IsEmpty())
+ CThreadDecoder threadDecoder(options.MultiThreadMixer);
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer && thereAreRepacks)
{
#ifdef EXTERNAL_CODECS
threadDecoder.__externalCodecs = __externalCodecs;
#endif
RINOK(threadDecoder.Create());
}
-
- CObjectVector<CSolidGroup> groups;
- for (i = 0; i < kNumGroupsMax; i++)
- groups.AddNew();
+ #endif
{
+ CAnalysis analysis;
+ if (options.AnalysisLevel == 0)
+ {
+ analysis.ParseWav = false;
+ analysis.ParseExe = false;
+ analysis.ParseAll = false;
+ }
+ else
+ {
+ analysis.Callback = opCallback;
+ if (options.AnalysisLevel > 0)
+ {
+ analysis.ParseWav = true;
+ if (options.AnalysisLevel >= 7)
+ {
+ analysis.ParseExe = true;
+ if (options.AnalysisLevel >= 9)
+ analysis.ParseAll = true;
+ }
+ }
+ }
+
// ---------- Split files to groups ----------
bool useFilters = options.UseFilters;
const CCompressionMethodMode &method = *options.Method;
- if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
+
+ if (useFilters)
+ for (i = 0; i < method.Methods.Size(); i++)
+ if (IsFilterMethod(method.Methods[i].Id))
+ {
+ useFilters = false;
+ break;
+ }
+
+ /*
+ if (!method.Bonds.IsEmpty())
useFilters = false;
+ */
+
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
if (!ui.NewData || !ui.HasStream())
continue;
- bool filteredGroup = false;
+
+ CFilterMode2 fm;
if (useFilters)
{
- int dotPos = ui.Name.ReverseFind(L'.');
- if (dotPos >= 0)
- filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1));
+ RINOK(analysis.GetFilterGroup(i, ui, fm));
}
- groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);
+ fm.Encrypted = method.PasswordIsDefined;
+
+ unsigned groupIndex = GetGroup(filters, fm);
+ while (groupIndex >= groups.Size())
+ groups.AddNew();
+ groups[groupIndex].Indices.Add(i);
}
}
+
#ifndef _NO_CRYPTO
CCryptoGetTextPassword *getPasswordSpec = NULL;
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
if (needEncryptedRepack)
{
getPasswordSpec = new CCryptoGetTextPassword;
+ getTextPassword = getPasswordSpec;
+
+ #ifndef _7ZIP_ST
threadDecoder.getTextPassword = getPasswordSpec;
+ #endif
if (options.Method->PasswordIsDefined)
getPasswordSpec->Password = options.Method->Password;
@@ -926,7 +1787,7 @@ HRESULT Update(
return E_NOTIMPL;
CMyComBSTR password;
RINOK(getDecoderPassword->CryptoGetTextPassword(&password));
- if ((BSTR)password)
+ if (password)
getPasswordSpec->Password = password;
}
}
@@ -986,7 +1847,8 @@ HRESULT Update(
{
/* ---------- Write non-AUX dirs and Empty files ---------- */
- CRecordVector<int> emptyRefs;
+ CUIntVector emptyRefs;
+
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
@@ -1003,7 +1865,9 @@ HRESULT Update(
*/
emptyRefs.Add(i);
}
+
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
+
for (i = 0; i < emptyRefs.Size(); i++)
{
const CUpdateItem &ui = updateItems[emptyRefs[i]];
@@ -1030,17 +1894,34 @@ HRESULT Update(
}
}
- unsigned folderRefIndex = 0;
lps->ProgressOffset = 0;
- for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)
{
- const CSolidGroup &group = groups[groupIndex];
+ // ---------- Sort Filters ----------
+
+ FOR_VECTOR (i, filters)
+ {
+ filters[i].GroupIndex = i;
+ }
+ filters.Sort2();
+ }
+
+ for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++)
+ {
+ const CFilterMode2 &filterMode = filters[groupIndex];
CCompressionMethodMode method = *options.Method;
- MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter);
+ HRESULT res = MakeExeMethod(method, filterMode,
+ #ifdef _7ZIP_ST
+ false
+ #else
+ options.MaxFilter && options.MultiThreadMixer
+ #endif
+ );
+
+ RINOK(res);
- if (IsEncryptedGroup(groupIndex))
+ if (filterMode.Encrypted)
{
if (!method.PasswordIsDefined)
{
@@ -1059,83 +1940,260 @@ HRESULT Update(
CEncoder encoder(method);
- for (; folderRefIndex < folderRefs.Size(); folderRefIndex++)
+ // ---------- Repack and copy old solid blocks ----------
+
+ const CSolidGroup &group = groups[filterMode.GroupIndex];
+
+ FOR_VECTOR(folderRefIndex, group.folderRefs)
{
- const CFolderRepack &rep = folderRefs[folderRefIndex];
- if (rep.Group != groupIndex)
- break;
- int folderIndex = rep.FolderIndex;
+ const CFolderRepack &rep = group.folderRefs[folderRefIndex];
+
+ unsigned folderIndex = rep.FolderIndex;
- if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex])
+ CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
+
+ if (rep.NumCopyFiles == numUnpackStreams)
{
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NUpdateNotifyOp::kReplicate));
+
+ // ---------- Copy old solid block ----------
+ {
+ CNum indexInFolder = 0;
+ for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
+ {
+ if (db->Files[fi].HasStream)
+ {
+ indexInFolder++;
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, (UInt32)fi,
+ NUpdateNotifyOp::kReplicate));
+ }
+ }
+ }
+ }
+
UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
RINOK(WriteRange(inStream, archive.SeqStream,
- db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
+ db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
lps->ProgressOffset += packSize;
CFolder &folder = newDatabase.Folders.AddNew();
db->ParseFolderInfo(folderIndex, folder);
CNum startIndex = db->FoStartPackStreamIndex[folderIndex];
- for (unsigned j = 0; j < folder.PackStreams.Size(); j++)
+ FOR_VECTOR(j, folder.PackStreams)
{
newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j));
// newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);
// newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
}
- UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex];
- UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
+ size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];
+ size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
for (; indexStart < indexEnd; indexStart++)
newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]);
}
else
{
+ // ---------- Repack old solid block ----------
+
CBoolVector extractStatuses;
- CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
CNum indexInFolder = 0;
-
+
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NUpdateNotifyOp::kRepack))
+ }
+
+ /* We could reduce data size of decoded folder, if we don't need to repack
+ last files in folder. But the gain in speed is small in most cases.
+ So we unpack full folder. */
+
+ UInt64 sizeToEncode = 0;
+
+ /*
+ UInt64 importantUnpackSize = 0;
+ unsigned numImportantFiles = 0;
+ UInt64 decodeSize = 0;
+ */
+
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
{
bool needExtract = false;
- if (db->Files[fi].HasStream)
+ const CFileItem &file = db->Files[fi];
+
+ if (file.HasStream)
{
indexInFolder++;
int updateIndex = fileIndexToUpdateIndexMap[fi];
if (updateIndex >= 0 && !updateItems[updateIndex].NewData)
needExtract = true;
+ // decodeSize += file.Size;
}
+
extractStatuses.Add(needExtract);
+ if (needExtract)
+ {
+ sizeToEncode += file.Size;
+ /*
+ numImportantFiles = extractStatuses.Size();
+ importantUnpackSize = decodeSize;
+ */
+ }
}
+ // extractStatuses.DeleteFrom(numImportantFiles);
+
unsigned startPackIndex = newDatabase.PackSizes.Size();
UInt64 curUnpackSize;
{
+
CMyComPtr<ISequentialInStream> sbInStream;
+ CRepackStreamBase *repackBase;
+ CFolderInStream2 *FosSpec2 = NULL;
+
+ CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes;
+ CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
{
- CMyComPtr<ISequentialOutStream> sbOutStream;
- sb.CreateStreams(&sbInStream, &sbOutStream);
- sb.ReInit();
- RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));
- }
-
- threadDecoder.InStream = inStream;
- threadDecoder.Folders = (const CFolders *)db;
- threadDecoder.FolderIndex = folderIndex;
- threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);
-
- threadDecoder.Start();
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ repackBase = threadDecoder.FosSpec;
+ CMyComPtr<ISequentialOutStream> sbOutStream;
+ sb.CreateStreams(&sbInStream, &sbOutStream);
+ sb.ReInit();
+
+ threadDecoder.FosSpec->_stream = sbOutStream;
+
+ threadDecoder.InStream = inStream;
+ threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);
+ threadDecoder.Folders = (const CFolders *)db;
+ threadDecoder.FolderIndex = folderIndex;
+
+ // threadDecoder.UnpackSize = importantUnpackSize;
+ // threadDecoder.send_UnpackSize = true;
+ }
+ else
+ #endif
+ {
+ FosSpec2 = new CFolderInStream2;
+ FosSpec2->Init();
+ sbInStream = FosSpec2;
+ repackBase = FosSpec2;
+
+ #ifndef _NO_CRYPTO
+ bool isEncrypted = false;
+ bool passwordIsDefined = false;
+ UString password;
+ #endif
+
+ CMyComPtr<ISequentialInStream> decodedStream;
+ HRESULT res = threadDecoder.Decoder.Decode(
+ EXTERNAL_CODECS_LOC_VARS
+ inStream,
+ db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);,
+ *db, folderIndex,
+ // &importantUnpackSize, // *unpackSize
+ NULL, // *unpackSize : FULL unpack
+
+ NULL, // *outStream
+ NULL, // *compressProgress
+ &decodedStream
+
+ _7Z_DECODER_CRYPRO_VARS
+ #ifndef _7ZIP_ST
+ , false // mtMode
+ , 1 // numThreads
+ #endif
+ );
- RINOK(encoder.Encode(
+ RINOK(res);
+ if (!decodedStream)
+ return E_FAIL;
+
+ FosSpec2->_inStream = decodedStream;
+ }
+
+ repackBase->_db = db;
+ repackBase->_opCallback = opCallback;
+ repackBase->_extractCallback = extractCallback;
+
+ UInt32 startIndex = db->FolderStartFileIndex[folderIndex];
+ RINOK(repackBase->Init(startIndex, &extractStatuses));
+
+ inStreamSizeCountSpec->_db = db;
+ inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses);
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ threadDecoder.Start();
+ }
+ #endif
+ }
+
+
+ HRESULT encodeRes = encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- sbInStream, NULL, &inSizeForReduce,
+ inStreamSizeCount,
+ // NULL,
+ &inSizeForReduce,
newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize,
- archive.SeqStream, newDatabase.PackSizes, progress));
-
- threadDecoder.WaitExecuteFinish();
- }
+ archive.SeqStream, newDatabase.PackSizes, progress);
- RINOK(threadDecoder.Result);
+ if (encodeRes == k_My_HRESULT_CRC_ERROR)
+ return E_FAIL;
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ threadDecoder.WaitExecuteFinish();
+ HRESULT decodeRes = threadDecoder.Result;
+ // if (res == k_My_HRESULT_CRC_ERROR)
+ if (decodeRes == S_FALSE)
+ {
+ if (extractCallback)
+ {
+ RINOK(extractCallback->ReportExtractResult(
+ NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],
+ // NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NExtract::NOperationResult::kDataError));
+ }
+ return E_FAIL;
+ }
+ RINOK(decodeRes);
+ if (encodeRes == S_OK)
+ if (sb.ProcessedSize != sizeToEncode)
+ encodeRes = E_FAIL;
+ }
+ else
+ #endif
+ {
+ if (FosSpec2->Result == S_FALSE)
+ {
+ if (extractCallback)
+ {
+ RINOK(extractCallback->ReportExtractResult(
+ NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ NExtract::NOperationResult::kDataError));
+ }
+ return E_FAIL;
+ }
+ RINOK(FosSpec2->Result);
+ }
+
+ RINOK(encodeRes);
+ RINOK(repackBase->CheckFinishedState());
+
+ if (curUnpackSize != sizeToEncode)
+ return E_FAIL;
+ }
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
lps->OutSize += newDatabase.PackSizes[startPackIndex];
@@ -1144,8 +2202,6 @@ HRESULT Update(
newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);
- CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
-
CNum indexInFolder = 0;
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
{
@@ -1187,6 +2243,9 @@ HRESULT Update(
}
}
+
+ // ---------- Compress files to new solid blocks ----------
+
unsigned numFiles = group.Indices.Size();
if (numFiles == 0)
continue;
@@ -1222,10 +2281,11 @@ HRESULT Update(
for (i = 0; i < numFiles;)
{
UInt64 totalSize = 0;
- int numSubFiles;
- UString prevExtension;
- for (numSubFiles = 0; i + numSubFiles < numFiles &&
- numSubFiles < numSolidFiles; numSubFiles++)
+ unsigned numSubFiles;
+
+ const wchar_t *prevExtension = NULL;
+
+ for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++)
{
const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];
totalSize += ui.Size;
@@ -1233,17 +2293,21 @@ HRESULT Update(
break;
if (options.SolidExtension)
{
- UString ext = ui.GetExtension();
+ int slashPos = ui.Name.ReverseFind_PathSepar();
+ int dotPos = ui.Name.ReverseFind_Dot();
+ const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : dotPos + 1);
if (numSubFiles == 0)
prevExtension = ext;
- else
- if (!ext.IsEqualToNoCase(prevExtension))
- break;
+ else if (!StringsAreEqualNoCase(ext, prevExtension))
+ break;
}
}
+
if (numSubFiles < 1)
numSubFiles = 1;
+ RINOK(lps->SetCur());
+
CFolderInStream *inStreamSpec = new CFolderInStream;
CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
@@ -1252,10 +2316,15 @@ HRESULT Update(
UInt64 curFolderUnpackSize;
RINOK(encoder.Encode(
EXTERNAL_CODECS_LOC_VARS
- solidInStream, NULL, &inSizeForReduce,
+ solidInStream,
+ // NULL,
+ &inSizeForReduce,
newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize,
archive.SeqStream, newDatabase.PackSizes, progress));
+ if (!inStreamSpec->WasFinished())
+ return E_FAIL;
+
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
lps->OutSize += newDatabase.PackSizes[startPackIndex];
@@ -1263,9 +2332,11 @@ HRESULT Update(
// for ()
// newDatabase.PackCRCsDefined.Add(false);
// newDatabase.PackCRCs.Add(0);
-
+
CNum numUnpackStreams = 0;
- for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
+ UInt64 skippedSize = 0;
+
+ for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++)
{
const CUpdateItem &ui = updateItems[indices[i + subIndex]];
CFileItem file;
@@ -1290,12 +2361,15 @@ HRESULT Update(
*/
if (!inStreamSpec->Processed[subIndex])
{
+ skippedSize += ui.Size;
continue;
- // file.Name += L".locked";
+ // file.Name.AddAscii(".locked");
}
file.Crc = inStreamSpec->CRCs[subIndex];
file.Size = inStreamSpec->Sizes[subIndex];
+
+ // if (file.Size >= 0) // test purposes
if (file.Size != 0)
{
file.CrcDefined = true;
@@ -1307,6 +2381,7 @@ HRESULT Update(
file.CrcDefined = false;
file.HasStream = false;
}
+
/*
file.Parent = ui.ParentFolderIndex;
if (ui.TreeFolderIndex >= 0)
@@ -1316,20 +2391,23 @@ HRESULT Update(
*/
newDatabase.AddFile(file, file2, name);
}
+
// numUnpackStreams = 0 is very bad case for locked files
// v3.13 doesn't understand it.
newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);
i += numSubFiles;
+
+ if (skippedSize != 0 && complexity >= skippedSize)
+ {
+ complexity -= skippedSize;
+ RINOK(updateCallback->SetTotal(complexity));
+ }
}
}
- if (folderRefIndex != folderRefs.Size())
- return E_FAIL;
-
RINOK(lps->SetCur());
/*
- folderRefs.ClearAndFree();
fileIndexToUpdateIndexMap.ClearAndFree();
groups.ClearAndFree();
*/
@@ -1350,13 +2428,18 @@ HRESULT Update(
{
const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];
size_t size = buf.GetCapacity();
- memcpy(newDatabase.SecureBuf + pos, buf, size);
+ if (size != 0)
+ memcpy(newDatabase.SecureBuf + pos, buf, size);
newDatabase.SecureSizes.Add((UInt32)size);
pos += size;
}
}
*/
newDatabase.ReserveDown();
+
+ if (opCallback)
+ RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader));
+
return S_OK;
}
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
index d00276e0..3986af43 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -65,6 +65,7 @@ struct CUpdateItem
// int SecureIndex; // 0 means (no_security)
bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }
+ // bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes
CUpdateItem():
// ParentSortIndex(-1),
@@ -77,18 +78,19 @@ struct CUpdateItem
MTimeDefined(false)
// SecureIndex(0)
{}
- void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };
+ void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }
- int GetExtensionPos() const;
- UString GetExtension() const;
+ // unsigned GetExtensionPos() const;
+ // UString GetExtension() const;
};
struct CUpdateOptions
{
const CCompressionMethodMode *Method;
const CCompressionMethodMode *HeaderMethod;
- bool UseFilters;
- bool MaxFilter;
+ bool UseFilters; // use additional filters for some files
+ bool MaxFilter; // use BCJ2 filter instead of BCJ
+ int AnalysisLevel;
CHeaderOptions HeaderOptions;
@@ -96,7 +98,20 @@ struct CUpdateOptions
UInt64 NumSolidBytes;
bool SolidExtension;
bool RemoveSfxBlock;
- bool VolumeMode;
+ bool MultiThreadMixer;
+
+ CUpdateOptions():
+ Method(NULL),
+ HeaderMethod(NULL),
+ UseFilters(false),
+ MaxFilter(false),
+ AnalysisLevel(-1),
+ NumSolidFiles((UInt64)(Int64)(-1)),
+ NumSolidBytes((UInt64)(Int64)(-1)),
+ SolidExtension(false),
+ RemoveSfxBlock(false),
+ MultiThreadMixer(true)
+ {}
};
HRESULT Update(
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp
index 96656733..d5a111e9 100644
--- a/CPP/7zip/Archive/ApmHandler.cpp
+++ b/CPP/7zip/Archive/ApmHandler.cpp
@@ -376,15 +376,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { kSig0, kSig1 };
-static CArcInfo g_ArcInfo =
- { "APM", "apm", 0, 0xD4,
- 2, { kSig0, kSig1 },
+REGISTER_ARC_I(
+ "APM", "apm", 0, 0xD4,
+ k_Signature,
0,
0,
- CreateArc, NULL, IsArc_Apm };
-
-REGISTER_ARC(Apm)
+ IsArc_Apm)
}}
diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp
index b7dcda85..1eec728f 100644
--- a/CPP/7zip/Archive/ArHandler.cpp
+++ b/CPP/7zip/Archive/ArHandler.cpp
@@ -77,7 +77,7 @@ enum EType
kType_Lib
};
-static const char *k_TypeExtionsions[] =
+static const char * const k_TypeExtionsions[] =
{
"ar"
, "a"
@@ -121,7 +121,7 @@ struct CItem
int SameNameIndex;
CItem(): TextFileIndex(-1), SameNameIndex(-1) {}
- UInt64 GetDataPos() const { return HeaderPos + HeaderSize; };
+ UInt64 GetDataPos() const { return HeaderPos + HeaderSize; }
};
class CInArchive
@@ -257,10 +257,9 @@ HRESULT CInArchive::GetNextItem(CItem &item, bool &filled)
{
SubType = kSubType_BSD;
size_t processedSize = longNameLen;
- char *s = item.Name.GetBuffer(longNameLen);
+ char *s = item.Name.GetBuf(longNameLen);
HRESULT res = ReadStream(m_Stream, s, &processedSize);
- s[longNameLen] = 0;
- item.Name.ReleaseBuffer();
+ item.Name.ReleaseBuf_CalcLen(longNameLen);
RINOK(res);
if (processedSize != longNameLen)
return S_OK;
@@ -683,11 +682,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
case kpidPhySize: prop = _phySize; break;
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
- case kpidExtension: prop = k_TypeExtionsions[_type]; break;
+ case kpidExtension: prop = k_TypeExtionsions[(unsigned)_type]; break;
case kpidShortComment:
case kpidSubType:
{
- AString s = k_TypeExtionsions[_type];
+ AString s = k_TypeExtionsions[(unsigned)_type];
if (_subType == kSubType_BSD)
s += ":BSD";
prop = s;
@@ -724,7 +723,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidSize:
case kpidPackSize:
if (item.TextFileIndex >= 0)
- prop = (UInt64)_libFiles[item.TextFileIndex].Len();
+ prop = (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len();
else
prop = item.Size;
break;
@@ -766,7 +765,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CItem &item = _items[allFilesMode ? i : indices[i]];
totalSize +=
(item.TextFileIndex >= 0) ?
- (UInt64)_libFiles[item.TextFileIndex].Len() : item.Size;
+ (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;
}
extractCallback->SetTotal(totalSize);
@@ -795,7 +794,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
currentTotalSize += (item.TextFileIndex >= 0) ?
- (UInt64)_libFiles[item.TextFileIndex].Len() : item.Size;
+ (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;
if (!testMode && !realOutStream)
continue;
@@ -808,7 +807,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool isOk = true;
if (item.TextFileIndex >= 0)
{
- const AString &f = _libFiles[item.TextFileIndex];
+ const AString &f = _libFiles[(unsigned)item.TextFileIndex];
if (realOutStream)
RINOK(WriteStream(realOutStream, f, f.Len()));
}
@@ -834,8 +833,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
const CItem &item = _items[index];
if (item.TextFileIndex >= 0)
{
- const AString &f = _libFiles[item.TextFileIndex];
- Create_BufInStream_WithNewBuf((const void *)(const char *)f, f.Len(), stream);
+ const AString &f = _libFiles[(unsigned)item.TextFileIndex];
+ Create_BufInStream_WithNewBuffer((const void *)(const char *)f, f.Len(), stream);
return S_OK;
}
else
@@ -843,15 +842,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Ar", "ar a deb lib", 0, 0xEC,
- kSignatureLen, SIGNATURE,
+REGISTER_ARC_I(
+ "Ar", "ar a deb lib", 0, 0xEC,
+ kSignature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Ar)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def
index 55b530b2..145516d7 100644
--- a/CPP/7zip/Archive/Archive.def
+++ b/CPP/7zip/Archive/Archive.def
@@ -1,6 +1,12 @@
EXPORTS
CreateObject PRIVATE
+
GetHandlerProperty PRIVATE
GetNumberOfFormats PRIVATE
GetHandlerProperty2 PRIVATE
- CreateObject PRIVATE
+ GetIsArc PRIVATE
+
+ SetCodecs PRIVATE
+
+ SetLargePageMode PRIVATE
+ SetCaseSensitive PRIVATE
diff --git a/CPP/7zip/Archive/Archive2.def b/CPP/7zip/Archive/Archive2.def
index 66feb41d..c7582742 100644
--- a/CPP/7zip/Archive/Archive2.def
+++ b/CPP/7zip/Archive/Archive2.def
@@ -1,11 +1,19 @@
EXPORTS
CreateObject PRIVATE
+
GetHandlerProperty PRIVATE
GetNumberOfFormats PRIVATE
GetHandlerProperty2 PRIVATE
+ GetIsArc PRIVATE
+
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE
+ CreateDecoder PRIVATE
+ CreateEncoder PRIVATE
+
GetHashers PRIVATE
+
+ SetCodecs PRIVATE
+
SetLargePageMode PRIVATE
SetCaseSensitive PRIVATE
- GetIsArc PRIVATE \ No newline at end of file
diff --git a/CPP/7zip/Archive/ArchiveExports.cpp b/CPP/7zip/Archive/ArchiveExports.cpp
index 0a520413..28e9946d 100644
--- a/CPP/7zip/Archive/ArchiveExports.cpp
+++ b/CPP/7zip/Archive/ArchiveExports.cpp
@@ -22,17 +22,19 @@ void RegisterArc(const CArcInfo *arcInfo) throw()
const char *p = arcInfo->Name;
if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
g_DefaultArcIndex = g_NumArcs;
- g_Arcs[g_NumArcs] = arcInfo;
- g_NumArcs++;
+ g_Arcs[g_NumArcs++] = arcInfo;
}
}
DEFINE_GUID(CLSID_CArchiveHandler,
-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
+ k_7zip_GUID_Data1,
+ k_7zip_GUID_Data2,
+ k_7zip_GUID_Data3_Common,
+ 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
-static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value)
+static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)
{
if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
value->vt = VT_BSTR;
@@ -41,18 +43,18 @@ static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *v
static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
{
- return SetPropString((const char *)&guid, sizeof(GUID), value);
+ return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
}
-int FindFormatCalssId(const GUID *clsID)
+int FindFormatCalssId(const GUID *clsid)
{
- GUID cls = *clsID;
+ GUID cls = *clsid;
CLS_ARC_ID_ITEM(cls) = 0;
if (cls != CLSID_CArchiveHandler)
return -1;
- Byte id = CLS_ARC_ID_ITEM(*clsID);
+ Byte id = CLS_ARC_ID_ITEM(*clsid);
for (unsigned i = 0; i < g_NumArcs; i++)
- if (g_Arcs[i]->ClassId == id)
+ if (g_Arcs[i]->Id == id)
return (int)i;
return -1;
}
@@ -101,7 +103,7 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
case NArchive::NHandlerPropID::kClassID:
{
GUID clsId = CLSID_CArchiveHandler;
- CLS_ARC_ID_ITEM(clsId) = arc.ClassId;
+ CLS_ARC_ID_ITEM(clsId) = arc.Id;
return SetPropGUID(clsId, value);
}
case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
@@ -115,12 +117,12 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
// case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
case NArchive::NHandlerPropID::kSignature:
- if (!arc.IsMultiSignature())
- return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
+ if (arc.SignatureSize != 0 && !arc.IsMultiSignature())
+ return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
break;
case NArchive::NHandlerPropID::kMultiSignature:
- if (arc.IsMultiSignature())
- return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
+ if (arc.SignatureSize != 0 && arc.IsMultiSignature())
+ return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
break;
}
prop.Detach(value);
diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp
index 737b8fc9..90819753 100644
--- a/CPP/7zip/Archive/ArjHandler.cpp
+++ b/CPP/7zip/Archive/ArjHandler.cpp
@@ -17,13 +17,180 @@
#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
-#include "../Compress/ArjDecoder1.h"
-#include "../Compress/ArjDecoder2.h"
#include "../Compress/CopyCoder.h"
+#include "../Compress/LzhDecoder.h"
#include "Common/ItemNameUtils.h"
#include "Common/OutStreamWithCRC.h"
+namespace NCompress {
+namespace NArj {
+namespace NDecoder {
+
+static const unsigned kMatchMinLen = 3;
+
+static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14)
+
+class CCoder:
+ public ICompressCoder,
+ public CMyUnknownImp
+{
+ CLzOutWindow _outWindow;
+ NBitm::CDecoder<CInBuffer> _inBitStream;
+
+ class CCoderReleaser
+ {
+ CCoder *_coder;
+ public:
+ CCoderReleaser(CCoder *coder): _coder(coder) {}
+ void Disable() { _coder = NULL; }
+ ~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); }
+ };
+ friend class CCoderReleaser;
+
+ HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress);
+public:
+ MY_UNKNOWN_IMP
+
+ bool FinishMode;
+ CCoder(): FinishMode(false) {}
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }
+};
+
+HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
+{
+ const UInt32 kStep = 1 << 20;
+ UInt64 next = 0;
+ if (rem > kStep && progress)
+ next = rem - kStep;
+
+ while (rem != 0)
+ {
+ if (rem <= next)
+ {
+ if (_inBitStream.ExtraBitsWereRead())
+ return S_FALSE;
+
+ UInt64 packSize = _inBitStream.GetProcessedSize();
+ UInt64 pos = _outWindow.GetProcessedSize();
+ RINOK(progress->SetRatioInfo(&packSize, &pos));
+ next = 0;
+ if (rem > kStep)
+ next = rem - kStep;
+ }
+
+ UInt32 len;
+
+ {
+ const unsigned kNumBits = 7 + 7;
+ UInt32 val = _inBitStream.GetValue(kNumBits);
+
+ if ((val & (1 << (kNumBits - 1))) == 0)
+ {
+ _outWindow.PutByte((Byte)(val >> 5));
+ _inBitStream.MovePos(1 + 8);
+ rem--;
+ continue;
+ }
+
+ UInt32 mask = 1 << (kNumBits - 2);
+ unsigned w;
+
+ for (w = 1; w < 7; w++, mask >>= 1)
+ if ((val & mask) == 0)
+ break;
+
+ unsigned readBits = (w != 7 ? 1 : 0);
+ readBits += w + w;
+ len = (1 << w) - 1 + kMatchMinLen - 1 +
+ (((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
+ _inBitStream.MovePos(readBits);
+ }
+
+ {
+ const unsigned kNumBits = 4 + 13;
+ UInt32 val = _inBitStream.GetValue(kNumBits);
+
+ unsigned readBits = 1;
+ unsigned w;
+
+ if ((val & ((UInt32)1 << 16)) == 0) w = 9;
+ else if ((val & ((UInt32)1 << 15)) == 0) w = 10;
+ else if ((val & ((UInt32)1 << 14)) == 0) w = 11;
+ else if ((val & ((UInt32)1 << 13)) == 0) w = 12;
+ else { w = 13; readBits = 0; }
+
+ readBits += w + w - 9;
+
+ UInt32 dist = ((UInt32)1 << w) - (1 << 9) +
+ (((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
+ _inBitStream.MovePos(readBits);
+
+ if (len > rem)
+ len = (UInt32)rem;
+
+ if (!_outWindow.CopyBlock(dist, len))
+ return S_FALSE;
+ rem -= len;
+ }
+ }
+
+ if (FinishMode)
+ {
+ if (_inBitStream.ReadAlignBits() != 0)
+ return S_FALSE;
+ }
+
+ if (_inBitStream.ExtraBitsWereRead())
+ return S_FALSE;
+
+ return S_OK;
+}
+
+
+
+STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ try
+ {
+ if (!outSize)
+ return E_INVALIDARG;
+
+ if (!_outWindow.Create(kWindowSize))
+ return E_OUTOFMEMORY;
+ if (!_inBitStream.Create(1 << 17))
+ return E_OUTOFMEMORY;
+
+ _outWindow.SetStream(outStream);
+ _outWindow.Init(false);
+ _inBitStream.SetStream(inStream);
+ _inBitStream.Init();
+
+ CCoderReleaser coderReleaser(this);
+ HRESULT res;
+ {
+ res = CodeReal(*outSize, progress);
+ if (res != S_OK)
+ return res;
+ }
+
+ coderReleaser.Disable();
+ return _outWindow.Flush();
+ }
+ catch(const CInBufferException &e) { return e.ErrorCode; }
+ catch(const CLzOutWindowException &e) { return e.ErrorCode; }
+ catch(...) { return S_FALSE; }
+}
+
+}}}
+
+
+
+
using namespace NWindows;
#define Get16(p) GetUi16(p)
@@ -95,7 +262,7 @@ namespace NHostOS
};
}
-static const char *kHostOS[] =
+static const char * const kHostOS[] =
{
"MSDOS"
, "PRIMOS"
@@ -164,10 +331,10 @@ API_FUNC_static_IsArc IsArc_Arj(const Byte *p, size_t size)
static HRESULT ReadString(const Byte *p, unsigned &size, AString &res)
{
- for (unsigned i = 0; i < size;)
+ unsigned num = size;
+ for (unsigned i = 0; i < num;)
{
- char c = (char)p[i++];
- if (c == 0)
+ if (p[i++] == 0)
{
size = i;
res = (const char *)p;
@@ -656,15 +823,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
const CItem &item = _items[allFilesMode ? i : indices[i]];
totalUnpacked += item.Size;
- totalPacked += item.PackSize;
+ // totalPacked += item.PackSize;
}
extractCallback->SetTotal(totalUnpacked);
totalUnpacked = totalPacked = 0;
UInt64 curUnpacked, curPacked;
- CMyComPtr<ICompressCoder> arj1Decoder;
- CMyComPtr<ICompressCoder> arj2Decoder;
+ NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = NULL;
+ CMyComPtr<ICompressCoder> lzhDecoder;
+
+ NCompress::NArj::NDecoder::CCoder *arjDecoderSpec = NULL;
+ CMyComPtr<ICompressCoder> arjDecoder;
+
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
@@ -741,22 +912,37 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
case NCompressionMethod::kCompressed1b:
case NCompressionMethod::kCompressed1c:
{
- if (!arj1Decoder)
- arj1Decoder = new NCompress::NArj::NDecoder1::CCoder;
- result = arj1Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
+ if (!lzhDecoder)
+ {
+ lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
+ lzhDecoder = lzhDecoderSpec;
+ }
+ lzhDecoderSpec->FinishMode = true;
+ const UInt32 kHistorySize = 26624;
+ lzhDecoderSpec->SetDictSize(kHistorySize);
+ result = lzhDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
+ if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
+ result = S_FALSE;
break;
}
case NCompressionMethod::kCompressed2:
{
- if (!arj2Decoder)
- arj2Decoder = new NCompress::NArj::NDecoder2::CCoder;
- result = arj2Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
+ if (!arjDecoder)
+ {
+ arjDecoderSpec = new NCompress::NArj::NDecoder::CCoder;
+ arjDecoder = arjDecoderSpec;
+ }
+ arjDecoderSpec->FinishMode = true;
+ result = arjDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
+ if (result == S_OK && arjDecoderSpec->GetInputProcessedSize() != item.PackSize)
+ result = S_FALSE;
break;
}
default:
opRes = NExtract::NOperationResult::kUnsupportedMethod;
}
}
+
if (opRes == NExtract::NOperationResult::kOK)
{
if (result == S_FALSE)
@@ -769,23 +955,23 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
NExtract::NOperationResult::kCRCError;
}
}
+
outStream.Release();
RINOK(extractCallback->SetOperationResult(opRes));
}
}
+
return S_OK;
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { kSig0, kSig1 };
-static CArcInfo g_ArcInfo =
- { "Arj", "arj", 0, 4,
- 2, { kSig0, kSig1 },
+REGISTER_ARC_I(
+ "Arj", "arj", 0, 4,
+ k_Signature,
0,
0,
- CreateArc, NULL, IsArc_Arj };
-
-REGISTER_ARC(Arj)
+ IsArc_Arj)
}}
diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp
index a49e8293..d1d5f727 100644
--- a/CPP/7zip/Archive/Bz2Handler.cpp
+++ b/CPP/7zip/Archive/Bz2Handler.cpp
@@ -56,7 +56,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
CHandler() { }
};
@@ -367,6 +367,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
+ COM_TRY_BEGIN
+
if (numItems != 1)
return E_INVALIDARG;
@@ -381,13 +383,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
- if (prop.vt == VT_BOOL)
- {
- if (prop.boolVal != VARIANT_FALSE)
+ if (prop.vt != VT_EMPTY)
+ if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
return E_INVALIDARG;
- }
- else if (prop.vt != VT_EMPTY)
- return E_INVALIDARG;
}
}
@@ -403,28 +401,43 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
return UpdateArchive(size, outStream, _props, updateCallback);
}
+
if (indexInArchive != 0)
return E_INVALIDARG;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, 0,
+ NUpdateNotifyOp::kReplicate))
+ }
+
if (_stream)
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
- return NCompress::CopyStream(_stream, outStream, NULL);
+
+ return NCompress::CopyStream(_stream, outStream, progress);
+
+ COM_TRY_END
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
return _props.SetProperties(names, values, numProps);
}
-IMP_CreateArcIn
-IMP_CreateArcOut
+static const Byte k_Signature[] = { 'B', 'Z', 'h' };
-static CArcInfo g_ArcInfo =
- { "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
- 3, { 'B', 'Z', 'h' },
+REGISTER_ARC_IO(
+ "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
+ k_Signature,
0,
NArcInfoFlags::kKeepName,
- REF_CreateArc_Pair, IsArc_BZip2 };
-
-REGISTER_ARC(BZip2)
+ IsArc_BZip2)
}}
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
index cebec610..625276f3 100644
--- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
@@ -75,11 +75,14 @@ HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- UInt32 rem = _size - _pos;
- if (size > rem)
- size = rem;
- memcpy(data, _buf + _pos, size);
- _pos += size;
+ if (size != 0)
+ {
+ UInt32 rem = _size - _pos;
+ if (size > rem)
+ size = rem;
+ memcpy(data, _buf + _pos, size);
+ _pos += size;
+ }
if (processedSize)
*processedSize = size;
return S_OK;
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
index 22bc93a0..4235ec34 100644
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -71,7 +71,7 @@ static const Byte kArcProps[] =
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
-static const char *kMethods[] =
+static const char * const kMethods[] =
{
"None"
, "MSZip"
@@ -124,17 +124,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
}
}
+
AString s;
+
for (unsigned i = 0; i < kNumMethodsMax; i++)
{
if ((mask & (1 << i)) == 0)
continue;
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
char temp[kMethodNameBufSize];
SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]);
s += temp;
}
+
prop = s;
break;
}
@@ -466,8 +468,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
return result;
if (!_errorMessage.IsEmpty())
- _errorMessage += L"\n";
- _errorMessage += L"Can't open volume: ";
+ _errorMessage.Add_LF();
+ _errorMessage.AddAscii("Can't open volume: ");
_errorMessage += fullName;
if (prevChecked)
@@ -528,7 +530,7 @@ private:
Byte *TempBuf;
UInt32 TempBufSize;
- int NumIdenticalFiles;
+ unsigned NumIdenticalFiles;
bool TempBufMode;
UInt32 m_BufStartFolderOffset;
@@ -619,8 +621,9 @@ HRESULT CFolderOutStream::OpenFile()
{
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
- int numExtractItems = 0;
+ unsigned numExtractItems = 0;
unsigned curIndex;
+
for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)
{
const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];
@@ -632,10 +635,12 @@ HRESULT CFolderOutStream::OpenFile()
if (!m_TestMode && (*m_ExtractStatuses)[curIndex])
numExtractItems++;
}
+
NumIdenticalFiles = (curIndex - m_CurrentIndex);
if (NumIdenticalFiles == 0)
NumIdenticalFiles = 1;
TempBufMode = false;
+
if (numExtractItems > 1)
{
if (!TempBuf || item.Size > TempBufSize)
@@ -699,7 +704,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
COM_TRY_BEGIN
UInt32 realProcessed = 0;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
while (size != 0)
{
@@ -707,7 +712,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size);
HRESULT res = S_OK;
- if (numBytesToWrite > 0)
+ if (numBytesToWrite != 0)
{
if (!isOK)
m_IsOk = false;
@@ -721,7 +726,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);
}
realProcessed += numBytesToWrite;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = realProcessed;
data = (const void *)((const Byte *)data + numBytesToWrite);
size -= numBytesToWrite;
@@ -773,7 +778,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);
realProcessed += numBytesToWrite;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = realProcessed;
data = (const void *)((const Byte *)data + numBytesToWrite);
size -= numBytesToWrite;
@@ -799,24 +804,24 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
HRESULT CFolderOutStream::FlushCorrupted()
{
- const UInt32 kBufferSize = (1 << 10);
- Byte buffer[kBufferSize];
- for (int i = 0; i < kBufferSize; i++)
- buffer[i] = 0;
+ const unsigned kBufSize = (1 << 10);
+ Byte buf[kBufSize];
+ for (unsigned i = 0; i < kBufSize; i++)
+ buf[i] = 0;
for (;;)
{
UInt64 remain = GetRemain();
if (remain == 0)
return S_OK;
- UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize);
+ UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize);
UInt32 processedSizeLocal = 0;
- RINOK(Write2(buffer, size, &processedSizeLocal, false));
+ RINOK(Write2(buf, size, &processedSizeLocal, false));
}
}
HRESULT CFolderOutStream::Unsupported()
{
- while(m_CurrentIndex < m_ExtractStatuses->Size())
+ while (m_CurrentIndex < m_ExtractStatuses->Size())
{
HRESULT result = OpenFile();
if (result != S_FALSE && result != S_OK)
@@ -844,9 +849,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt32 i;
int lastFolder = -2;
UInt64 lastFolderSize = 0;
- for(i = 0; i < numItems; i++)
+
+ for (i = 0; i < numItems; i++)
{
- int index = allFilesMode ? i : indices[i];
+ unsigned index = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[index];
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
@@ -857,6 +863,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lastFolder = folderIndex;
lastFolderSize = item.GetEndOffset();
}
+
totalUnPacked += lastFolderSize;
extractCallback->SetTotal(totalUnPacked);
@@ -887,9 +894,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return E_OUTOFMEMORY;
CRecordVector<bool> extractStatuses;
- for(i = 0; i < numItems;)
+
+ for (i = 0; i < numItems;)
{
- int index = allFilesMode ? i : indices[i];
+ unsigned index = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[index];
const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
@@ -909,7 +917,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue;
}
+
int folderIndex = m_Database.GetFolderIndex(&mvItem);
+
if (folderIndex < 0)
{
// If we need previous archive
@@ -923,17 +933,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
continue;
}
- int startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
- int startIndex = startIndex2;
+
+ unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
+ unsigned startIndex = startIndex2;
extractStatuses.Clear();
for (; startIndex < index; startIndex++)
extractStatuses.Add(false);
extractStatuses.Add(true);
startIndex++;
UInt64 curUnpack = item.GetEndOffset();
+
for (; i < numItems; i++)
{
- int indexNext = allFilesMode ? i : indices[i];
+ unsigned indexNext = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[indexNext];
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
@@ -963,6 +975,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
cabBlockInStreamSpec->MsZip = false;
HRESULT res = S_OK;
+
switch (folder.GetMethod())
{
case NHeader::NMethod::kNone:
@@ -1009,7 +1022,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
bool keepHistory = false;
bool keepInputBuffer = false;
- for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;)
+
+ for (UInt32 bl = 0; cabFolderOutStream->GetRemain() != 0;)
{
if (volIndex >= m_Database.Volumes.Size())
{
@@ -1019,19 +1033,32 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CDatabaseEx &db = m_Database.Volumes[volIndex];
const CFolder &folder = db.Folders[locFolderIndex];
- if (f == 0)
+
+ if (bl == 0)
{
cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize();
RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL));
}
- if (f == folder.NumDataBlocks)
+
+ if (bl == folder.NumDataBlocks)
{
- volIndex++;
- locFolderIndex = 0;
- f = 0;
- continue;
+ /*
+ CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit.
+ But there are some big CAB archives from MS that contain more
+ than (0xFFFF) CFDATA blocks in folder.
+ Old cab extracting software can show error (or ask next volume)
+ but cab extracting library in new Windows ignores this error.
+ 15.00 : We also try to ignore such error, if archive is not multi-volume.
+ */
+ if (m_Database.Volumes.Size() > 1)
+ {
+ volIndex++;
+ locFolderIndex = 0;
+ bl = 0;
+ continue;
+ }
}
- f++;
+ bl++;
if (!keepInputBuffer)
cabBlockInStreamSpec->InitForNewBlock();
@@ -1059,7 +1086,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
unpackRemain = kBlockSizeMax;
if (unpackRemain > unpackSize)
unpackRemain = unpackSize;
-
+
switch (folder.GetMethod())
{
case NHeader::NMethod::kNone:
@@ -1092,14 +1119,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
break;
}
+
if (res != S_OK)
{
if (res != S_FALSE)
RINOK(res);
break;
}
+
keepHistory = true;
}
+
if (res == S_OK)
{
RINOK(cabFolderOutStream->WriteEmptyFiles());
@@ -1111,6 +1141,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
totalUnPacked += curUnpack;
}
+
return S_OK;
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Cab/CabHeader.cpp b/CPP/7zip/Archive/Cab/CabHeader.cpp
index 0cba1b0b..370a2f1e 100644
--- a/CPP/7zip/Archive/Cab/CabHeader.cpp
+++ b/CPP/7zip/Archive/Cab/CabHeader.cpp
@@ -8,8 +8,8 @@ namespace NArchive {
namespace NCab {
namespace NHeader {
-Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
+const Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
-// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; }; } g_SignatureInitializer;
+// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; } } g_SignatureInitializer;
}}}
diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h
index 9ec0760a..2f2bd109 100644
--- a/CPP/7zip/Archive/Cab/CabHeader.h
+++ b/CPP/7zip/Archive/Cab/CabHeader.h
@@ -1,4 +1,4 @@
-// Archive/Cab/Header.h
+// Archive/CabHeader.h
#ifndef __ARCHIVE_CAB_HEADER_H
#define __ARCHIVE_CAB_HEADER_H
@@ -10,7 +10,7 @@ namespace NCab {
namespace NHeader {
const unsigned kMarkerSize = 8;
-extern Byte kMarker[kMarkerSize];
+extern const Byte kMarker[kMarkerSize];
namespace NArcFlags
{
diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp
index c499f05f..a72e05f7 100644
--- a/CPP/7zip/Archive/Cab/CabIn.cpp
+++ b/CPP/7zip/Archive/Cab/CabIn.cpp
@@ -40,8 +40,7 @@ void CInArchive::ReadName(AString &s)
throw CUnexpectedEndException();
if (b == 0)
{
- memcpy(s.GetBuffer((unsigned)i), _tempBuf, i);
- s.ReleaseBuffer((unsigned)i);
+ s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i);
return;
}
if (_tempBuf.Size() == i)
diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h
index 4fdab77b..baeeb7b2 100644
--- a/CPP/7zip/Archive/Cab/CabIn.h
+++ b/CPP/7zip/Archive/Cab/CabIn.h
@@ -17,6 +17,12 @@ struct COtherArc
{
AString FileName;
AString DiskName;
+
+ void Clear()
+ {
+ FileName.Empty();
+ DiskName.Empty();
+ }
};
struct CArchInfo
@@ -43,7 +49,9 @@ struct CArchInfo
CArchInfo()
{
- Clear();
+ PerCabinet_AreaSize = 0;
+ PerFolder_AreaSize = 0;
+ PerDataBlock_AreaSize = 0;
}
void Clear()
@@ -51,6 +59,9 @@ struct CArchInfo
PerCabinet_AreaSize = 0;
PerFolder_AreaSize = 0;
PerDataBlock_AreaSize = 0;
+
+ PrevArc.Clear();
+ NextArc.Clear();
}
};
diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h
index eda62bda..9b513202 100644
--- a/CPP/7zip/Archive/Cab/CabItem.h
+++ b/CPP/7zip/Archive/Cab/CabItem.h
@@ -51,7 +51,7 @@ struct CItem
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
}
- int GetFolderIndex(int numFolders) const
+ int GetFolderIndex(unsigned numFolders) const
{
if (ContinuedFromPrev())
return 0;
diff --git a/CPP/7zip/Archive/Cab/CabRegister.cpp b/CPP/7zip/Archive/Cab/CabRegister.cpp
index acad4c4a..0b5cc93a 100644
--- a/CPP/7zip/Archive/Cab/CabRegister.cpp
+++ b/CPP/7zip/Archive/Cab/CabRegister.cpp
@@ -9,15 +9,11 @@
namespace NArchive {
namespace NCab {
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Cab", "cab", 0, 8,
- 8, { 'M', 'S', 'C', 'F', 0, 0, 0, 0 },
+REGISTER_ARC_I(
+ "Cab", "cab", 0, 8,
+ NHeader::kMarker,
0,
NArcInfoFlags::kFindSignature,
- CreateArc };
-
-REGISTER_ARC(Cab)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp
index c67ded28..3035ef9e 100644
--- a/CPP/7zip/Archive/Chm/ChmHandler.cpp
+++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp
@@ -123,15 +123,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPath:
{
UString us;
- if (ConvertUTF8ToUnicode(item.Name, us))
+ // if (
+ ConvertUTF8ToUnicode(item.Name, us);
{
if (!m_Database.LowLevel)
{
- if (us.Len() > 1)
- if (us[0] == L'/')
- us.Delete(0);
+ if (us.Len() > 1 && us[0] == L'/')
+ us.Delete(0);
}
- prop = NItemName::GetOSName2(us);
+ NItemName::ConvertToOSName2(us);
+ prop = us;
}
break;
}
@@ -141,7 +142,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
if (!item.IsDir())
if (item.Section == 0)
- prop = L"Copy";
+ prop = "Copy";
else if (item.Section < m_Database.Sections.Size())
prop = m_Database.Sections[(int)item.Section].GetMethodName();
break;
@@ -734,30 +735,30 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
namespace NChm {
-IMP_CreateArcIn_2(CHandler(false))
+static const Byte k_Signature[] = { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 };
-static CArcInfo g_ArcInfo =
- { "Chm", "chm chi chq chw", 0, 0xE9,
- 12, { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 },
+REGISTER_ARC_I_CLS(
+ CHandler(false),
+ "Chm", "chm chi chq chw", 0, 0xE9,
+ k_Signature,
0,
0,
- CreateArc };
+ NULL)
-REGISTER_ARC(Chm)
}
namespace NHxs {
-IMP_CreateArcIn_2(CHandler(true))
+static const Byte k_Signature[] = { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 };
-static CArcInfo g_ArcInfo =
- { "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE,
- 16, { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 },
+REGISTER_ARC_I_CLS(
+ CHandler(true),
+ "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE,
+ k_Signature,
0,
NArcInfoFlags::kFindSignature,
- CreateArc };
+ NULL)
-REGISTER_ARC(Hxs)
}
}}
diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp
index 9b0bb199..e8da227d 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.cpp
+++ b/CPP/7zip/Archive/Chm/ChmIn.cpp
@@ -107,10 +107,10 @@ UString CMethodInfo::GetName() const
UString s;
if (IsLzx())
{
- s = L"LZX:";
- wchar_t temp[16];
+ s.SetFromAscii("LZX:");
+ char temp[16];
ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp);
- s += temp;
+ s.AddAscii(temp);
}
else
{
@@ -147,12 +147,12 @@ UString CSectionInfo::GetMethodName() const
UString temp;
if (ConvertUTF8ToUnicode(Name, temp))
s += temp;
- s += L": ";
+ s.AddAscii(": ");
}
FOR_VECTOR (i, Methods)
{
if (i != 0)
- s += L' ';
+ s.Add_Space();
s += Methods[i].GetName();
}
return s;
@@ -584,9 +584,9 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
AString s;
ConvertUnicodeToUTF8(name, s);
Byte b = ReadByte();
- s += ' ';
+ s.Add_Space();
PrintByte(b, s);
- s += ' ';
+ s.Add_Space();
UInt64 len = ReadEncInt();
// then number of items ?
// then length ?
@@ -641,7 +641,10 @@ static const char *kTransformList = "List";
static AString GetSectionPrefix(const AString &name)
{
- return AString(kStorage) + name + AString("/");
+ AString s = kStorage;
+ s += name;
+ s += '/';
+ return s;
}
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
@@ -721,8 +724,8 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
ReadUString(nameLen, name);
if (ReadUInt16() != 0)
return S_FALSE;
- if (!ConvertUnicodeToUTF8(name, section.Name))
- return S_FALSE;
+ ConvertUnicodeToUTF8(name, section.Name);
+ // if (!ConvertUnicodeToUTF8(name, section.Name)) return S_FALSE;
database.Sections.Add(section);
}
}
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h
index 70764ab9..c4ce83ed 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.h
+++ b/CPP/7zip/Archive/Chm/ChmIn.h
@@ -120,10 +120,10 @@ struct CLzxInfo
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; };
+ 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);
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp
index fc686b94..9cfd40cc 100644
--- a/CPP/7zip/Archive/ComHandler.cpp
+++ b/CPP/7zip/Archive/ComHandler.cpp
@@ -27,8 +27,7 @@ namespace NArchive {
namespace NCom {
#define SIGNATURE { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }
-static const UInt32 kSignatureSize = 8;
-static const Byte kSignature[kSignatureSize] = SIGNATURE;
+static const Byte kSignature[] = SIGNATURE;
enum EType
{
@@ -40,7 +39,7 @@ enum EType
k_Type_Xls,
};
-static const char *kExtensions[] =
+static const char * const kExtensions[] =
{
"compound"
, "msi"
@@ -240,8 +239,8 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did)
return S_OK;
}
-static const char kCharOpenBracket = '[';
-static const char kCharCloseBracket = ']';
+static const wchar_t kCharOpenBracket = L'[';
+static const wchar_t kCharCloseBracket = L']';
static UString CompoundNameToFileName(const UString &s)
{
@@ -263,23 +262,25 @@ static UString CompoundNameToFileName(const UString &s)
return res;
}
-static char g_MsiChars[] =
+static const char k_Msi_Chars[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._";
-static const wchar_t *kMsi_ID = L""; // L"{msi}";
+// static const char *k_Msi_ID = ""; // "{msi}";
+static const wchar_t k_Msi_SpecChar = L'!';
+
+static const unsigned k_Msi_NumBits = 6;
+static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits;
+static const unsigned k_Msi_CharMask = k_Msi_NumChars - 1;
+static const unsigned k_Msi_StartUnicodeChar = 0x3800;
+static const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1);
-static const unsigned kMsiNumBits = 6;
-static const UInt32 kMsiNumChars = 1 << kMsiNumBits;
-static const UInt32 kMsiCharMask = kMsiNumChars - 1;
-static const UInt32 kMsiStartUnicodeChar = 0x3800;
-static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1);
static bool IsMsiName(const Byte *p)
{
UInt32 c = Get16(p);
return
- c >= kMsiStartUnicodeChar &&
- c <= kMsiStartUnicodeChar + kMsiUnicodeRange;
+ c >= k_Msi_StartUnicodeChar &&
+ c <= k_Msi_StartUnicodeChar + k_Msi_UnicodeRange;
}
static bool AreEqualNames(const Byte *rawName, const char *asciiName)
@@ -296,30 +297,32 @@ static bool AreEqualNames(const Byte *rawName, const char *asciiName)
return false;
}
-static bool CompoundMsiNameToFileName(const UString &name, UString &resultName)
+static bool CompoundMsiNameToFileName(const UString &name, UString &res)
{
- resultName.Empty();
+ res.Empty();
for (unsigned i = 0; i < name.Len(); i++)
{
wchar_t c = name[i];
- if (c < kMsiStartUnicodeChar || c > kMsiStartUnicodeChar + kMsiUnicodeRange)
+ if (c < k_Msi_StartUnicodeChar || c > k_Msi_StartUnicodeChar + k_Msi_UnicodeRange)
return false;
+ /*
if (i == 0)
- resultName += kMsi_ID;
- c -= kMsiStartUnicodeChar;
+ res += k_Msi_ID;
+ */
+ c -= k_Msi_StartUnicodeChar;
- UInt32 c0 = c & kMsiCharMask;
- UInt32 c1 = c >> kMsiNumBits;
+ unsigned c0 = (unsigned)c & k_Msi_CharMask;
+ unsigned c1 = (unsigned)c >> k_Msi_NumBits;
- if (c1 <= kMsiNumChars)
+ if (c1 <= k_Msi_NumChars)
{
- resultName += (wchar_t)g_MsiChars[c0];
- if (c1 == kMsiNumChars)
+ res += (wchar_t)(Byte)k_Msi_Chars[c0];
+ if (c1 == k_Msi_NumChars)
break;
- resultName += (wchar_t)g_MsiChars[c1];
+ res += (wchar_t)(Byte)k_Msi_Chars[c1];
}
else
- resultName += L'!';
+ res += k_Msi_SpecChar;
}
return true;
}
@@ -328,6 +331,7 @@ static UString ConvertName(const Byte *p, bool &isMsi)
{
isMsi = false;
UString s;
+
for (unsigned i = 0; i < kNameSizeMax; i += 2)
{
wchar_t c = Get16(p + i);
@@ -335,6 +339,7 @@ static UString ConvertName(const Byte *p, bool &isMsi)
break;
s += c;
}
+
UString msiName;
if (CompoundMsiNameToFileName(s, msiName))
{
@@ -416,7 +421,7 @@ HRESULT CDatabase::Open(IInStream *inStream)
Byte p[kHeaderSize];
PhySize = kHeaderSize;
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
- if (memcmp(p, kSignature, kSignatureSize) != 0)
+ if (memcmp(p, kSignature, ARRAY_SIZE(kSignature)) != 0)
return S_FALSE;
if (Get16(p + 0x1A) > 4) // majorVer
return S_FALSE;
@@ -573,11 +578,14 @@ HRESULT CDatabase::Open(IInStream *inStream)
continue;
bool isMsiName;
UString msiName = ConvertName(item.Name, isMsiName);
- if (isMsiName && msiName.Len() >= 4 &&
- MyStringCompareNoCase(msiName.RightPtr(4), L".cab") == 0)
+ if (isMsiName)
{
- numCabs++;
- MainSubfile = i;
+ if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")
+ || msiName.Len() >= 3 && msiName[0] != k_Msi_SpecChar && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe"))
+ {
+ numCabs++;
+ MainSubfile = i;
+ }
}
}
if (numCabs > 1)
@@ -663,7 +671,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
switch (propID)
{
- case kpidExtension: prop = kExtensions[_db.Type]; break;
+ case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break;
case kpidPhySize: prop = _db.PhySize; break;
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
@@ -861,15 +869,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Compound", "msi msp doc xls ppt", 0, 0xE5,
- kSignatureSize, SIGNATURE,
+REGISTER_ARC_I(
+ "Compound", "msi msp doc xls ppt", 0, 0xE5,
+ kSignature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Com)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
index 13019d1f..41b5805c 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -4,116 +4,1041 @@
#include "CoderMixer2.h"
-namespace NCoderMixer {
+#ifdef USE_MIXER_ST
-CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
- _srcBindInfo(srcBindInfo)
+STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
+ UInt32 realProcessed = 0;
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Read(data, size, &realProcessed);
+ _size += realProcessed;
+ if (size != 0 && realProcessed == 0)
+ _wasFinished = true;
+ if (processedSize)
+ *processedSize = realProcessed;
+ return result;
+}
+
- UInt32 j;
- _srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams);
- DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams);
+STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ _size += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
+}
- for (j = 0; j < NumSrcInStreams; j++)
+STDMETHODIMP COutStreamCalcSize::OutStreamFinish()
+{
+ HRESULT result = S_OK;
+ if (_stream)
{
- _srcInToDestOutMap[j] = 0;
- DestOutToSrcInMap[j] = 0;
+ CMyComPtr<IOutStreamFinish> outStreamFinish;
+ _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish);
+ if (outStreamFinish)
+ result = outStreamFinish->OutStreamFinish();
}
+ return result;
+}
- _srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams);
- _destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams);
+#endif
- for (j = 0; j < _numSrcOutStreams; j++)
+
+
+
+namespace NCoderMixer2 {
+
+static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
+{
+ v.ClearAndSetSize(size);
+ bool *p = &v[0];
+ for (unsigned i = 0; i < size; i++)
+ p[i] = false;
+}
+
+class CBondsChecks
+{
+ CBoolVector _coderUsed;
+
+ bool Init();
+ bool CheckCoder(unsigned coderIndex);
+public:
+ const CBindInfo *BindInfo;
+
+ bool Check();
+};
+
+bool CBondsChecks::CheckCoder(unsigned coderIndex)
+{
+ const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex];
+
+ if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex])
+ return false;
+ _coderUsed[coderIndex] = true;
+
+ UInt32 start = BindInfo->Coder_to_Stream[coderIndex];
+
+ for (unsigned i = 0; i < coder.NumStreams; i++)
{
- _srcOutToDestInMap[j] = 0;
- _destInToSrcOutMap[j] = 0;
+ UInt32 ind = start + i;
+
+ if (BindInfo->IsStream_in_PackStreams(ind))
+ continue;
+
+ int bond = BindInfo->FindBond_for_PackStream(ind);
+ if (bond < 0)
+ return false;
+ if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex))
+ return false;
}
+
+ return true;
+}
+
+bool CBondsChecks::Check()
+{
+ BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size());
+
+ if (!CheckCoder(BindInfo->UnpackCoder))
+ return false;
+
+ FOR_VECTOR(i, _coderUsed)
+ if (!_coderUsed[i])
+ return false;
+
+ return true;
+}
+
+void CBindInfo::ClearMaps()
+{
+ Coder_to_Stream.Clear();
+ Stream_to_Coder.Clear();
+}
- UInt32 destInOffset = 0;
- UInt32 destOutOffset = 0;
- UInt32 srcInOffset = NumSrcInStreams;
- UInt32 srcOutOffset = _numSrcOutStreams;
+bool CBindInfo::CalcMapsAndCheck()
+{
+ ClearMaps();
+
+ UInt32 numStreams = 0;
+
+ if (Coders.Size() == 0)
+ return false;
+ if (Coders.Size() - 1 != Bonds.Size())
+ return false;
- for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)
+ FOR_VECTOR(i, Coders)
{
- const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];
+ Coder_to_Stream.Add(numStreams);
+
+ const CCoderStreamsInfo &c = Coders[i];
+
+ for (unsigned j = 0; j < c.NumStreams; j++)
+ Stream_to_Coder.Add(i);
+
+ numStreams += c.NumStreams;
+ }
+
+ if (numStreams != GetNum_Bonds_and_PackStreams())
+ return false;
+
+ CBondsChecks bc;
+ bc.BindInfo = this;
+ return bc.Check();
+}
+
+
+void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes)
+{
+ if (unpackSize)
+ {
+ UnpackSize = *unpackSize;
+ UnpackSizePointer = &UnpackSize;
+ }
+ else
+ {
+ UnpackSize = 0;
+ UnpackSizePointer = NULL;
+ }
+
+ PackSizes.ClearAndSetSize((unsigned)NumStreams);
+ PackSizePointers.ClearAndSetSize((unsigned)NumStreams);
+
+ for (unsigned i = 0; i < NumStreams; i++)
+ {
+ if (packSizes && packSizes[i])
+ {
+ PackSizes[i] = *(packSizes[i]);
+ PackSizePointers[i] = &PackSizes[i];
+ }
+ else
+ {
+ PackSizes[i] = 0;
+ PackSizePointers[i] = NULL;
+ }
+ }
+}
+
+bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)
+{
+ if (coderIndex == _bi.UnpackCoder)
+ return true;
+
+ int bond = _bi.FindBond_for_UnpackStream(coderIndex);
+ if (bond < 0)
+ throw 20150213;
+
+ /*
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex);
+ */
+ UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex];
+
+ if (!IsFilter_Vector[nextCoder])
+ return false;
+
+ return Is_UnpackSize_Correct_for_Coder(nextCoder);
+}
+
+bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)
+{
+ if (_bi.IsStream_in_PackStreams(streamIndex))
+ return true;
+
+ int bond = _bi.FindBond_for_PackStream(streamIndex);
+ if (bond < 0)
+ throw 20150213;
+
+ UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex;
+
+ if (!IsFilter_Vector[nextCoder])
+ return false;
+
+ return Is_PackSize_Correct_for_Coder(nextCoder);
+}
+
+bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)
+{
+ UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
+ UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
+ for (UInt32 i = 0; i < numStreams; i++)
+ if (!Is_PackSize_Correct_for_Stream(startIndex + i))
+ return false;
+ return true;
+}
+
+bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)
+{
+ if (IsExternal_Vector[coderIndex])
+ return true;
+ UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
+ UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
+ for (UInt32 i = 0; i < numStreams; i++)
+ {
+ UInt32 si = startIndex + i;
+ if (_bi.IsStream_in_PackStreams(si))
+ continue;
+
+ int bond = _bi.FindBond_for_PackStream(si);
+ if (bond < 0)
+ throw 20150213;
+
+ if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex))
+ return true;
+ }
+ return false;
+}
+
+
+
+
+#ifdef USE_MIXER_ST
+
+CMixerST::CMixerST(bool encodeMode):
+ CMixer(encodeMode)
+ {}
+
+CMixerST::~CMixerST() {}
+
+void CMixerST::AddCoder(const CCreatedCoder &cod)
+{
+ IsFilter_Vector.Add(cod.IsFilter);
+ IsExternal_Vector.Add(cod.IsExternal);
+ // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
+ CCoderST &c2 = _coders.AddNew();
+ c2.NumStreams = cod.NumStreams;
+ c2.Coder = cod.Coder;
+ c2.Coder2 = cod.Coder2;
- srcInOffset -= srcCoderInfo.NumInStreams;
- srcOutOffset -= srcCoderInfo.NumOutStreams;
+ /*
+ if (isFilter)
+ {
+ c2.CanRead = true;
+ c2.CanWrite = true;
+ }
+ else
+ */
+ {
+ IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2);
+ {
+ CMyComPtr<ISequentialInStream> s;
+ unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
+ c2.CanRead = (s != NULL);
+ }
+ {
+ CMyComPtr<ISequentialOutStream> s;
+ unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
+ c2.CanWrite = (s != NULL);
+ }
+ }
+}
+
+CCoder &CMixerST::GetCoder(unsigned index)
+{
+ return _coders[index];
+}
+
+void CMixerST::ReInit() {}
+
+HRESULT CMixerST::GetInStream2(
+ ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
+{
+ UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
+
+ if (EncodeMode)
+ {
+ _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
+ if (coderStreamIndex != 0)
+ return E_NOTIMPL;
+ }
+
+ const CCoder &coder = _coders[coderIndex];
+
+ CMyComPtr<ISequentialInStream> seqInStream;
+ coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
+ if (!seqInStream)
+ return E_NOTIMPL;
+
+ UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
+ UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
+
+ bool isSet = false;
+
+ if (numInStreams == 1)
+ {
+ CMyComPtr<ICompressSetInStream> setStream;
+ coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
+ if (setStream)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
+ RINOK(setStream->SetInStream(seqInStream2));
+ isSet = true;
+ }
+ }
+
+ if (!isSet && numInStreams != 0)
+ {
+ CMyComPtr<ICompressSetInStream2> setStream2;
+ coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
+ if (!setStream2)
+ return E_NOTIMPL;
- UInt32 j;
- for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)
+ for (UInt32 i = 0; i < numInStreams; i++)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
+ RINOK(setStream2->SetInStream2(i, seqInStream2));
+ }
+ }
+
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
+}
+
+
+HRESULT CMixerST::GetInStream(
+ ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
+{
+ CMyComPtr<ISequentialInStream> seqInStream;
+
+ {
+ int index = -1;
+ if (EncodeMode)
+ {
+ if (_bi.UnpackCoder == inStreamIndex)
+ index = 0;
+ }
+ else
+ index = _bi.FindStream_in_PackStreams(inStreamIndex);
+
+ if (index >= 0)
+ {
+ seqInStream = inStreams[(unsigned)index];
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
+ }
+ }
+
+ int bond = FindBond_for_Stream(
+ true, // forInputStream
+ inStreamIndex);
+ if (bond < 0)
+ return E_INVALIDARG;
+
+ RINOK(GetInStream2(inStreams, /* inSizes, */
+ _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
+
+ while (_binderStreams.Size() <= (unsigned)bond)
+ _binderStreams.AddNew();
+ CStBinderStream &bs = _binderStreams[bond];
+
+ if (bs.StreamRef || bs.InStreamSpec)
+ return E_NOTIMPL;
+
+ CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
+ bs.StreamRef = spec;
+ bs.InStreamSpec = spec;
+
+ spec->SetStream(seqInStream);
+ spec->Init();
+
+ seqInStream = bs.InStreamSpec;
+
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
+}
+
+
+HRESULT CMixerST::GetOutStream(
+ ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
+ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
+{
+ CMyComPtr<ISequentialOutStream> seqOutStream;
+
+ {
+ int index = -1;
+ if (!EncodeMode)
+ {
+ if (_bi.UnpackCoder == outStreamIndex)
+ index = 0;
+ }
+ else
+ index = _bi.FindStream_in_PackStreams(outStreamIndex);
+
+ if (index >= 0)
+ {
+ seqOutStream = outStreams[(unsigned)index];
+ *outStreamRes = seqOutStream.Detach();
+ return S_OK;
+ }
+ }
+
+ int bond = FindBond_for_Stream(
+ false, // forInputStream
+ outStreamIndex);
+ if (bond < 0)
+ return E_INVALIDARG;
+
+ UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
+
+ UInt32 coderIndex = inStreamIndex;
+ UInt32 coderStreamIndex = 0;
+
+ if (!EncodeMode)
+ _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
+
+ CCoder &coder = _coders[coderIndex];
+
+ /*
+ if (!coder.Coder)
+ return E_NOTIMPL;
+ */
+
+ coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
+ if (!seqOutStream)
+ return E_NOTIMPL;
+
+ UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
+ UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
+
+ bool isSet = false;
+
+ if (numOutStreams == 1)
+ {
+ CMyComPtr<ICompressSetOutStream> setOutStream;
+ coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
+ if (setOutStream)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
+ RINOK(setOutStream->SetOutStream(seqOutStream2));
+ isSet = true;
+ }
+ }
+
+ if (!isSet && numOutStreams != 0)
+ {
+ return E_NOTIMPL;
+ /*
+ CMyComPtr<ICompressSetOutStream2> setStream2;
+ coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
+ if (!setStream2)
+ return E_NOTIMPL;
+ for (UInt32 i = 0; i < numOutStreams; i++)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
+ RINOK(setStream2->SetOutStream2(i, seqOutStream2));
+ }
+ */
+ }
+
+ while (_binderStreams.Size() <= (unsigned)bond)
+ _binderStreams.AddNew();
+ CStBinderStream &bs = _binderStreams[bond];
+
+ if (bs.StreamRef || bs.OutStreamSpec)
+ return E_NOTIMPL;
+
+ COutStreamCalcSize *spec = new COutStreamCalcSize;
+ bs.StreamRef = (ISequentialOutStream *)spec;
+ bs.OutStreamSpec = spec;
+
+ spec->SetStream(seqOutStream);
+ spec->Init();
+
+ seqOutStream = bs.OutStreamSpec;
+
+ *outStreamRes = seqOutStream.Detach();
+ return S_OK;
+}
+
+
+static HRESULT GetError(HRESULT res, HRESULT res2)
+{
+ if (res == res2)
+ return res;
+ if (res == S_OK)
+ return res2;
+ if (res == k_My_HRESULT_WritingWasCut)
+ {
+ if (res2 != S_OK)
+ return res2;
+ }
+ return res;
+}
+
+
+HRESULT CMixerST::FinishStream(UInt32 streamIndex)
+{
+ {
+ int index = -1;
+ if (!EncodeMode)
{
- UInt32 index = srcInOffset + j;
- _srcInToDestOutMap[index] = destOutOffset;
- DestOutToSrcInMap[destOutOffset] = index;
+ if (_bi.UnpackCoder == streamIndex)
+ index = 0;
}
- for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)
+ else
+ index = _bi.FindStream_in_PackStreams(streamIndex);
+
+ if (index >= 0)
+ return S_OK;
+ }
+
+ int bond = FindBond_for_Stream(
+ false, // forInputStream
+ streamIndex);
+ if (bond < 0)
+ return E_INVALIDARG;
+
+ UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
+
+ UInt32 coderIndex = inStreamIndex;
+ UInt32 coderStreamIndex = 0;
+ if (!EncodeMode)
+ _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
+
+ CCoder &coder = _coders[coderIndex];
+ CMyComPtr<IOutStreamFinish> finish;
+ coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);
+ HRESULT res = S_OK;
+ if (finish)
+ {
+ res = finish->OutStreamFinish();
+ }
+ return GetError(res, FinishCoder(coderIndex));
+}
+
+
+HRESULT CMixerST::FinishCoder(UInt32 coderIndex)
+{
+ CCoder &coder = _coders[coderIndex];
+
+ UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
+ UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
+
+ HRESULT res = S_OK;
+ for (unsigned i = 0; i < numOutStreams; i++)
+ res = GetError(res, FinishStream(startIndex + i));
+ return res;
+}
+
+
+void CMixerST::SelectMainCoder(bool useFirst)
+{
+ unsigned ci = _bi.UnpackCoder;
+
+ int firstNonFilter = -1;
+ int firstAllowed = ci;
+
+ for (;;)
+ {
+ const CCoderST &coder = _coders[ci];
+ // break;
+
+ if (ci != _bi.UnpackCoder)
+ if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
+ {
+ firstAllowed = ci;
+ firstNonFilter = -2;
+ }
+
+ if (coder.NumStreams != 1)
+ break;
+
+ UInt32 st = _bi.Coder_to_Stream[ci];
+ if (_bi.IsStream_in_PackStreams(st))
+ break;
+ int bond = _bi.FindBond_for_PackStream(st);
+ if (bond < 0)
+ throw 20150213;
+
+ if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
+ break;
+
+ if (firstNonFilter == -1 && !IsFilter_Vector[ci])
+ firstNonFilter = ci;
+
+ ci = _bi.Bonds[bond].UnpackIndex;
+ }
+
+ if (useFirst)
+ ci = firstAllowed;
+ else if (firstNonFilter >= 0)
+ ci = firstNonFilter;
+
+ MainCoderIndex = ci;
+}
+
+
+HRESULT CMixerST::Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress)
+{
+ _binderStreams.Clear();
+ unsigned ci = MainCoderIndex;
+
+ const CCoder &mainCoder = _coders[MainCoderIndex];
+
+ CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
+ CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
+
+ UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
+ UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
+
+ UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
+ UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
+
+ UInt32 i;
+
+ for (i = 0; i < numInStreams; i++)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
+ seqInStreams.Add(seqInStream);
+ }
+
+ for (i = 0; i < numOutStreams; i++)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream;
+ RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
+ seqOutStreams.Add(seqOutStream);
+ }
+
+ CRecordVector< ISequentialInStream * > seqInStreamsSpec;
+ CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
+
+ for (i = 0; i < numInStreams; i++)
+ seqInStreamsSpec.Add(seqInStreams[i]);
+ for (i = 0; i < numOutStreams; i++)
+ seqOutStreamsSpec.Add(seqOutStreams[i]);
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ if (i == ci)
+ continue;
+
+ CCoder &coder = _coders[i];
+
+ if (EncodeMode)
+ {
+ CMyComPtr<ICompressInitEncoder> initEncoder;
+ coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);
+ if (initEncoder)
+ RINOK(initEncoder->InitEncoder());
+ }
+ else
+ {
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
+ if (setOutStreamSize)
+ RINOK(setOutStreamSize->SetOutStreamSize(
+ EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
+ }
+ }
+
+ const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
+ const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
+
+ HRESULT res;
+ if (mainCoder.Coder)
+ {
+ res = mainCoder.Coder->Code(
+ seqInStreamsSpec[0], seqOutStreamsSpec[0],
+ isSizes2[0], outSizes2[0],
+ progress);
+ }
+ else
+ {
+ res = mainCoder.Coder2->Code(
+ &seqInStreamsSpec.Front(), isSizes2, numInStreams,
+ &seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
+ progress);
+ }
+
+ if (res == k_My_HRESULT_WritingWasCut)
+ res = S_OK;
+
+ if (res == S_OK || res == S_FALSE)
+ {
+ res = GetError(res, FinishCoder(ci));
+ }
+
+ for (i = 0; i < _binderStreams.Size(); i++)
+ {
+ const CStBinderStream &bs = _binderStreams[i];
+ if (bs.InStreamSpec)
+ bs.InStreamSpec->ReleaseStream();
+ else
+ bs.OutStreamSpec->ReleaseStream();
+ }
+
+ if (res == k_My_HRESULT_WritingWasCut)
+ res = S_OK;
+ return res;
+}
+
+
+HRESULT CMixerST::GetMainUnpackStream(
+ ISequentialInStream * const *inStreams,
+ ISequentialInStream **inStreamRes)
+{
+ CMyComPtr<ISequentialInStream> seqInStream;
+
+ RINOK(GetInStream2(inStreams, /* inSizes, */
+ _bi.UnpackCoder, &seqInStream))
+
+ FOR_VECTOR (i, _coders)
+ {
+ CCoder &coder = _coders[i];
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
+ if (setOutStreamSize)
{
- UInt32 index = srcOutOffset + j;
- _srcOutToDestInMap[index] = destInOffset;
- _destInToSrcOutMap[destInOffset] = index;
+ RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
}
}
+
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
}
-void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
+
+UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
{
- destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size());
- destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size());
- destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size());
- destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size());
+ const CStBinderStream &bs = _binderStreams[bondIndex];
+ if (bs.InStreamSpec)
+ return bs.InStreamSpec->GetSize();
+ return bs.OutStreamSpec->GetSize();
+}
+
+#endif
+
+
+
+
+
+
+#ifdef USE_MIXER_MT
+
+
+void CCoderMT::Execute()
+{
+ try
+ {
+ Code(NULL);
+ }
+ catch(...)
+ {
+ Result = E_FAIL;
+ }
+}
+
+void CCoderMT::Code(ICompressProgressInfo *progress)
+{
+ unsigned numInStreams = EncodeMode ? 1 : NumStreams;
+ unsigned numOutStreams = EncodeMode ? NumStreams : 1;
+
+ InStreamPointers.ClearAndReserve(numInStreams);
+ OutStreamPointers.ClearAndReserve(numOutStreams);
unsigned i;
- for (i = _srcBindInfo.Coders.Size(); i != 0;)
+
+ for (i = 0; i < numInStreams; i++)
+ InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
+
+ for (i = 0; i < numOutStreams; i++)
+ OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
+
+ // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
+ /*
+ if (UnpackSizePointer)
+ UnpackSizePointer = &UnpackSize;
+ for (i = 0; i < NumStreams; i++)
+ if (PackSizePointers[i])
+ PackSizePointers[i] = &PackSizes[i];
+ */
+
+ CReleaser releaser(*this);
+
+ if (Coder)
+ Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
+ EncodeMode ? UnpackSizePointer : PackSizePointers[0],
+ EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
+ progress);
+ else
+ Result = Coder2->Code(
+ &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
+ &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
+ progress);
+}
+
+HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
+{
+ CMixer::SetBindInfo(bindInfo);
+
+ _streamBinders.Clear();
+ FOR_VECTOR (i, _bi.Bonds)
{
- i--;
- const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];
- CCoderStreamsInfo destCoderInfo;
- destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;
- destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;
- destBindInfo.Coders.AddInReserved(destCoderInfo);
+ RINOK(_streamBinders.AddNew().CreateEvents());
}
- for (i = _srcBindInfo.BindPairs.Size(); i != 0;)
+ return S_OK;
+}
+
+void CMixerMT::AddCoder(const CCreatedCoder &cod)
+{
+ IsFilter_Vector.Add(cod.IsFilter);
+ IsExternal_Vector.Add(cod.IsExternal);
+ // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
+ CCoderMT &c2 = _coders.AddNew();
+ c2.NumStreams = cod.NumStreams;
+ c2.Coder = cod.Coder;
+ c2.Coder2 = cod.Coder2;
+ c2.EncodeMode = EncodeMode;
+}
+
+CCoder &CMixerMT::GetCoder(unsigned index)
+{
+ return _coders[index];
+}
+
+void CMixerMT::ReInit()
+{
+ FOR_VECTOR (i, _streamBinders)
+ _streamBinders[i].ReInit();
+}
+
+void CMixerMT::SelectMainCoder(bool useFirst)
+{
+ unsigned ci = _bi.UnpackCoder;
+
+ if (!useFirst)
+ for (;;)
{
- i--;
- const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];
- CBindPair destBindPair;
- destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];
- destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];
- destBindInfo.BindPairs.AddInReserved(destBindPair);
+ if (_coders[ci].NumStreams != 1)
+ break;
+ if (!IsFilter_Vector[ci])
+ break;
+
+ UInt32 st = _bi.Coder_to_Stream[ci];
+ if (_bi.IsStream_in_PackStreams(st))
+ break;
+ int bond = _bi.FindBond_for_PackStream(st);
+ if (bond < 0)
+ throw 20150213;
+ ci = _bi.Bonds[bond].UnpackIndex;
}
- for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)
- destBindInfo.OutStreams.AddInReserved(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);
- for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)
- destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
+
+ MainCoderIndex = ci;
}
-void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
- CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
+HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
{
- sizes.ClearAndSetSize(numItems);
- sizePointers.ClearAndSetSize(numItems);
- for(UInt32 i = 0; i < numItems; i++)
+ unsigned i;
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ CCoderMT &coderInfo = _coders[i];
+ const CCoderStreamsInfo &csi = _bi.Coders[i];
+
+ UInt32 j;
+
+ unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
+ unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
+
+ coderInfo.InStreams.Clear();
+ for (j = 0; j < numInStreams; j++)
+ coderInfo.InStreams.AddNew();
+
+ coderInfo.OutStreams.Clear();
+ for (j = 0; j < numOutStreams; j++)
+ coderInfo.OutStreams.AddNew();
+ }
+
+ for (i = 0; i < _bi.Bonds.Size(); i++)
{
- if (!srcSizes || !srcSizes[i])
+ const CBond &bond = _bi.Bonds[i];
+
+ UInt32 inCoderIndex, inCoderStreamIndex;
+ UInt32 outCoderIndex, outCoderStreamIndex;
+
+ {
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
+
+ inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
+ outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
+
+ inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
+ outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
+ }
+
+ _streamBinders[i].CreateStreams(
+ &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
+ &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
+
+ CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
+ _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
+ _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
+ if (inSetSize && outSetSize)
{
- sizes[i] = 0;
- sizePointers[i] = NULL;
+ const UInt32 kBufSize = 1 << 19;
+ inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
+ outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
}
+ }
+
+ {
+ CCoderMT &cod = _coders[_bi.UnpackCoder];
+ if (EncodeMode)
+ cod.InStreams[0] = inStreams[0];
else
+ cod.OutStreams[0] = outStreams[0];
+ }
+
+ for (i = 0; i < _bi.PackStreams.Size(); i++)
+ {
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
+ CCoderMT &cod = _coders[coderIndex];
+ if (EncodeMode)
+ cod.OutStreams[coderStreamIndex] = outStreams[i];
+ else
+ cod.InStreams[coderStreamIndex] = inStreams[i];
+ }
+
+ return S_OK;
+}
+
+HRESULT CMixerMT::ReturnIfError(HRESULT code)
+{
+ FOR_VECTOR (i, _coders)
+ if (_coders[i].Result == code)
+ return code;
+ return S_OK;
+}
+
+HRESULT CMixerMT::Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress)
+{
+ Init(inStreams, outStreams);
+
+ unsigned i;
+ for (i = 0; i < _coders.Size(); i++)
+ if (i != MainCoderIndex)
{
- sizes[i] = *(srcSizes[i]);
- sizePointers[i] = &sizes[i];
+ RINOK(_coders[i].Create());
}
+
+ for (i = 0; i < _coders.Size(); i++)
+ if (i != MainCoderIndex)
+ _coders[i].Start();
+
+ _coders[MainCoderIndex].Code(progress);
+
+ for (i = 0; i < _coders.Size(); i++)
+ if (i != MainCoderIndex)
+ _coders[i].WaitExecuteFinish();
+
+ RINOK(ReturnIfError(E_ABORT));
+ RINOK(ReturnIfError(E_OUTOFMEMORY));
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ HRESULT result = _coders[i].Result;
+ if (result != S_OK
+ && result != k_My_HRESULT_WritingWasCut
+ && result != S_FALSE
+ && result != E_FAIL)
+ return result;
+ }
+
+ RINOK(ReturnIfError(S_FALSE));
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ HRESULT result = _coders[i].Result;
+ if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
+ return result;
}
+
+ return S_OK;
}
-void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
+UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
{
- SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
- SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+ return _streamBinders[bondIndex].ProcessedSize;
}
+#endif
+
}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
index 50e7077a..e63f2ff0 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -8,172 +8,430 @@
#include "../../ICoder.h"
-namespace NCoderMixer {
+#include "../../Common/CreateCoder.h"
-struct CBindPair
+#ifdef _7ZIP_ST
+ #define USE_MIXER_ST
+#else
+ #define USE_MIXER_MT
+ #ifndef _SFX
+ #define USE_MIXER_ST
+ #endif
+#endif
+
+#ifdef USE_MIXER_MT
+#include "../../Common/StreamBinder.h"
+#include "../../Common/VirtThread.h"
+#endif
+
+
+
+#ifdef USE_MIXER_ST
+
+class CSequentialInStreamCalcSize:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _size;
+ bool _wasFinished;
+public:
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ _wasFinished = false;
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt64 GetSize() const { return _size; }
+ bool WasFinished() const { return _wasFinished; }
+};
+
+
+class COutStreamCalcSize:
+ public ISequentialOutStream,
+ public IOutStreamFinish,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+public:
+ MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(OutStreamFinish)();
+
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init() { _size = 0; }
+ UInt64 GetSize() const { return _size; }
+};
+
+#endif
+
+
+
+namespace NCoderMixer2 {
+
+struct CBond
{
- UInt32 InIndex;
- UInt32 OutIndex;
+ UInt32 PackIndex;
+ UInt32 UnpackIndex;
+
+ UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }
+ UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }
};
+
struct CCoderStreamsInfo
{
- UInt32 NumInStreams;
- UInt32 NumOutStreams;
+ UInt32 NumStreams;
};
+
struct CBindInfo
{
CRecordVector<CCoderStreamsInfo> Coders;
- CRecordVector<CBindPair> BindPairs;
- CRecordVector<UInt32> InStreams;
- CRecordVector<UInt32> OutStreams;
+ CRecordVector<CBond> Bonds;
+ CRecordVector<UInt32> PackStreams;
+ unsigned UnpackCoder;
- void Clear()
+ unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }
+
+ int FindBond_for_PackStream(UInt32 packStream) const
{
- Coders.Clear();
- BindPairs.Clear();
- InStreams.Clear();
- OutStreams.Clear();
+ FOR_VECTOR (i, Bonds)
+ if (Bonds[i].PackIndex == packStream)
+ return i;
+ return -1;
}
- /*
- UInt32 GetCoderStartOutStream(UInt32 coderIndex) const
+ int FindBond_for_UnpackStream(UInt32 unpackStream) const
{
- UInt32 numOutStreams = 0;
- for (UInt32 i = 0; i < coderIndex; i++)
- numOutStreams += Coders[i].NumOutStreams;
- return numOutStreams;
+ FOR_VECTOR (i, Bonds)
+ if (Bonds[i].UnpackIndex == unpackStream)
+ return i;
+ return -1;
}
- */
-
- void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
+ bool SetUnpackCoder()
{
- numInStreams = 0;
- numOutStreams = 0;
- FOR_VECTOR (i, Coders)
+ bool isOk = false;
+ FOR_VECTOR(i, Coders)
{
- const CCoderStreamsInfo &coderStreamsInfo = Coders[i];
- numInStreams += coderStreamsInfo.NumInStreams;
- numOutStreams += coderStreamsInfo.NumOutStreams;
+ if (FindBond_for_UnpackStream(i) < 0)
+ {
+ if (isOk)
+ return false;
+ UnpackCoder = i;
+ isOk = true;
+ }
}
+ return isOk;
}
-
- int FindBinderForInStream(UInt32 inStream) const
+
+ bool IsStream_in_PackStreams(UInt32 streamIndex) const
{
- FOR_VECTOR (i, BindPairs)
- if (BindPairs[i].InIndex == inStream)
- return i;
- return -1;
+ return FindStream_in_PackStreams(streamIndex) >= 0;
}
- int FindBinderForOutStream(UInt32 outStream) const
+
+ int FindStream_in_PackStreams(UInt32 streamIndex) const
{
- FOR_VECTOR (i, BindPairs)
- if (BindPairs[i].OutIndex == outStream)
+ FOR_VECTOR(i, PackStreams)
+ if (PackStreams[i] == streamIndex)
return i;
return -1;
}
- UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const
+
+ // that function is used before Maps is calculated
+
+ UInt32 GetStream_for_Coder(UInt32 coderIndex) const
{
UInt32 streamIndex = 0;
for (UInt32 i = 0; i < coderIndex; i++)
- streamIndex += Coders[i].NumInStreams;
+ streamIndex += Coders[i].NumStreams;
return streamIndex;
}
+
+ // ---------- Maps Section ----------
+
+ CRecordVector<UInt32> Coder_to_Stream;
+ CRecordVector<UInt32> Stream_to_Coder;
+
+ void ClearMaps();
+ bool CalcMapsAndCheck();
+
+ // ---------- End of Maps Section ----------
- UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const
+ void Clear()
{
- UInt32 streamIndex = 0;
- for (UInt32 i = 0; i < coderIndex; i++)
- streamIndex += Coders[i].NumOutStreams;
- return streamIndex;
+ Coders.Clear();
+ Bonds.Clear();
+ PackStreams.Clear();
+
+ ClearMaps();
}
+
+ void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const
+ {
+ coderIndex = Stream_to_Coder[streamIndex];
+ coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];
+ }
+};
- void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,
- UInt32 &coderStreamIndex) const
+
+class CCoder
+{
+ CLASS_NO_COPY(CCoder);
+public:
+ CMyComPtr<ICompressCoder> Coder;
+ CMyComPtr<ICompressCoder2> Coder2;
+ UInt32 NumStreams;
+
+ UInt64 UnpackSize;
+ const UInt64 *UnpackSizePointer;
+
+ CRecordVector<UInt64> PackSizes;
+ CRecordVector<const UInt64 *> PackSizePointers;
+
+ CCoder() {}
+
+ void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes);
+
+ IUnknown *GetUnknown() const
{
- for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
- {
- UInt32 curSize = Coders[coderIndex].NumInStreams;
- if (streamIndex < curSize)
- {
- coderStreamIndex = streamIndex;
- return;
- }
- streamIndex -= curSize;
- }
- throw 1;
+ return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
}
- void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,
- UInt32 &coderStreamIndex) const
+
+ HRESULT QueryInterface(REFGUID iid, void** pp) const
{
- for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
- {
- UInt32 curSize = Coders[coderIndex].NumOutStreams;
- if (streamIndex < curSize)
+ return GetUnknown()->QueryInterface(iid, pp);
+ }
+};
+
+
+
+class CMixer
+{
+ bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);
+
+protected:
+ CBindInfo _bi;
+
+ int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const
+ {
+ if (EncodeMode == forInputStream)
+ return _bi.FindBond_for_UnpackStream(streamIndex);
+ else
+ return _bi.FindBond_for_PackStream(streamIndex);
+ }
+
+ CBoolVector IsFilter_Vector;
+ CBoolVector IsExternal_Vector;
+ bool EncodeMode;
+public:
+ unsigned MainCoderIndex;
+
+ CMixer(bool encodeMode):
+ EncodeMode(encodeMode),
+ MainCoderIndex(0)
+ {}
+
+ /*
+ Sequence of calling:
+
+ SetBindInfo();
+ for each coder
+ AddCoder();
+ SelectMainCoder();
+
+ for each file
{
- coderStreamIndex = streamIndex;
- return;
+ ReInit()
+ for each coder
+ SetCoderInfo();
+ Code();
}
- streamIndex -= curSize;
- }
- throw 1;
+ */
+
+ virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)
+ {
+ _bi = bindInfo;
+ IsFilter_Vector.Clear();
+ MainCoderIndex = 0;
+ return S_OK;
}
+
+ virtual void AddCoder(const CCreatedCoder &cod) = 0;
+ virtual CCoder &GetCoder(unsigned index) = 0;
+ virtual void SelectMainCoder(bool useFirst) = 0;
+ virtual void ReInit() = 0;
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0;
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress) = 0;
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
+
+ bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
+ bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);
+ bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);
};
-class CBindReverseConverter
+
+
+
+#ifdef USE_MIXER_ST
+
+struct CCoderST: public CCoder
{
- UInt32 _numSrcOutStreams;
- NCoderMixer::CBindInfo _srcBindInfo;
- CRecordVector<UInt32> _srcInToDestOutMap;
- CRecordVector<UInt32> _srcOutToDestInMap;
- CRecordVector<UInt32> _destInToSrcOutMap;
-public:
- UInt32 NumSrcInStreams;
- CRecordVector<UInt32> DestOutToSrcInMap;
+ bool CanRead;
+ bool CanWrite;
+
+ CCoderST(): CanRead(false), CanWrite(false) {}
+};
- CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);
- void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);
+
+struct CStBinderStream
+{
+ CSequentialInStreamCalcSize *InStreamSpec;
+ COutStreamCalcSize *OutStreamSpec;
+ CMyComPtr<IUnknown> StreamRef;
+
+ CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
};
-void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
- CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems);
-struct CCoderInfo2
+class CMixerST:
+ public IUnknown,
+ public CMixer,
+ public CMyUnknownImp
{
- CMyComPtr<ICompressCoder> Coder;
- CMyComPtr<ICompressCoder2> Coder2;
- UInt32 NumInStreams;
- UInt32 NumOutStreams;
+ HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
+ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
- CRecordVector<UInt64> InSizes;
- CRecordVector<UInt64> OutSizes;
- CRecordVector<const UInt64 *> InSizePointers;
- CRecordVector<const UInt64 *> OutSizePointers;
+ HRESULT FinishStream(UInt32 streamIndex);
+ HRESULT FinishCoder(UInt32 coderIndex);
- CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
- NumInStreams(numInStreams),
- NumOutStreams(numOutStreams) {}
- void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
+public:
+ CObjectVector<CCoderST> _coders;
+
+ CObjectVector<CStBinderStream> _binderStreams;
- HRESULT QueryInterface(REFGUID iid, void** pp) const
+ MY_UNKNOWN_IMP
+
+ CMixerST(bool encodeMode);
+ ~CMixerST();
+
+ virtual void AddCoder(const CCreatedCoder &cod);
+ virtual CCoder &GetCoder(unsigned index);
+ virtual void SelectMainCoder(bool useFirst);
+ virtual void ReInit();
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress);
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
+
+ HRESULT GetMainUnpackStream(
+ ISequentialInStream * const *inStreams,
+ ISequentialInStream **inStreamRes);
+};
+
+#endif
+
+
+
+
+#ifdef USE_MIXER_MT
+
+class CCoderMT: public CCoder, public CVirtThread
+{
+ CLASS_NO_COPY(CCoderMT)
+ CRecordVector<ISequentialInStream*> InStreamPointers;
+ CRecordVector<ISequentialOutStream*> OutStreamPointers;
+
+private:
+ void Execute();
+public:
+ bool EncodeMode;
+ HRESULT Result;
+ CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
+ CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
+
+ void Release()
{
- IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
- return p->QueryInterface(iid, pp);
+ InStreamPointers.Clear();
+ OutStreamPointers.Clear();
+ unsigned i;
+ for (i = 0; i < InStreams.Size(); i++)
+ InStreams[i].Release();
+ for (i = 0; i < OutStreams.Size(); i++)
+ OutStreams[i].Release();
}
+
+ class CReleaser
+ {
+ CLASS_NO_COPY(CReleaser)
+ CCoderMT &_c;
+ public:
+ CReleaser(CCoderMT &c): _c(c) {}
+ ~CReleaser() { _c.Release(); }
+ };
+
+ CCoderMT(): EncodeMode(false) {}
+ ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
+
+ void Code(ICompressProgressInfo *progress);
};
-class CCoderMixer2
+
+class CMixerMT:
+ public IUnknown,
+ public CMixer,
+ public CMyUnknownImp
{
+ CObjectVector<CStreamBinder> _streamBinders;
+
+ HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
+ HRESULT ReturnIfError(HRESULT code);
+
public:
- virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0;
- virtual void ReInit() = 0;
- virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
+ CObjectVector<CCoderMT> _coders;
+
+ MY_UNKNOWN_IMP
+
+ virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
+ virtual void AddCoder(const CCreatedCoder &cod);
+ virtual CCoder &GetCoder(unsigned index);
+ virtual void SelectMainCoder(bool useFirst);
+ virtual void ReInit();
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress);
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
+
+ CMixerMT(bool encodeMode): CMixer(encodeMode) {}
};
+#endif
+
}
#endif
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
index 5288fbc1..c0139862 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
@@ -4,125 +4,153 @@
#include "CoderMixer2MT.h"
-namespace NCoderMixer {
+namespace NCoderMixer2 {
-CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):
- CCoderInfo2(numInStreams, numOutStreams)
+void CCoderMT::Execute() { Code(NULL); }
+
+void CCoderMT::Code(ICompressProgressInfo *progress)
{
- InStreams.ClearAndReserve(NumInStreams);
- OutStreams.ClearAndReserve(NumOutStreams);
-}
+ unsigned numInStreams = EncodeMode ? 1 : NumStreams;
+ unsigned numOutStreams = EncodeMode ? NumStreams : 1;
-void CCoder2::Execute() { Code(NULL); }
+ InStreamPointers.ClearAndReserve(numInStreams);
+ OutStreamPointers.ClearAndReserve(numOutStreams);
-void CCoder2::Code(ICompressProgressInfo *progress)
-{
- InStreamPointers.ClearAndReserve(NumInStreams);
- OutStreamPointers.ClearAndReserve(NumOutStreams);
- UInt32 i;
- for (i = 0; i < NumInStreams; i++)
- {
- if (InSizePointers[i])
- InSizePointers[i] = &InSizes[i];
+ unsigned i;
+
+ for (i = 0; i < numInStreams; i++)
InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
- }
- for (i = 0; i < NumOutStreams; i++)
- {
- if (OutSizePointers[i])
- OutSizePointers[i] = &OutSizes[i];
+
+ for (i = 0; i < numOutStreams; i++)
OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
- }
+
+ // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
+ /*
+ if (UnpackSizePointer)
+ UnpackSizePointer = &UnpackSize;
+ for (i = 0; i < NumStreams; i++)
+ if (PackSizePointers[i])
+ PackSizePointers[i] = &PackSizes[i];
+ */
+
if (Coder)
Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
- InSizePointers[0], OutSizePointers[0], progress);
+ EncodeMode ? UnpackSizePointer : PackSizePointers[0],
+ EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
+ progress);
else
- Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
- &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
- {
- unsigned i;
- for (i = 0; i < InStreams.Size(); i++)
- InStreams[i].Release();
- for (i = 0; i < OutStreams.Size(); i++)
- OutStreams[i].Release();
- }
-}
+ Result = Coder2->Code(
+ &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
+ &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
+ progress);
+
+ InStreamPointers.Clear();
+ OutStreamPointers.Clear();
-/*
-void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
-{
- SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
- SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+ for (i = 0; i < InStreams.Size(); i++)
+ InStreams[i].Release();
+ for (i = 0; i < OutStreams.Size(); i++)
+ OutStreams[i].Release();
}
-*/
-
-//////////////////////////////////////
-// CCoderMixer2MT
-HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
+HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
{
- _bindInfo = bindInfo;
+ CMixer::SetBindInfo(bindInfo);
+
_streamBinders.Clear();
- FOR_VECTOR (i, _bindInfo.BindPairs)
+ FOR_VECTOR (i, _bi.Bonds)
{
RINOK(_streamBinders.AddNew().CreateEvents());
}
return S_OK;
}
-void CCoderMixer2MT::AddCoderCommon()
-{
- const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
- CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
- _coders.Add(threadCoderInfo);
-}
-
-void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
+void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
{
- AddCoderCommon();
- _coders.Back().Coder = coder;
+ const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
+ CCoderMT &c2 = _coders.AddNew();
+ c2.NumStreams = c.NumStreams;
+ c2.EncodeMode = EncodeMode;
+ c2.Coder = coder;
+ c2.Coder2 = coder2;
+ IsFilter_Vector.Add(isFilter);
}
-void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
+CCoder &CMixerMT::GetCoder(unsigned index)
{
- AddCoderCommon();
- _coders.Back().Coder2 = coder;
+ return _coders[index];
}
-
-void CCoderMixer2MT::ReInit()
+void CMixerMT::ReInit()
{
FOR_VECTOR (i, _streamBinders)
_streamBinders[i].ReInit();
}
+void CMixerMT::SelectMainCoder(bool useFirst)
+{
+ unsigned ci = _bi.UnpackCoder;
+
+ if (!useFirst)
+ for (;;)
+ {
+ if (_coders[ci].NumStreams != 1)
+ break;
+ if (!IsFilter_Vector[ci])
+ break;
+
+ UInt32 st = _bi.Coder_to_Stream[ci];
+ if (_bi.IsStream_in_PackStreams(st))
+ break;
+ int bond = _bi.FindBond_for_PackStream(st);
+ if (bond < 0)
+ throw 20150213;
+ ci = _bi.Bonds[bond].UnpackIndex;
+ }
+
+ MainCoderIndex = ci;
+}
-HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams)
+HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
{
- /*
- if (_coders.Size() != _bindInfo.Coders.Size())
- throw 0;
- */
unsigned i;
+
for (i = 0; i < _coders.Size(); i++)
{
- CCoder2 &coderInfo = _coders[i];
- const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
- coderInfo.InStreams.Clear();
+ CCoderMT &coderInfo = _coders[i];
+ const CCoderStreamsInfo &csi = _bi.Coders[i];
+
UInt32 j;
- for (j = 0; j < coderStreamsInfo.NumInStreams; j++)
- coderInfo.InStreams.Add(NULL);
+
+ unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
+ unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
+
+ coderInfo.InStreams.Clear();
+ for (j = 0; j < numInStreams; j++)
+ coderInfo.InStreams.AddNew();
+
coderInfo.OutStreams.Clear();
- for (j = 0; j < coderStreamsInfo.NumOutStreams; j++)
- coderInfo.OutStreams.Add(NULL);
+ for (j = 0; j < numOutStreams; j++)
+ coderInfo.OutStreams.AddNew();
}
- for (i = 0; i < _bindInfo.BindPairs.Size(); i++)
+ for (i = 0; i < _bi.Bonds.Size(); i++)
{
- const CBindPair &bindPair = _bindInfo.BindPairs[i];
+ const CBond &bond = _bi.Bonds[i];
+
UInt32 inCoderIndex, inCoderStreamIndex;
UInt32 outCoderIndex, outCoderStreamIndex;
- _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
- _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
+
+ {
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
+
+ inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
+ outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
+
+ inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
+ outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
+ }
_streamBinders[i].CreateStreams(
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
@@ -139,23 +167,29 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
}
}
- for (i = 0; i < _bindInfo.InStreams.Size(); i++)
{
- UInt32 inCoderIndex, inCoderStreamIndex;
- _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
- _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
+ CCoderMT &cod = _coders[_bi.UnpackCoder];
+ if (EncodeMode)
+ cod.InStreams[0] = inStreams[0];
+ else
+ cod.OutStreams[0] = outStreams[0];
}
-
- for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 0; i < _bi.PackStreams.Size(); i++)
{
- UInt32 outCoderIndex, outCoderStreamIndex;
- _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
- _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
+ UInt32 coderIndex, coderStreamIndex;
+ _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
+ CCoderMT &cod = _coders[coderIndex];
+ if (EncodeMode)
+ cod.OutStreams[coderStreamIndex] = outStreams[i];
+ else
+ cod.InStreams[coderStreamIndex] = inStreams[i];
}
+
return S_OK;
}
-HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
+HRESULT CMixerMT::ReturnIfError(HRESULT code)
{
FOR_VECTOR (i, _coders)
if (_coders[i].Result == code)
@@ -163,35 +197,28 @@ HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
return S_OK;
}
-STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
- const UInt64 ** /* inSizes */,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 ** /* outSizes */,
- UInt32 numOutStreams,
- ICompressProgressInfo *progress)
+HRESULT CMixerMT::Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress)
{
- if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
- numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
- return E_INVALIDARG;
-
Init(inStreams, outStreams);
unsigned i;
for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
+ if (i != MainCoderIndex)
{
RINOK(_coders[i].Create());
}
for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
+ if (i != MainCoderIndex)
_coders[i].Start();
- _coders[_progressCoderIndex].Code(progress);
+ _coders[MainCoderIndex].Code(progress);
for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
+ if (i != MainCoderIndex)
_coders[i].WaitExecuteFinish();
RINOK(ReturnIfError(E_ABORT));
@@ -200,7 +227,10 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
- if (result != S_OK && result != E_FAIL && result != S_FALSE)
+ if (result != S_OK
+ && result != k_My_HRESULT_WritingWasCut
+ && result != S_FALSE
+ && result != E_FAIL)
return result;
}
@@ -209,10 +239,16 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
for (i = 0; i < _coders.Size(); i++)
{
HRESULT result = _coders[i].Result;
- if (result != S_OK)
+ if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
return result;
}
+
return S_OK;
}
+UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
+{
+ return _streamBinders[bondIndex].ProcessedSize;
+}
+
}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
index ba475cec..41bb3e1c 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h
@@ -3,81 +3,75 @@
#ifndef __CODER_MIXER2_MT_H
#define __CODER_MIXER2_MT_H
-#include "CoderMixer2.h"
#include "../../../Common/MyCom.h"
+
#include "../../Common/StreamBinder.h"
#include "../../Common/VirtThread.h"
-namespace NCoderMixer {
+#include "CoderMixer2.h"
+
+namespace NCoderMixer2 {
-struct CCoder2: public CCoderInfo2, public CVirtThread
+class CCoderMT: public CCoder, public CVirtThread
{
+ CLASS_NO_COPY(CCoderMT)
CRecordVector<ISequentialInStream*> InStreamPointers;
CRecordVector<ISequentialOutStream*> OutStreamPointers;
+private:
+ void Execute();
public:
+ bool EncodeMode;
HRESULT Result;
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
- CCoder2(UInt32 numInStreams, UInt32 numOutStreams);
- ~CCoder2() { CVirtThread::WaitThreadFinish(); }
- // void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
- virtual void Execute();
+ CCoderMT(): EncodeMode(false) {}
+ ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
+
void Code(ICompressProgressInfo *progress);
};
-/*
- SetBindInfo()
- for each coder
- AddCoder[2]()
- SetProgressIndex(UInt32 coderIndex);
-
- for each file
- {
- ReInit()
- for each coder
- SetCoderInfo
- Code
- }
-*/
-
-class CCoderMixer2MT:
- public ICompressCoder2,
- public CCoderMixer2,
+
+class CMixerMT:
+ public IUnknown,
+ public CMixer,
public CMyUnknownImp
{
- CBindInfo _bindInfo;
CObjectVector<CStreamBinder> _streamBinders;
- unsigned _progressCoderIndex;
- void AddCoderCommon();
- HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);
+ HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
HRESULT ReturnIfError(HRESULT code);
+
public:
- CObjectVector<CCoder2> _coders;
+ CObjectVector<CCoderMT> _coders;
+
MY_UNKNOWN_IMP
- STDMETHOD(Code)(ISequentialInStream **inStreams,
- const UInt64 **inSizes,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 **outSizes,
- UInt32 numOutStreams,
+ virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
+
+ virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
+
+ virtual CCoder &GetCoder(unsigned index);
+
+ virtual void SelectMainCoder(bool useFirst);
+
+ virtual void ReInit();
+
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
ICompressProgressInfo *progress);
- HRESULT SetBindInfo(const CBindInfo &bindInfo);
- void AddCoder(ICompressCoder *coder);
- void AddCoder2(ICompressCoder2 *coder);
- void SetProgressCoderIndex(unsigned coderIndex) { _progressCoderIndex = coderIndex; }
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
- void ReInit();
- void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
- { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
- UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
- { return _streamBinders[binderIndex].ProcessedSize; }
+ CMixerMT(bool encodeMode): CMixer(encodeMode) {}
};
}
+
#endif
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
index a94ba115..127c1ed4 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
@@ -4,236 +4,559 @@
#include "CoderMixer2ST.h"
-namespace NCoderMixer {
+STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessed = 0;
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Read(data, size, &realProcessed);
+ _size += realProcessed;
+ if (size != 0 && realProcessed == 0)
+ _wasFinished = true;
+ if (processedSize)
+ *processedSize = realProcessed;
+ return result;
+}
-CCoderMixer2ST::CCoderMixer2ST() {}
-CCoderMixer2ST::~CCoderMixer2ST(){ }
-HRESULT CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo)
+STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- _bindInfo = bindInfo;
- return S_OK;
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ _size += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
}
-void CCoderMixer2ST::AddCoderCommon(bool isMain)
+STDMETHODIMP COutStreamCalcSize::Flush()
{
- const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()];
- _coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain));
+ HRESULT result = S_OK;
+ if (_stream)
+ {
+ CMyComPtr<IOutStreamFlush> outStreamFlush;
+ _stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush);
+ if (outStreamFlush)
+ result = outStreamFlush->Flush();;
+ }
+ return result;
}
-void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain)
+
+
+namespace NCoderMixer2 {
+
+CMixerST::CMixerST(bool encodeMode):
+ CMixer(encodeMode)
+ {}
+
+CMixerST::~CMixerST() {}
+
+void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
{
- AddCoderCommon(isMain);
- _coders.Back().Coder = coder;
+ IsFilter_Vector.Add(isFilter);
+ const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
+ CCoderST &c2 = _coders.AddNew();
+ c2.NumStreams = c.NumStreams;
+ c2.Coder = coder;
+ c2.Coder2 = coder2;
+
+ /*
+ if (isFilter)
+ {
+ c2.CanRead = true;
+ c2.CanWrite = true;
+ }
+ else
+ */
+ {
+ IUnknown *unk = (coder ? (IUnknown *)coder : (IUnknown *)coder2);
+ {
+ CMyComPtr<ISequentialInStream> s;
+ unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
+ c2.CanRead = (s != NULL);
+ }
+ {
+ CMyComPtr<ISequentialOutStream> s;
+ unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
+ c2.CanWrite = (s != NULL);
+ }
+ }
}
-void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain)
+CCoder &CMixerST::GetCoder(unsigned index)
{
- AddCoderCommon(isMain);
- _coders.Back().Coder2 = coder;
+ return _coders[index];
+}
+
+void CMixerST::ReInit() {}
+
+HRESULT CMixerST::GetInStream2(
+ ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
+{
+ UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
+
+ if (EncodeMode)
+ {
+ _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
+ if (coderStreamIndex != 0)
+ return E_NOTIMPL;
+ }
+
+ const CCoder &coder = _coders[coderIndex];
+
+ CMyComPtr<ISequentialInStream> seqInStream;
+ coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
+ if (!seqInStream)
+ return E_NOTIMPL;
+
+ UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
+ UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
+
+ bool isSet = false;
+
+ if (numInStreams == 1)
+ {
+ CMyComPtr<ICompressSetInStream> setStream;
+ coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
+ if (setStream)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
+ RINOK(setStream->SetInStream(seqInStream2));
+ isSet = true;
+ }
+ }
+
+ if (!isSet && numInStreams != 0)
+ {
+ CMyComPtr<ICompressSetInStream2> setStream2;
+ coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
+ if (!setStream2)
+ return E_NOTIMPL;
+
+ for (UInt32 i = 0; i < numInStreams; i++)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
+ RINOK(setStream2->SetInStream2(i, seqInStream2));
+ }
+ }
+
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
}
-void CCoderMixer2ST::ReInit() { }
-HRESULT CCoderMixer2ST::GetInStream(
- ISequentialInStream **inStreams, const UInt64 **inSizes,
- UInt32 streamIndex, ISequentialInStream **inStreamRes)
+HRESULT CMixerST::GetInStream(
+ ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
{
CMyComPtr<ISequentialInStream> seqInStream;
- int i;
- for (i = 0; i < _bindInfo.InStreams.Size(); i++)
- if (_bindInfo.InStreams[i] == streamIndex)
+
+ {
+ int index = -1;
+ if (EncodeMode)
+ {
+ if (_bi.UnpackCoder == inStreamIndex)
+ index = 0;
+ }
+ else
+ index = _bi.FindStream_in_PackStreams(inStreamIndex);
+
+ if (index >= 0)
{
- seqInStream = inStreams[i];
+ seqInStream = inStreams[index];
*inStreamRes = seqInStream.Detach();
return S_OK;
}
- int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);
- if (binderIndex < 0)
+ }
+
+ int bond = FindBond_for_Stream(
+ true, // forInputStream
+ inStreamIndex);
+ if (bond < 0)
return E_INVALIDARG;
- UInt32 coderIndex, coderStreamIndex;
- _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex,
- coderIndex, coderStreamIndex);
-
- CCoderInfo2 &coder = _coders[coderIndex];
- if (!coder.Coder)
- return E_NOTIMPL;
- coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
- if (!seqInStream)
- return E_NOTIMPL;
+ RINOK(GetInStream2(inStreams, /* inSizes, */
+ _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
- UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex);
+ while (_binderStreams.Size() <= (unsigned)bond)
+ _binderStreams.AddNew();
+ CStBinderStream &bs = _binderStreams[bond];
- CMyComPtr<ICompressSetInStream> setInStream;
- if (!coder.Coder)
- return E_NOTIMPL;
- coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream);
- if (!setInStream)
+ if (bs.StreamRef || bs.InStreamSpec)
return E_NOTIMPL;
+
+ CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
+ bs.StreamRef = spec;
+ bs.InStreamSpec = spec;
+
+ spec->SetStream(seqInStream);
+ spec->Init();
+
+ seqInStream = bs.InStreamSpec;
- if (coder.NumInStreams > 1)
- return E_NOTIMPL;
- for (i = 0; i < (int)coder.NumInStreams; i++)
- {
- CMyComPtr<ISequentialInStream> seqInStream2;
- RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2));
- RINOK(setInStream->SetInStream(seqInStream2));
- }
*inStreamRes = seqInStream.Detach();
return S_OK;
}
-HRESULT CCoderMixer2ST::GetOutStream(
- ISequentialOutStream **outStreams, const UInt64 **outSizes,
- UInt32 streamIndex, ISequentialOutStream **outStreamRes)
+
+HRESULT CMixerST::GetOutStream(
+ ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
+ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
{
CMyComPtr<ISequentialOutStream> seqOutStream;
- int i;
- for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
- if (_bindInfo.OutStreams[i] == streamIndex)
+
+ {
+ int index = -1;
+ if (!EncodeMode)
+ {
+ if (_bi.UnpackCoder == outStreamIndex)
+ index = 0;
+ }
+ else
+ index = _bi.FindStream_in_PackStreams(outStreamIndex);
+
+ if (index >= 0)
{
- seqOutStream = outStreams[i];
+ seqOutStream = outStreams[index];
*outStreamRes = seqOutStream.Detach();
return S_OK;
}
- int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);
- if (binderIndex < 0)
+ }
+
+ int bond = FindBond_for_Stream(
+ false, // forInputStream
+ outStreamIndex);
+ if (bond < 0)
return E_INVALIDARG;
- UInt32 coderIndex, coderStreamIndex;
- _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex,
- coderIndex, coderStreamIndex);
+ UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
+
+ UInt32 coderIndex = inStreamIndex;
+ UInt32 coderStreamIndex = 0;
+
+ if (!EncodeMode)
+ _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
+
+ CCoder &coder = _coders[coderIndex];
- CCoderInfo2 &coder = _coders[coderIndex];
+ /*
if (!coder.Coder)
return E_NOTIMPL;
- coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
+ */
+
+ coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
if (!seqOutStream)
return E_NOTIMPL;
- UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
+ UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
+ UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
- CMyComPtr<ICompressSetOutStream> setOutStream;
- if (!coder.Coder)
- return E_NOTIMPL;
- coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
- if (!setOutStream)
- return E_NOTIMPL;
+ bool isSet = false;
- if (coder.NumOutStreams > 1)
- return E_NOTIMPL;
- for (i = 0; i < (int)coder.NumOutStreams; i++)
+ if (numOutStreams == 1)
{
- CMyComPtr<ISequentialOutStream> seqOutStream2;
- RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2));
- RINOK(setOutStream->SetOutStream(seqOutStream2));
+ CMyComPtr<ICompressSetOutStream> setOutStream;
+ coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
+ if (setOutStream)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
+ RINOK(setOutStream->SetOutStream(seqOutStream2));
+ isSet = true;
+ }
}
+
+ if (!isSet && numOutStreams != 0)
+ {
+ // return E_NOTIMPL;
+ // /*
+ CMyComPtr<ICompressSetOutStream2> setStream2;
+ coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
+ if (!setStream2)
+ return E_NOTIMPL;
+ for (UInt32 i = 0; i < numOutStreams; i++)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
+ RINOK(setStream2->SetOutStream2(i, seqOutStream2));
+ }
+ // */
+ }
+
+ while (_binderStreams.Size() <= (unsigned)bond)
+ _binderStreams.AddNew();
+ CStBinderStream &bs = _binderStreams[bond];
+
+ if (bs.StreamRef || bs.OutStreamSpec)
+ return E_NOTIMPL;
+
+ COutStreamCalcSize *spec = new COutStreamCalcSize;
+ bs.StreamRef = (ISequentialOutStream *)spec;
+ bs.OutStreamSpec = spec;
+
+ spec->SetStream(seqOutStream);
+ spec->Init();
+
+ seqOutStream = bs.OutStreamSpec;
+
*outStreamRes = seqOutStream.Detach();
return S_OK;
}
-
-STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
- const UInt64 **inSizes,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 **outSizes,
- UInt32 numOutStreams,
- ICompressProgressInfo *progress)
+
+static HRESULT GetError(HRESULT res, HRESULT res2)
{
- if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
- numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
- return E_INVALIDARG;
+ if (res == res2)
+ return res;
+ if (res == S_OK)
+ return res2;
+ if (res == k_My_HRESULT_WritingWasCut)
+ {
+ if (res2 != S_OK)
+ return res2;
+ }
+ return res;
+}
- // Find main coder
- int _mainCoderIndex = -1;
- int i;
- for (i = 0; i < _coders.Size(); i++)
- if (_coders[i].IsMain)
- {
- _mainCoderIndex = i;
- break;
- }
- if (_mainCoderIndex < 0)
- for (i = 0; i < _coders.Size(); i++)
- if (_coders[i].NumInStreams > 1)
+
+HRESULT CMixerST::FlushStream(UInt32 streamIndex)
+{
+ {
+ int index = -1;
+ if (!EncodeMode)
{
- if (_mainCoderIndex >= 0)
- return E_NOTIMPL;
- _mainCoderIndex = i;
+ if (_bi.UnpackCoder == streamIndex)
+ index = 0;
}
- if (_mainCoderIndex < 0)
- _mainCoderIndex = 0;
+ else
+ index = _bi.FindStream_in_PackStreams(streamIndex);
+
+ if (index >= 0)
+ return S_OK;
+ }
+
+ int bond = FindBond_for_Stream(
+ false, // forInputStream
+ streamIndex);
+ if (bond < 0)
+ return E_INVALIDARG;
+
+ UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
+
+ UInt32 coderIndex = inStreamIndex;
+ UInt32 coderStreamIndex = 0;
+ if (!EncodeMode)
+ _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
+
+ CCoder &coder = _coders[coderIndex];
+ CMyComPtr<IOutStreamFlush> flush;
+ coder.QueryInterface(IID_IOutStreamFlush, (void **)&flush);
+ HRESULT res = S_OK;
+ if (flush)
+ {
+ res = flush->Flush();
+ }
+ return GetError(res, FlushCoder(coderIndex));
+}
+
+
+HRESULT CMixerST::FlushCoder(UInt32 coderIndex)
+{
+ CCoder &coder = _coders[coderIndex];
+
+ UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
+ UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
+
+ HRESULT res = S_OK;
+ for (unsigned i = 0; i < numOutStreams; i++)
+ res = GetError(res, FlushStream(startIndex + i));
+ return res;
+}
+
+
+void CMixerST::SelectMainCoder(bool useFirst)
+{
+ unsigned ci = _bi.UnpackCoder;
+
+ int firstNonFilter = -1;
+ int firstAllowed = ci;
+
+ for (;;)
+ {
+ const CCoderST &coder = _coders[ci];
+ // break;
+
+ if (ci != _bi.UnpackCoder)
+ if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
+ {
+ firstAllowed = ci;
+ firstNonFilter = -2;
+ }
+
+ if (coder.NumStreams != 1)
+ break;
+
+ UInt32 st = _bi.Coder_to_Stream[ci];
+ if (_bi.IsStream_in_PackStreams(st))
+ break;
+ int bond = _bi.FindBond_for_PackStream(st);
+ if (bond < 0)
+ throw 20150213;
+
+ if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
+ break;
+
+ if (firstNonFilter == -1 && !IsFilter_Vector[ci])
+ firstNonFilter = ci;
+
+ ci = _bi.Bonds[bond].UnpackIndex;
+ }
+
+ ci = firstNonFilter;
+ if (firstNonFilter < 0 || useFirst)
+ ci = firstAllowed;
+ MainCoderIndex = ci;
+}
+
+
+HRESULT CMixerST::Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress)
+{
+ _binderStreams.Clear();
+ unsigned ci = MainCoderIndex;
- // _mainCoderIndex = 0;
- // _mainCoderIndex = _coders.Size() - 1;
- CCoderInfo2 &mainCoder = _coders[_mainCoderIndex];
+ const CCoder &mainCoder = _coders[MainCoderIndex];
CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
- UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex);
- UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex);
- for (i = 0; i < (int)mainCoder.NumInStreams; i++)
+
+ UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
+ UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
+
+ UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
+ UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
+
+ UInt32 i;
+
+ for (i = 0; i < numInStreams; i++)
{
CMyComPtr<ISequentialInStream> seqInStream;
- RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream));
+ RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
seqInStreams.Add(seqInStream);
}
- for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
+
+ for (i = 0; i < numOutStreams; i++)
{
CMyComPtr<ISequentialOutStream> seqOutStream;
- RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream));
+ RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
seqOutStreams.Add(seqOutStream);
}
+
CRecordVector< ISequentialInStream * > seqInStreamsSpec;
CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
- for (i = 0; i < (int)mainCoder.NumInStreams; i++)
+
+ for (i = 0; i < numInStreams; i++)
seqInStreamsSpec.Add(seqInStreams[i]);
- for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
+ for (i = 0; i < numOutStreams; i++)
seqOutStreamsSpec.Add(seqOutStreams[i]);
for (i = 0; i < _coders.Size(); i++)
{
- if (i == _mainCoderIndex)
+ if (i == ci)
continue;
- CCoderInfo2 &coder = _coders[i];
+
+ CCoder &coder = _coders[i];
+
CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
- coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
+ coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
if (setOutStreamSize)
{
- RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0]));
+ RINOK(setOutStreamSize->SetOutStreamSize(
+ EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
}
}
+
+ const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
+ const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
+
+ HRESULT res;
if (mainCoder.Coder)
{
- RINOK(mainCoder.Coder->Code(
+ res = mainCoder.Coder->Code(
seqInStreamsSpec[0], seqOutStreamsSpec[0],
- mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0],
- progress));
+ isSizes2[0], outSizes2[0],
+ progress);
}
else
{
- RINOK(mainCoder.Coder2->Code(
- &seqInStreamsSpec.Front(),
- &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams,
- &seqOutStreamsSpec.Front(),
- &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams,
- progress));
+ res = mainCoder.Coder2->Code(
+ &seqInStreamsSpec.Front(), isSizes2, numInStreams,
+ &seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
+ progress);
}
- CMyComPtr<IOutStreamFlush> flush;
- seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush);
- if (flush)
- return flush->Flush();
+
+ if (res == k_My_HRESULT_WritingWasCut)
+ res = S_OK;
+
+ if (res == S_OK || res == S_FALSE)
+ {
+ res = GetError(res, FlushCoder(ci));
+ }
+
+ for (i = 0; i < _binderStreams.Size(); i++)
+ {
+ const CStBinderStream &bs = _binderStreams[i];
+ if (bs.InStreamSpec)
+ bs.InStreamSpec->ReleaseStream();
+ else
+ bs.OutStreamSpec->ReleaseStream();
+ }
+
+ if (res == k_My_HRESULT_WritingWasCut)
+ res = S_OK;
+ return res;
+}
+
+
+HRESULT CMixerST::GetMainUnpackStream(
+ ISequentialInStream * const *inStreams,
+ ISequentialInStream **inStreamRes)
+{
+ CMyComPtr<ISequentialInStream> seqInStream;
+
+ RINOK(GetInStream2(inStreams, /* inSizes, */
+ _bi.UnpackCoder, &seqInStream))
+
+ FOR_VECTOR (i, _coders)
+ {
+ CCoder &coder = _coders[i];
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
+ if (setOutStreamSize)
+ {
+ RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
+ }
+ }
+
+ *inStreamRes = seqInStream.Detach();
return S_OK;
}
-/*
-UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const
+
+UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
{
- return _streamBinders[binderIndex].ProcessedSize;
+ const CStBinderStream &bs = _binderStreams[bondIndex];
+ if (bs.InStreamSpec)
+ return bs.InStreamSpec->GetSize();
+ return bs.OutStreamSpec->GetSize();
}
-*/
}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h
index d35655ba..f2f7c4cb 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h
@@ -3,84 +3,125 @@
#ifndef __CODER_MIXER2_ST_H
#define __CODER_MIXER2_ST_H
-#include "CoderMixer2.h"
#include "../../../Common/MyCom.h"
+
#include "../../ICoder.h"
-namespace NCoderMixer {
-
-// SetBindInfo()
-// for each coder
-// {
-// AddCoder[2]()
-// }
-//
-// for each file
-// {
-// ReInit()
-// for each coder
-// {
-// SetCoderInfo
-// }
-// SetProgressIndex(UInt32 coderIndex);
-// Code
-// }
-
-struct CSTCoderInfo: public CCoderInfo2
+#include "CoderMixer2.h"
+
+class CSequentialInStreamCalcSize:
+ public ISequentialInStream,
+ public CMyUnknownImp
{
- bool IsMain;
- CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):
- CCoderInfo2(numInStreams, numOutStreams), IsMain(isMain) {}
+public:
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _size;
+ bool _wasFinished;
+public:
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ _wasFinished = false;
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt64 GetSize() const { return _size; }
+ bool WasFinished() const { return _wasFinished; }
};
-class CCoderMixer2ST:
- public ICompressCoder2,
- public CCoderMixer2,
+
+class COutStreamCalcSize:
+ public ISequentialOutStream,
+ public IOutStreamFlush,
public CMyUnknownImp
{
- MY_UNKNOWN_IMP
-
- HRESULT GetInStream(
- ISequentialInStream **inStreams, const UInt64 **inSizes,
- UInt32 streamIndex, ISequentialInStream **inStreamRes);
- HRESULT GetOutStream(
- ISequentialOutStream **outStreams, const UInt64 **outSizes,
- UInt32 streamIndex, ISequentialOutStream **outStreamRes);
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
public:
- STDMETHOD(Code)(ISequentialInStream **inStreams,
- const UInt64 **inSizes,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 **outSizes,
- UInt32 numOutStreams,
- ICompressProgressInfo *progress);
+ MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFlush)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Flush)();
+
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init() { _size = 0; }
+ UInt64 GetSize() const { return _size; }
+};
- CCoderMixer2ST();
- ~CCoderMixer2ST();
- void AddCoderCommon(bool isMain);
- void AddCoder(ICompressCoder *coder, bool isMain);
- void AddCoder2(ICompressCoder2 *coder, bool isMain);
- void ReInit();
- void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
- {
- { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
- }
- void SetProgressCoderIndex(UInt32 /*coderIndex*/)
- {
- // _progressCoderIndex = coderIndex;
- }
+namespace NCoderMixer2 {
- // UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;
+struct CCoderST: public CCoder
+{
+ bool CanRead;
+ bool CanWrite;
+
+ CCoderST(): CanRead(false), CanWrite(false) {}
+};
+
+
+struct CStBinderStream
+{
+ CSequentialInStreamCalcSize *InStreamSpec;
+ COutStreamCalcSize *OutStreamSpec;
+ CMyComPtr<IUnknown> StreamRef;
+
+ CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
+};
+
+
+class CMixerST:
+ public IUnknown,
+ public CMixer,
+ public CMyUnknownImp
+{
+ HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
+ UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
+ UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
+
+ HRESULT FlushStream(UInt32 streamIndex);
+ HRESULT FlushCoder(UInt32 coderIndex);
-private:
- CBindInfo _bindInfo;
- CObjectVector<CSTCoderInfo> _coders;
- int _mainCoderIndex;
public:
- HRESULT SetBindInfo(const CBindInfo &bindInfo);
+ CObjectVector<CCoderST> _coders;
+
+ CObjectVector<CStBinderStream> _binderStreams;
+
+ MY_UNKNOWN_IMP
+
+ CMixerST(bool encodeMode);
+ ~CMixerST();
+
+ virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
+
+ virtual CCoder &GetCoder(unsigned index);
+
+ virtual void SelectMainCoder(bool useFirst);
+
+ virtual void ReInit();
+
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress);
+
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
+ HRESULT GetMainUnpackStream(
+ ISequentialInStream * const *inStreams,
+ ISequentialInStream **inStreamRes);
};
}
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h
index 9491a965..d2891b26 100644
--- a/CPP/7zip/Archive/Common/CoderMixerMT.h
+++ b/CPP/7zip/Archive/Common/CoderMixerMT.h
@@ -18,7 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread
virtual void Execute();
void Code(ICompressProgressInfo *progress);
- ~CCoder() { CVirtThread::WaitThreadFinish(); }
+ virtual ~CCoder() { CVirtThread::WaitThreadFinish(); }
};
/*
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
index 18ad5580..9c11b31d 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -29,6 +29,7 @@ void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
UInt32 level = _level;
if (level != (UInt32)(Int32)-1)
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
+
#ifndef _7ZIP_ST
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
#endif
@@ -41,6 +42,8 @@ void CMultiMethodProps::Init()
#endif
_level = (UInt32)(Int32)-1;
+ _analysisLevel = -1;
+
_autoFilter = true;
_crcSize = 4;
_filterMethod.Clear();
@@ -60,8 +63,17 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
_level = 9;
return ParsePropToUInt32(name, value, _level);
}
+
+ if (name.IsPrefixedBy_Ascii_NoCase("yx"))
+ {
+ name.Delete(0, 2);
+ UInt32 v = 9;
+ RINOK(ParsePropToUInt32(name, value, v));
+ _analysisLevel = (int)v;
+ return S_OK;
+ }
- if (name == L"crc")
+ if (name.IsEqualTo("crc"))
{
name.Delete(0, 3);
_crcSize = 4;
@@ -73,11 +85,12 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
UString realName = name.Ptr(index);
if (index == 0)
{
- if (name.IsPrefixedBy(L"mt"))
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
#endif
+
return S_OK;
}
if (name.IsEqualTo("f"))
@@ -87,7 +100,7 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
return res;
if (value.vt != VT_BSTR)
return E_INVALIDARG;
- return _filterMethod.ParseMethodFromPROPVARIANT(L"", value);
+ return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);
}
number = 0;
}
@@ -101,14 +114,15 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
void CSingleMethodProps::Init()
{
Clear();
+ _level = (UInt32)(Int32)-1;
+
#ifndef _7ZIP_ST
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
- AddNumThreadsProp(_numThreads);
+ AddProp_NumThreads(_numThreads);
#endif
- _level = (UInt32)(Int32)-1;
}
-HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
Init();
for (UInt32 i = 0; i < numProps; i++)
@@ -123,13 +137,13 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIA
UInt32 a = 9;
RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
_level = a;
- AddLevelProp(a);
+ AddProp_Level(a);
}
- else if (name.IsPrefixedBy(L"mt"))
+ else if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
#ifndef _7ZIP_ST
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
- AddNumThreadsProp(_numThreads);
+ AddProp_NumThreads(_numThreads);
#endif
}
else
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
index 40a4a698..5a18d980 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -10,6 +10,7 @@ namespace NArchive {
class CMultiMethodProps
{
UInt32 _level;
+ int _analysisLevel;
public:
#ifndef _7ZIP_ST
UInt32 _numThreads;
@@ -37,6 +38,7 @@ public:
}
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
+ int GetAnalysisLevel() const { return _analysisLevel; }
void Init();
@@ -57,7 +59,7 @@ public:
void Init();
CSingleMethodProps() { Init(); }
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
- HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
}
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
index 0526c1b1..77252938 100644
--- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
@@ -10,9 +10,9 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr
if (_stream)
result = _stream->Write(data, size, &size);
if (_calculate)
- _sha.Update((const Byte *)data, size);
+ Sha1_Update(&_sha, (const Byte *)data, size);
_size += size;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = size;
return result;
}
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
index 3bbfbbe1..41a84cd6 100644
--- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
@@ -3,7 +3,7 @@
#ifndef __OUT_STREAM_WITH_SHA1_H
#define __OUT_STREAM_WITH_SHA1_H
-#include "../../Crypto/Sha1.h"
+#include "../../../../C/Sha1.h"
#include "../../../Common/MyCom.h"
@@ -15,7 +15,7 @@ class COutStreamWithSha1:
{
CMyComPtr<ISequentialOutStream> _stream;
UInt64 _size;
- NCrypto::NSha1::CContext _sha;
+ CSha1 _sha;
bool _calculate;
public:
MY_UNKNOWN_IMP
@@ -26,11 +26,11 @@ public:
{
_size = 0;
_calculate = calculate;
- _sha.Init();
+ Sha1_Init(&_sha);
}
- void InitSha1() { _sha.Init(); }
+ void InitSha1() { Sha1_Init(&_sha); }
UInt64 GetSize() const { return _size; }
- void Final(Byte *digest) { _sha.Final(digest); }
+ void Final(Byte *digest) { Sha1_Final(&_sha, digest); }
};
#endif
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp
index 431d315d..2436fb5e 100644
--- a/CPP/7zip/Archive/CpioHandler.cpp
+++ b/CPP/7zip/Archive/CpioHandler.cpp
@@ -87,7 +87,7 @@ enum EType
k_Type_HexCrc
};
-static const char *k_Types[] =
+static const char * const k_Types[] =
{
"Binary LE"
, "Binary BE"
@@ -396,11 +396,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, EErrorType &errorType)
return S_FALSE;
if (nameSize == 0 || nameSize >= kNameSizeMax)
return S_OK;
- char *s = item.Name.GetBuffer(nameSize);
+ char *s = item.Name.GetBuf(nameSize);
size_t processedSize = nameSize;
RINOK(Read(s, &processedSize));
- s[nameSize] = 0;
- item.Name.ReleaseBuffer();
+ item.Name.ReleaseBuf_CalcLen(nameSize);
if (processedSize != nameSize)
{
errorType = k_ErrorType_UnexpectedEnd;
@@ -451,7 +450,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
NCOM::CPropVariant prop;
switch (propID)
{
- case kpidSubType: prop = k_Types[_Type]; break;
+ case kpidSubType: prop = k_Types[(unsigned)_Type]; break;
case kpidPhySize: prop = _phySize; break;
case kpidErrorFlags:
{
@@ -780,20 +779,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Cpio", "cpio", 0, 0xED,
- 3 + 5 + 2 + 2,
- {
+static const Byte k_Signature[] = {
5, '0', '7', '0', '7', '0',
2, kMagicBin0, kMagicBin1,
- 2, kMagicBin1, kMagicBin0,
- },
+ 2, kMagicBin1, kMagicBin0 };
+
+REGISTER_ARC_I(
+ "Cpio", "cpio", 0, 0xED,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature,
- CreateArc, NULL, IsArc_Cpio };
-
-REGISTER_ARC(Cpio)
+ IsArc_Cpio)
}}
diff --git a/CPP/7zip/Archive/CramfsHandler.cpp b/CPP/7zip/Archive/CramfsHandler.cpp
index 3764f1af..e776b3c7 100644
--- a/CPP/7zip/Archive/CramfsHandler.cpp
+++ b/CPP/7zip/Archive/CramfsHandler.cpp
@@ -26,8 +26,7 @@ namespace NCramfs {
#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' }
-static const UInt32 kSignatureSize = 16;
-static const char kSignature[kSignatureSize] = SIGNATURE;
+static const Byte kSignature[] = SIGNATURE;
static const UInt32 kArcSizeMax = (256 + 16) << 20;
static const UInt32 kNumFilesMax = (1 << 19);
@@ -55,7 +54,7 @@ static const unsigned k_Flags_Method_Mask = 3;
#define k_Flags_Method_ZLIB 1
#define k_Flags_Method_LZMA 2
-static const char *k_Methods[] =
+static const char * const k_Methods[] =
{
"Copy"
, "ZLIB"
@@ -145,7 +144,7 @@ struct CHeader
bool Parse(const Byte *p)
{
- if (memcmp(p + 16, kSignature, kSignatureSize) != 0)
+ if (memcmp(p + 16, kSignature, ARRAY_SIZE(kSignature)) != 0)
return false;
switch(GetUi32(p))
{
@@ -408,7 +407,7 @@ AString CHandler::GetPath(int index) const
len--;
AString path;
- char *dest = path.GetBuffer(len) + len;
+ char *dest = path.GetBuf_SetEnd(len) + len;
index = indexMem;
for (;;)
{
@@ -425,7 +424,6 @@ AString CHandler::GetPath(int index) const
break;
*(--dest) = CHAR_PATH_SEPARATOR;
}
- path.ReleaseBuffer(len);
return path;
}
@@ -565,10 +563,6 @@ HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSi
return Handler->ReadBlock(blockIndex, dest, blockSize);
}
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
{
if (_method == k_Flags_Method_ZLIB)
@@ -789,15 +783,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "CramFS", "cramfs", 0, 0xD3,
- kSignatureSize, SIGNATURE,
+REGISTER_ARC_I(
+ "CramFS", "cramfs", 0, 0xD3,
+ kSignature,
16,
0,
- CreateArc };
-
-REGISTER_ARC(Cramfs)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/DllExports.cpp b/CPP/7zip/Archive/DllExports.cpp
index 37f53cd7..7aee235e 100644
--- a/CPP/7zip/Archive/DllExports.cpp
+++ b/CPP/7zip/Archive/DllExports.cpp
@@ -13,10 +13,13 @@
#include "../../Windows/NtCheck.h"
#include "../../Windows/PropVariant.h"
-#include "IArchive.h"
#include "../ICoder.h"
#include "../IPassword.h"
+#include "../Common/CreateCoder.h"
+
+#include "IArchive.h"
+
HINSTANCE g_hInstance;
#define NT_CHECK_FAIL_ACTION return FALSE;
@@ -33,7 +36,10 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
}
DEFINE_GUID(CLSID_CArchiveHandler,
-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
+ k_7zip_GUID_Data1,
+ k_7zip_GUID_Data2,
+ k_7zip_GUID_Data3_Common,
+ 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
@@ -49,3 +55,40 @@ STDAPI SetLargePageMode()
#endif
return S_OK;
}
+
+extern bool g_CaseSensitive;
+
+STDAPI SetCaseSensitive(Int32 caseSensitive)
+{
+ g_CaseSensitive = (caseSensitive != 0);
+ return S_OK;
+}
+
+#ifdef EXTERNAL_CODECS
+
+CExternalCodecs g_ExternalCodecs;
+
+STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
+{
+ COM_TRY_BEGIN
+
+ // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL");
+ if (compressCodecsInfo)
+ {
+ g_ExternalCodecs.GetCodecs = compressCodecsInfo;
+ return g_ExternalCodecs.Load();
+ }
+ g_ExternalCodecs.ClearAndRelease();
+ return S_OK;
+
+ COM_TRY_END
+}
+
+#else
+
+STDAPI SetCodecs(ICompressCodecsInfo *)
+{
+ return S_OK;
+}
+
+#endif
diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp
index aa023524..2b196abe 100644
--- a/CPP/7zip/Archive/DllExports2.cpp
+++ b/CPP/7zip/Archive/DllExports2.cpp
@@ -16,6 +16,8 @@
#include "../ICoder.h"
#include "../IPassword.h"
+#include "../Common/CreateCoder.h"
+
#include "IArchive.h"
HINSTANCE g_hInstance;
@@ -33,23 +35,28 @@ BOOL WINAPI DllMain(
{
if (dwReason == DLL_PROCESS_ATTACH)
{
+ // OutputDebugStringA("7z.dll DLL_PROCESS_ATTACH");
g_hInstance = (HINSTANCE)hInstance;
NT_CHECK;
}
+ /*
+ if (dwReason == DLL_PROCESS_DETACH)
+ {
+ OutputDebugStringA("7z.dll DLL_PROCESS_DETACH");
+ }
+ */
return TRUE;
}
DEFINE_GUID(CLSID_CArchiveHandler,
-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
-
-static const UInt16 kDecodeId = 0x2790;
-
-DEFINE_GUID(CLSID_CCodec,
-0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0);
+ k_7zip_GUID_Data1,
+ k_7zip_GUID_Data2,
+ k_7zip_GUID_Data3_Common,
+ 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateHasher(const GUID *clsid, IHasher **hasher);
-STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
+STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
{
@@ -80,3 +87,32 @@ STDAPI SetCaseSensitive(Int32 caseSensitive)
g_CaseSensitive = (caseSensitive != 0);
return S_OK;
}
+
+#ifdef EXTERNAL_CODECS
+
+CExternalCodecs g_ExternalCodecs;
+
+STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
+{
+ COM_TRY_BEGIN
+
+ // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL");
+ if (compressCodecsInfo)
+ {
+ g_ExternalCodecs.GetCodecs = compressCodecsInfo;
+ return g_ExternalCodecs.Load();
+ }
+ g_ExternalCodecs.ClearAndRelease();
+ return S_OK;
+
+ COM_TRY_END
+}
+
+#else
+
+STDAPI SetCodecs(ICompressCodecsInfo *)
+{
+ return S_OK;
+}
+
+#endif
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp
index 7166f2ce..208f2a82 100644
--- a/CPP/7zip/Archive/DmgHandler.cpp
+++ b/CPP/7zip/Archive/DmgHandler.cpp
@@ -48,6 +48,7 @@ static Byte *Base64ToBin(Byte *dest, const char *src)
{
UInt32 val = 1;
UInt32 c = k_Base64Table[(Byte)(*src++)];
+
for (;;)
{
/*
@@ -88,12 +89,14 @@ static Byte *Base64ToBin(Byte *dest, const char *src)
break;
c = k_Base64Table[(Byte)(*src++)];
}
+
if (val >= ((UInt32)1 << 12))
{
if (val >= ((UInt32)1 << 18))
*dest++ = (Byte)(val >> 16);
*dest++ = (Byte)(val);
}
+
return dest;
}
@@ -195,7 +198,8 @@ public:
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};
-const UInt32 kXmlSizeMax = ((UInt32)1 << 31) - (1 << 14);
+// that limit can be increased, if there are such dmg files
+static const size_t kXmlSizeMax = 0xFFFF0000; // 4 GB - 64 KB;
struct CMethods
{
@@ -216,7 +220,9 @@ void CMethods::Update(const CFile &file)
void CMethods::GetString(AString &res) const
{
res.Empty();
+
unsigned i;
+
for (i = 0; i < Types.Size(); i++)
{
UInt32 type = Types[i];
@@ -234,10 +240,10 @@ void CMethods::GetString(AString &res) const
case METHOD_BZIP2: s = "BZip2"; break;
default: ConvertUInt32ToString(type, buf); s = buf;
}
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += s;
}
+
for (i = 0; i < ChecksumTypes.Size(); i++)
{
UInt32 type = ChecksumTypes[i];
@@ -250,8 +256,7 @@ void CMethods::GetString(AString &res) const
ConvertUInt32ToString(type, MyStpCpy(buf, "Check"));
s = buf;
}
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += s;
}
}
@@ -325,8 +330,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidMainSubfile:
{
int mainIndex = -1;
- int numFS = 0;
- int numUnknown = 0;
+ unsigned numFS = 0;
+ unsigned numUnknown = 0;
FOR_VECTOR (i, _files)
{
const AString &name = _files[i].Name;
@@ -334,7 +339,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
for (n = 0; n < kNumAppleNames; n++)
{
const CAppleName &appleName = k_Names[n];
- if (name.Find(appleName.AppleName) >= 0)
+ // if (name.Find(appleName.AppleName) >= 0)
+ if (strstr(name, appleName.AppleName))
{
if (appleName.IsFs)
{
@@ -404,6 +410,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
p += kHeadSize;
UInt32 i;
+
for (i = 0; i < numBlocks; i++, p += kRecordSize)
{
CBlock b;
@@ -426,6 +433,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
if (b.Type == METHOD_END)
break;
PackSize += b.PackSize;
+
if (b.UnpSize != 0)
{
if (b.Type == METHOD_ZERO_2)
@@ -433,12 +441,14 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
Blocks.AddInReserved(b);
}
}
+
if (i != numBlocks - 1)
return S_FALSE;
if (!Blocks.IsEmpty())
Size = Blocks.Back().GetNextUnpPos();
if (Size != (numSectors << 9))
return S_FALSE;
+
return S_OK;
}
@@ -463,8 +473,12 @@ static const AString *GetStringFromKeyPair(const CXmlItem &item, const AString &
static const unsigned HEADER_SIZE = 0x200;
-static bool IsKoly(const Byte *p)
+static const Byte k_Signature[] = { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 };
+
+static inline bool IsKoly(const Byte *p)
{
+ return memcmp(p, k_Signature, ARRAY_SIZE(k_Signature)) == 0;
+ /*
if (Get32(p) != 0x6B6F6C79) // "koly" signature
return false;
if (Get32(p + 4) != 4) // version
@@ -472,6 +486,7 @@ static bool IsKoly(const Byte *p)
if (Get32(p + 8) != HEADER_SIZE)
return false;
return true;
+ */
}
HRESULT CHandler::Open2(IInStream *stream)
@@ -510,6 +525,14 @@ HRESULT CHandler::Open2(IInStream *stream)
UInt64 xmlOffset = Get64(buf + 0xD8);
UInt64 xmlLen = Get64(buf + 0xE0);
+ if ( headerPos < dataForkOffset
+ || headerPos - dataForkOffset < dataForkLen
+ || headerPos < rsrcOffset
+ || headerPos - rsrcOffset < rsrcLen
+ || headerPos < xmlOffset
+ || headerPos - xmlOffset < xmlLen)
+ return S_FALSE;
+
UInt64 totalLen = dataForkLen + rsrcLen + xmlLen;
if (totalLen > headerPos)
return S_FALSE;
@@ -517,14 +540,6 @@ HRESULT CHandler::Open2(IInStream *stream)
_phySize = totalLen + HEADER_SIZE;
headerPos = totalLen;
- if (headerPos < dataForkOffset ||
- headerPos < dataForkOffset + dataForkLen ||
- headerPos < rsrcOffset ||
- headerPos < rsrcOffset + rsrcLen ||
- headerPos < xmlOffset ||
- headerPos < xmlOffset + xmlLen)
- return S_FALSE;
-
// Byte reserved[0x78]
CChecksum masterChecksum;
@@ -620,9 +635,7 @@ HRESULT CHandler::Open2(IInStream *stream)
ConvertUInt32ToString(_files.Size(), extraName);
extra.Name = extraName;
}
- CByteBuffer &rawBuf = extra.Data;
- rawBuf.SetCapacity(blockSize);
- memcpy(rawBuf, pBlock + 4, blockSize);
+ extra.Data.CopyFrom(pBlock + 4, blockSize);
}
#endif
@@ -638,10 +651,10 @@ HRESULT CHandler::Open2(IInStream *stream)
return S_FALSE;
for (UInt32 r = 1; r <= nameLen; r++)
{
- char c = namePtr[r];
+ Byte c = namePtr[r];
if (c < 0x20 || c >= 0x80)
break;
- file.Name += c;
+ file.Name += (char)c;
}
}
RINOK(file.Parse(pBlock + 4, blockSize));
@@ -652,36 +665,28 @@ HRESULT CHandler::Open2(IInStream *stream)
{
if (xmlLen >= kXmlSizeMax || xmlLen == 0)
return S_FALSE;
- RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL));
size_t size = (size_t)xmlLen;
+ if (size != xmlLen)
+ return S_FALSE;
+
+ RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL));
CXml xml;
{
- AString xmlStr;
- char *ss = xmlStr.GetBuffer((int)size + 1);
- RINOK(ReadStream_FALSE(stream, ss, size));
- ss[size] = 0;
- {
- const char *p = ss;
- for (;;)
- {
- if (*p == 0) break; p++;
- if (*p == 0) break; p++;
- if (*p == 0) break; p++;
- if (*p == 0) break; p++;
- }
- xmlStr.ReleaseBuffer((int)(p - ss));
- }
+ CObjArray<char> xmlStr(size + 1);
+ RINOK(ReadStream_FALSE(stream, xmlStr, size));
+ xmlStr[size] = 0;
+ // if (strlen(xmlStr) != size) return S_FALSE;
if (!xml.Parse(xmlStr))
return S_FALSE;
#ifdef DMG_SHOW_RAW
CExtraFile &extra = _extras.AddNew();
extra.Name = "a.xml";
- extra.Data.SetCapacity(size);
- memcpy(extra.Data, ss, size);
+ extra.Data.CopyFrom((const Byte *)(const char *)xmlStr, size);
#endif
}
+
if (xml.Root.Name != "plist")
return S_FALSE;
@@ -708,14 +713,14 @@ HRESULT CHandler::Open2(IInStream *stream)
continue;
CByteBuffer rawBuf;
- int destLen = 0;
+ unsigned destLen = 0;
{
const AString *dataString = GetStringFromKeyPair(item, "Data", "data");
if (!dataString)
return S_FALSE;
destLen = dataString->Len() / 4 * 3 + 4;
rawBuf.Alloc(destLen);
- destLen = (int)(Base64ToBin(rawBuf, *dataString) - rawBuf);
+ destLen = (unsigned)(Base64ToBin(rawBuf, *dataString) - rawBuf);
#ifdef DMG_SHOW_RAW
CExtraFile &extra = _extras.AddNew();
{
@@ -723,8 +728,7 @@ HRESULT CHandler::Open2(IInStream *stream)
ConvertUInt32ToString(_files.Size(), extraName);
extra.Name = extraName;
}
- extra.Data.SetCapacity(destLen);
- memcpy(extra.Data, rawBuf, destLen);
+ extra.Data.CopyFrom(rawBuf, destLen);
#endif
}
CFile &file = _files.AddNew();
@@ -805,7 +809,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
NWindows::NCOM::CPropVariant prop;
#ifdef DMG_SHOW_RAW
- if ((int)index >= _files.Size())
+ if (index >= _files.Size())
{
const CExtraFile &extra = _extras[index - _files.Size()];
switch (propID)
@@ -897,7 +901,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
UString name2;
ConvertUTF8ToUnicode(item.Name, name2);
if (!name2.IsEmpty())
- name += L" - ";
+ name.AddAscii(" - ");
name += name2;
}
prop = name;
@@ -1060,9 +1064,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return S_OK;
UInt64 totalSize = 0;
UInt32 i;
+
for (i = 0; i < numItems; i++)
{
- int index = (int)(allFilesMode ? i : indices[i]);
+ UInt32 index = (allFilesMode ? i : indices[i]);
#ifdef DMG_SHOW_RAW
if (index >= _files.Size())
totalSize += _extras[index - _files.Size()].Data.Size();
@@ -1112,7 +1117,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
- Int32 index = allFilesMode ? i : indices[i];
+ UInt32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if (!testMode && !realOutStream)
@@ -1225,6 +1230,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
opRes = NExtract::NOperationResult::kUnsupportedMethod;
break;
}
+
if (res != S_OK)
{
if (res != S_FALSE)
@@ -1232,7 +1238,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (opRes == NExtract::NOperationResult::kOK)
opRes = NExtract::NOperationResult::kDataError;
}
+
unpPos += block.UnpSize;
+
if (!outStreamSpec->IsFinishedOK())
{
if (realMethod && opRes == NExtract::NOperationResult::kOK)
@@ -1247,6 +1255,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
}
+
if (needCrc && opRes == NExtract::NOperationResult::kOK)
{
if (outCrcStreamSpec->GetCRC() != item.Checksum.GetCrc32())
@@ -1256,6 +1265,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStream.Release();
RINOK(extractCallback->SetOperationResult(opRes));
}
+
return S_OK;
COM_TRY_END
}
@@ -1322,12 +1332,12 @@ public:
};
-int FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
+unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
{
- int left = 0, right = blocks.Size();
+ unsigned left = 0, right = blocks.Size();
for (;;)
{
- int mid = (left + right) / 2;
+ unsigned mid = (left + right) / 2;
if (mid == left)
return left;
if (pos < blocks[mid].UnpPos)
@@ -1359,23 +1369,27 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
if (_virtPos < block.UnpPos || (_virtPos - block.UnpPos) >= block.UnpSize)
_latestBlock = -1;
}
+
if (_latestBlock < 0)
{
_latestChunk = -1;
- int blockIndex = FindBlock(File->Blocks, _virtPos);
+ unsigned blockIndex = FindBlock(File->Blocks, _virtPos);
const CBlock &block = File->Blocks[blockIndex];
+
if (!block.IsZeroMethod() && block.Type != METHOD_COPY)
{
unsigned i;
for (i = 0; i < _chunks.Size(); i++)
- if (_chunks[i].BlockIndex == blockIndex)
+ if (_chunks[i].BlockIndex == (int)blockIndex)
break;
+
if (i != _chunks.Size())
_latestChunk = i;
else
{
- const int kNumChunksMax = 128;
- int chunkIndex;
+ const unsigned kNumChunksMax = 128;
+ unsigned chunkIndex;
+
if (_chunks.Size() != kNumChunksMax)
chunkIndex = _chunks.Add(CChunk());
else
@@ -1385,9 +1399,11 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
if (_chunks[i].AccessMark < _chunks[chunkIndex].AccessMark)
chunkIndex = i;
}
+
CChunk &chunk = _chunks[chunkIndex];
chunk.BlockIndex = -1;
chunk.AccessMark = 0;
+
if (chunk.Buf.Size() < block.UnpSize)
{
chunk.Buf.Free();
@@ -1395,12 +1411,14 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
return E_FAIL;
chunk.Buf.Alloc((size_t)block.UnpSize);
}
+
outStreamSpec->Init(chunk.Buf, (size_t)block.UnpSize);
RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos, STREAM_SEEK_SET, NULL));
limitedStreamSpec->Init(block.PackSize);
HRESULT res = S_OK;
+
switch (block.Type)
{
case METHOD_COPY:
@@ -1443,6 +1461,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
default:
return E_FAIL;
}
+
if (res != S_OK)
return res;
if (block.Type != METHOD_COPY && outStreamSpec->GetPos() != block.UnpSize)
@@ -1450,8 +1469,10 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
chunk.BlockIndex = blockIndex;
_latestChunk = chunkIndex;
}
+
_chunks[_latestChunk].AccessMark = _accessMark++;
}
+
_latestBlock = blockIndex;
}
@@ -1462,6 +1483,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
size = (UInt32)rem;
HRESULT res = S_OK;
+
if (block.Type == METHOD_COPY)
{
RINOK(Stream->Seek(_startPos + File->StartPos + block.PackPos + offset, STREAM_SEEK_SET, NULL));
@@ -1469,11 +1491,13 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
}
else if (block.IsZeroMethod())
memset(data, 0, size);
- else
+ else if (size != 0)
memcpy(data, _chunks[_latestChunk].Buf + offset, size);
+
_virtPos += size;
if (processedSize)
*processedSize = size;
+
return res;
COM_TRY_END
}
@@ -1498,14 +1522,17 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
COM_TRY_BEGIN
+
#ifdef DMG_SHOW_RAW
if (index >= (UInt32)_files.Size())
return S_FALSE;
#endif
+
CInStream *spec = new CInStream;
CMyComPtr<ISequentialInStream> specStream = spec;
spec->File = &_files[index];
const CFile &file = *spec->File;
+
FOR_VECTOR (i, file.Blocks)
{
const CBlock &block = file.Blocks[i];
@@ -1523,24 +1550,22 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
return S_FALSE;
}
}
+
spec->Stream = _inStream;
spec->Size = spec->File->Size;
RINOK(spec->InitAndSeek(_startPos));
*stream = specStream.Detach();
return S_OK;
+
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Dmg", "dmg", 0, 0xE4,
- 12, { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 },
+REGISTER_ARC_I(
+ "Dmg", "dmg", 0, 0xE4,
+ k_Signature,
0,
NArcInfoFlags::kBackwardOpen |
NArcInfoFlags::kUseGlobalOffset,
- CreateArc };
-
-REGISTER_ARC(Dmg)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp
index 5e378ba8..089d1023 100644
--- a/CPP/7zip/Archive/ElfHandler.cpp
+++ b/CPP/7zip/Archive/ElfHandler.cpp
@@ -963,15 +963,13 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' };
-static CArcInfo g_ArcInfo =
- { "ELF", "elf", 0, 0xDE,
- 4, { 0x7F, 'E', 'L', 'F' },
+REGISTER_ARC_I(
+ "ELF", "elf", 0, 0xDE,
+ k_Signature,
0,
NArcInfoFlags::kPreArc,
- CreateArc };
-
-REGISTER_ARC(Elf)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp
index 970330cc..649d54bd 100644
--- a/CPP/7zip/Archive/FatHandler.cpp
+++ b/CPP/7zip/Archive/FatHandler.cpp
@@ -272,19 +272,27 @@ struct CItem
UString GetVolName() const;
};
-static int CopyAndTrim(char *dest, const char *src, int size, bool toLower)
+static unsigned CopyAndTrim(char *dest, const char *src, unsigned size, bool toLower)
{
- int i;
memcpy(dest, src, size);
if (toLower)
- for (i = 0; i < size; i++)
+ {
+ for (unsigned i = 0; i < size; i++)
{
char c = dest[i];
if (c >= 'A' && c <= 'Z')
dest[i] = (char)(c + 0x20);
}
- for (i = size - 1; i >= 0 && dest[i] == ' '; i--);
- return i + 1;
+ }
+
+ for (unsigned i = size;;)
+ {
+ if (i == 0)
+ return 0;
+ if (dest[i - 1] != ' ')
+ return i;
+ i--;
+ }
}
static UString FatStringToUnicode(const char *s)
@@ -295,11 +303,11 @@ static UString FatStringToUnicode(const char *s)
UString CItem::GetShortName() const
{
char s[16];
- int i = CopyAndTrim(s, DosName, 8, NameIsLow());
+ unsigned i = CopyAndTrim(s, DosName, 8, NameIsLow());
s[i++] = '.';
- int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow());
+ unsigned j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow());
if (j == 0)
- j--;
+ i--;
s[i + j] = 0;
return FatStringToUnicode(s);
}
@@ -316,7 +324,7 @@ UString CItem::GetVolName() const
if (!UName.IsEmpty())
return UName;
char s[12];
- int i = CopyAndTrim(s, DosName, 11, false);
+ unsigned i = CopyAndTrim(s, DosName, 11, false);
s[i] = 0;
return FatStringToUnicode(s);
}
@@ -348,7 +356,7 @@ struct CDatabase
UString GetItemPath(Int32 index) const;
HRESULT Open();
- HRESULT ReadDir(Int32 parent, UInt32 cluster, int level);
+ HRESULT ReadDir(Int32 parent, UInt32 cluster, unsigned level);
UInt64 GetHeadersSize() const
{
@@ -420,9 +428,9 @@ UString CDatabase::GetItemPath(Int32 index) const
}
}
-static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars)
+static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, unsigned numChars)
{
- for (int i = 0; i < numChars; i++)
+ for (unsigned i = 0; i < numChars; i++)
{
wchar_t c = Get16(p + i * 2);
if (c != 0 && c != 0xFFFF)
@@ -432,9 +440,9 @@ static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars)
return dest;
}
-HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
+HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
{
- int startIndex = Items.Size();
+ unsigned startIndex = Items.Size();
if (startIndex >= (1 << 30) || level > 256)
return S_FALSE;
@@ -451,6 +459,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
UString curName;
int checkSum = -1;
int numLongRecords = -1;
+
for (UInt32 pos = blockSize;; pos += 32)
{
if (pos == blockSize)
@@ -483,7 +492,9 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));
}
+
const Byte *p = ByteBuf + pos;
+
if (p[0] == 0)
{
/*
@@ -493,6 +504,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
*/
break;
}
+
if (p[0] == 0xE5)
{
if (numLongRecords > 0)
@@ -545,7 +557,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
if (checkSum >= 0)
{
Byte sum = 0;
- for (int i = 0; i < 11; i++)
+ for (unsigned i = 0; i < 11; i++)
sum = (Byte)(((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i]);
if (sum == checkSum)
item.UName = curName;
@@ -590,8 +602,8 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
}
}
- int finishIndex = Items.Size();
- for (int i = startIndex; i < finishIndex; i++)
+ unsigned finishIndex = Items.Size();
+ for (unsigned i = startIndex; i < finishIndex; i++)
{
const CItem &item = Items[i];
if (item.IsDir())
@@ -831,7 +843,7 @@ static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVari
}
/*
-static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop)
+static void StringToProp(const Byte *src, unsigned size, NWindows::NCOM::CPropVariant &prop)
{
char dest[32];
memcpy(dest, src, size);
@@ -1021,15 +1033,13 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0x55, 0xAA };
-static CArcInfo g_ArcInfo =
- { "FAT", "fat img", 0, 0xDA,
- 2, { 0x55, 0xAA },
+REGISTER_ARC_I(
+ "FAT", "fat img", 0, 0xDA,
+ k_Signature,
0x1FE,
0,
- CreateArc, NULL, IsArc_Fat };
-
-REGISTER_ARC(Fat)
+ IsArc_Fat)
}}
diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp
index 577224b2..dafb250b 100644
--- a/CPP/7zip/Archive/FlvHandler.cpp
+++ b/CPP/7zip/Archive/FlvHandler.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
@@ -69,12 +71,12 @@ class CHandler:
{
CMyComPtr<IInStream> _stream;
CObjectVector<CItem2> _items2;
- // CByteBuffer _metadata;
+ CByteBuffer _metadata;
bool _isRaw;
UInt64 _phySize;
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
- AString GetComment();
+ // AString GetComment();
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
@@ -195,10 +197,7 @@ AString CHandler::GetComment()
break;
{
AString temp;
- char *sz = temp.GetBuffer(len);
- memcpy(sz, p, len);
- sz[len] = 0;
- temp.ReleaseBuffer();
+ temp.SetFrom_CalcLen((const char *)p, len);
if (!res.IsEmpty())
res += '\n';
res += temp;
@@ -251,7 +250,6 @@ AString CHandler::GetComment()
}
return res;
}
-
*/
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
@@ -413,8 +411,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
src += kTagHeaderSize + 1;
size -= (kTagHeaderSize + 4 + 1);
}
- memcpy(item2.BufSpec->Buf + item2.Size, src, size);
- item2.Size += size;
+ if (size != 0)
+ {
+ memcpy(item2.BufSpec->Buf + item2.Size, src, size);
+ item2.Size += size;
+ }
}
return S_OK;
}
@@ -513,15 +514,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'F', 'L', 'V', 1, };
-static CArcInfo g_ArcInfo =
- { "FLV", "flv", 0, 0xD6,
- 4, { 'F', 'L', 'V', 1, },
+REGISTER_ARC_I(
+ "FLV", "flv", 0, 0xD6,
+ k_Signature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Flv)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp
index 766cefbf..d8979ada 100644
--- a/CPP/7zip/Archive/GzHandler.cpp
+++ b/CPP/7zip/Archive/GzHandler.cpp
@@ -44,10 +44,10 @@ namespace NGz {
namespace NFlags
{
- const Byte kIsText = 1 << 0;
- const Byte kCrc = 1 << 1;
- const Byte kExtra = 1 << 2;
- const Byte kName = 1 << 3;
+ const Byte kIsText = 1 << 0;
+ const Byte kCrc = 1 << 1;
+ const Byte kExtra = 1 << 2;
+ const Byte kName = 1 << 3;
const Byte kComment = 1 << 4;
const Byte kReserved = 0xE0;
}
@@ -85,7 +85,7 @@ namespace NGz {
};
}
-static const char *kHostOSes[] =
+static const char * const kHostOSes[] =
{
"FAT"
, "AMIGA"
@@ -126,19 +126,44 @@ public:
AString Comment;
// CByteBuffer Extra;
- // bool IsText() const { return TestFlag(NFlags::kIsText); }
- bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); }
- bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); }
- bool NameIsPresent() const { return TestFlag(NFlags::kName); }
- bool CommentIsPresent() const { return TestFlag(NFlags::kComment); }
- bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; }
+ CItem():
+ Flags(0),
+ ExtraFlags(0),
+ HostOS(0),
+ Time(0),
+ Crc(0),
+ Size32(0) {}
void Clear()
{
Name.Empty();
Comment.Empty();
- // Extra.SetCapacity(0);
+ // Extra.Free();
+ }
+
+ void CopyMetaPropsFrom(const CItem &a)
+ {
+ Flags = a.Flags;
+ HostOS = a.HostOS;
+ Time = a.Time;
+ Name = a.Name;
+ Comment = a.Comment;
+ // Extra = a.Extra;
+ }
+
+ void CopyDataPropsFrom(const CItem &a)
+ {
+ ExtraFlags = a.ExtraFlags;
+ Crc = a.Crc;
+ Size32 = a.Size32;
}
+
+ // bool IsText() const { return TestFlag(NFlags::kIsText); }
+ bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); }
+ bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); }
+ bool NameIsPresent() const { return TestFlag(NFlags::kName); }
+ bool CommentIsPresent() const { return TestFlag(NFlags::kComment); }
+ bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; }
HRESULT ReadHeader(NDecoder::CCOMCoder *stream);
HRESULT ReadFooter1(NDecoder::CCOMCoder *stream);
@@ -459,7 +484,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
CHandler()
{
@@ -510,7 +535,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
case kpidName:
if (_item.NameIsPresent())
- prop = MultiByteToUnicodeString(_item.Name, CP_ACP) + L".gz";
+ {
+ UString s = MultiByteToUnicodeString(_item.Name, CP_ACP);
+ s.AddAscii(".gz");
+ prop = s;
+ }
break;
}
prop.Detach(value);
@@ -656,7 +685,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
- // if (_stream) extractCallback->SetTotal(_packSize);
+ if (_packSize_Defined)
+ extractCallback->SetTotal(_packSize);
// UInt64 currentTotalPacked = 0;
// RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
@@ -794,6 +824,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
result = S_FALSE;
break;
}
+
+ // break; // we can use break, if we need only first stream
}
} catch(const CInBufferException &e) { return e.ErrorCode; }
@@ -844,7 +876,7 @@ static const Byte kHostOS =
static HRESULT UpdateArchive(
ISequentialOutStream *outStream,
UInt64 unpackSize,
- const CItem &newItem,
+ CItem &item,
const CSingleMethodProps &props,
IArchiveUpdateCallback *updateCallback)
{
@@ -865,7 +897,6 @@ static HRESULT UpdateArchive(
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
- CItem item = newItem;
item.ExtraFlags = props.GetLevel() >= 7 ?
NExtraFlags::kMaximum :
NExtraFlags::kFastest;
@@ -894,6 +925,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
+ COM_TRY_BEGIN
+
if (numItems != 1)
return E_INVALIDARG;
@@ -903,11 +936,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_FAIL;
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
- CItem newItem = _item;
- newItem.ExtraFlags = 0;
- newItem.Flags = 0;
- if (IntToBool(newProps))
+ CItem newItem;
+
+ if (!IntToBool(newProps))
+ {
+ newItem.CopyMetaPropsFrom(_item);
+ }
+ else
{
+ newItem.HostOS = kHostOS;
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidMTime, &prop));
@@ -924,9 +961,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (prop.vt == VT_BSTR)
{
UString name = prop.bstrVal;
- int dirDelimiterPos = name.ReverseFind(WCHAR_PATH_SEPARATOR);
- if (dirDelimiterPos >= 0)
- name = name.Ptr(dirDelimiterPos + 1);
+ int slashPos = name.ReverseFind_PathSepar();
+ if (slashPos >= 0)
+ name.DeleteFrontal(slashPos + 1);
newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);
if (!newItem.Name.IsEmpty())
newItem.Flags |= NFlags::kName;
@@ -937,13 +974,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
- if (prop.vt == VT_BOOL)
- {
- if (prop.boolVal != VARIANT_FALSE)
+ if (prop.vt != VT_EMPTY)
+ if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
return E_INVALIDARG;
- }
- else if (prop.vt != VT_EMPTY)
- return E_INVALIDARG;
}
}
@@ -959,13 +992,28 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
return UpdateArchive(outStream, size, newItem, _props, updateCallback);
}
-
+
if (indexInArchive != 0)
return E_INVALIDARG;
if (!_stream)
return E_NOTIMPL;
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, 0,
+ NUpdateNotifyOp::kReplicate))
+ }
+
+ newItem.CopyDataPropsFrom(_item);
+
UInt64 offset = 0;
if (IntToBool(newProps))
{
@@ -973,24 +1021,24 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
offset += _headerSize;
}
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
- return NCompress::CopyStream(_stream, outStream, NULL);
+
+ return NCompress::CopyStream(_stream, outStream, progress);
+
+ COM_TRY_END
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
return _props.SetProperties(names, values, numProps);
}
-IMP_CreateArcIn
-IMP_CreateArcOut
+static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 };
-static CArcInfo g_ArcInfo =
- { "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF,
- 3, { kSignature_0, kSignature_1, kSignature_2 },
+REGISTER_ARC_IO(
+ "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF,
+ k_Signature,
0,
NArcInfoFlags::kKeepName,
- REF_CreateArc_Pair, IsArc_Gz };
-
-REGISTER_ARC(GZip)
+ IsArc_Gz)
}}
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp
index ca1370d8..8459280d 100644
--- a/CPP/7zip/Archive/HfsHandler.cpp
+++ b/CPP/7zip/Archive/HfsHandler.cpp
@@ -28,7 +28,7 @@
namespace NArchive {
namespace NHfs {
-static const wchar_t *kResFileName = L"rsrc"; // L"com.apple.ResourceFork";
+static const char *kResFileName = "rsrc"; // "com.apple.ResourceFork";
struct CExtent
{
@@ -655,12 +655,17 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec
static void LoadName(const Byte *data, unsigned len, UString &dest)
{
- wchar_t *p = dest.GetBuffer(len);
+ wchar_t *p = dest.GetBuf(len);
unsigned i;
for (i = 0; i < len; i++)
- p[i] = Get16(data + i * 2);
+ {
+ wchar_t c = Get16(data + i * 2);
+ if (c == 0)
+ break;
+ p[i] = c;
+ }
p[i] = 0;
- dest.ReleaseBuffer();
+ dest.ReleaseBuf_SetLen(i);
}
static bool IsNameEqualTo(const Byte *data, const char *name)
@@ -805,7 +810,7 @@ static const UInt32 kMethod_Resource = 4; // data stored in resource fork
bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip)
{
skip = false;
- if (attr.Name != L"com.apple.decmpfs")
+ if (!attr.Name.IsEqualTo("com.apple.decmpfs"))
return true;
if (item.UseAttr || !item.DataFork.IsEmpty())
return false;
@@ -961,13 +966,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
IsNameEqualTo(name + 8, "HFS+ Private Data"))
{
// it's folder for "Hard Links" files
- item.Name = L"[HFS+ Private Data]";
+ item.Name.SetFromAscii("[HFS+ Private Data]");
}
}
// Some dmg files have ' ' folder item.
if (item.Name.IsEmpty() || item.Name[0] == L' ')
- item.Name = L"[]";
+ item.Name.SetFromAscii("[]");
}
}
@@ -1221,7 +1226,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
return S_FALSE;
*/
- ResFileName = kResFileName;
+ ResFileName.SetFromAscii(kResFileName);
CFork extentsFork, catalogFork, attrFork;
// allocationFork.Parse(p + 0x70 + 0x50 * 0);
@@ -1856,19 +1861,15 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
return GetForkStream(item.GetFork(ref.IsResource), stream);
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "HFS", "hfs hfsx", 0, 0xE3,
- 2 * (4 + 1),
- {
+static const Byte k_Signature[] = {
4, 'H', '+', 0, 4,
- 4, 'H', 'X', 0, 5,
- },
+ 4, 'H', 'X', 0, 5 };
+
+REGISTER_ARC_I(
+ "HFS", "hfs hfsx", 0, 0xE3,
+ k_Signature,
kHeaderPadSize,
NArcInfoFlags::kMultiSignature,
- CreateArc };
-
-REGISTER_ARC(Hfs)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
index a57a9b8f..84a4cc4b 100644
--- a/CPP/7zip/Archive/IArchive.h
+++ b/CPP/7zip/Archive/IArchive.h
@@ -82,10 +82,22 @@ namespace NArchive
kUnexpectedEnd,
kDataAfterEnd,
kIsNotArc,
- kHeadersError
+ kHeadersError,
+ kWrongPassword
};
}
}
+
+ namespace NEventIndexType
+ {
+ enum
+ {
+ kNoIndex = 0,
+ kInArcIndex,
+ kBlockIndex,
+ kOutArcIndex
+ };
+ }
namespace NUpdate
{
@@ -110,17 +122,59 @@ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
};
/*
-IArchiveExtractCallback::GetStream
- Result:
+IArchiveExtractCallback::
+
+7-Zip doesn't call IArchiveExtractCallback functions
+ GetStream()
+ PrepareOperation()
+ SetOperationResult()
+from different threads simultaneously.
+But 7-Zip can call functions for IProgress or ICompressProgressInfo functions
+from another threads simultaneously with calls for IArchiveExtractCallback interface.
+
+IArchiveExtractCallback::GetStream()
+ UInt32 index - index of item in Archive
+ Int32 askExtractMode (Extract::NAskMode)
+ if (askMode != NExtract::NAskMode::kExtract)
+ {
+ then the callee can not real stream: (*inStream == NULL)
+ }
+
+ Out:
(*inStream == NULL) - for directories
(*inStream == NULL) - if link (hard link or symbolic link) was created
+ if (*inStream == NULL && askMode == NExtract::NAskMode::kExtract)
+ {
+ then the caller must skip extracting of that file.
+ }
+
+ returns:
+ S_OK : OK
+ S_FALSE : data error (for decoders)
+
+if (IProgress::SetTotal() was called)
+{
+ IProgress::SetCompleted(completeValue) uses
+ packSize - for some stream formats (xz, gz, bz2, lzma, z, ppmd).
+ unpackSize - for another formats.
+}
+else
+{
+ IProgress::SetCompleted(completeValue) uses packSize.
+}
+
+SetOperationResult()
+ 7-Zip calls SetOperationResult at the end of extracting,
+ so the callee can close the file, set attributes, timestamps and security information.
+
+ Int32 opRes (NExtract::NOperationResult)
*/
#define INTERFACE_IArchiveExtractCallback(x) \
INTERFACE_IProgress(x) \
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \
STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \
- STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \
+ STDMETHOD(SetOperationResult)(Int32 opRes) x; \
ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
{
@@ -128,6 +182,25 @@ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
};
+
+/*
+IArchiveExtractCallbackMessage can be requested from IArchiveExtractCallback object
+ by Extract() or UpdateItems() functions to report about extracting errors
+ReportExtractResult()
+ UInt32 indexType (NEventIndexType)
+ UInt32 index
+ Int32 opRes (NExtract::NOperationResult)
+*/
+
+#define INTERFACE_IArchiveExtractCallbackMessage(x) \
+ STDMETHOD(ReportExtractResult)(UInt32 indexType, UInt32 index, Int32 opRes) x; \
+
+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21)
+{
+ INTERFACE_IArchiveExtractCallbackMessage(PURE)
+};
+
+
#define INTERFACE_IArchiveOpenVolumeCallback(x) \
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \
@@ -183,9 +256,6 @@ Notes:
Some IInArchive handlers will work incorrectly in that case.
*/
-/* MSVC allows the code where there is throw() in declaration of function,
- but there is no throw() in definition of function. */
-
#ifdef _MSC_VER
#define MY_NO_THROW_DECL_ONLY throw()
#else
@@ -202,7 +272,7 @@ Notes:
STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \
STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \
- STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x;
+ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \
ARCHIVE_INTERFACE(IInArchive, 0x60)
{
@@ -324,6 +394,8 @@ The order of calling for hard links:
- GetStream()
- GetProperty(kpidHardLink)
+SetOperationResult()
+ Int32 opRes (NExtract::NOperationResult::kOK)
*/
#define INTERFACE_IArchiveUpdateCallback(x) \
@@ -348,6 +420,40 @@ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
INTERFACE_IArchiveUpdateCallback2(PURE);
};
+namespace NUpdateNotifyOp
+{
+ enum
+ {
+ kAdd = 0,
+ kUpdate,
+ kAnalyze,
+ kReplicate,
+ kRepack,
+ kSkip,
+ kDelete,
+ kHeader
+
+ // kNumDefined
+ };
+};
+
+/*
+IArchiveUpdateCallbackFile::ReportOperation
+ UInt32 indexType (NEventIndexType)
+ UInt32 index
+ UInt32 notifyOp (NUpdateNotifyOp)
+*/
+
+#define INTERFACE_IArchiveUpdateCallbackFile(x) \
+ STDMETHOD(GetStream2)(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp) x; \
+ STDMETHOD(ReportOperation)(UInt32 indexType, UInt32 index, UInt32 notifyOp) x; \
+
+ARCHIVE_INTERFACE(IArchiveUpdateCallbackFile, 0x83)
+{
+ INTERFACE_IArchiveUpdateCallbackFile(PURE);
+};
+
+
/*
UpdateItems()
-------------
@@ -382,7 +488,7 @@ ARCHIVE_INTERFACE(IOutArchive, 0xA0)
ARCHIVE_INTERFACE(ISetProperties, 0x03)
{
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) PURE;
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE;
};
ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04)
diff --git a/CPP/7zip/Archive/IhexHandler.cpp b/CPP/7zip/Archive/IhexHandler.cpp
index 00816f0c..00ff80a7 100644
--- a/CPP/7zip/Archive/IhexHandler.cpp
+++ b/CPP/7zip/Archive/IhexHandler.cpp
@@ -85,7 +85,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CBlock &block = _blocks[index];
switch (propID)
{
- case kpidSize: prop = block.Data.GetPos(); break;
+ case kpidSize: prop = (UInt64)block.Data.GetPos(); break;
case kpidVa: prop = block.Offset; break;
case kpidPath:
{
@@ -103,7 +103,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
-static inline int HexToByte(char c)
+static inline int HexToByte(unsigned c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
@@ -138,9 +138,9 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)
p++;
size--;
- const int kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection
+ const unsigned kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection
- for (int j = 0; j < kNumLinesToCheck; j++)
+ for (unsigned j = 0; j < kNumLinesToCheck; j++)
{
if (size < 4 * 2)
return k_IsArc_Res_NEED_MORE;
@@ -279,7 +279,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
}
{
- size_t numPairs = (num + 4);
+ size_t numPairs = ((unsigned)num + 4);
size_t numBytes = numPairs * 2;
if (s.ReadBytes(temp, numBytes) != numBytes)
{
@@ -287,7 +287,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
return S_FALSE;
}
- int sum = num;
+ unsigned sum = num;
for (size_t i = 0; i < numPairs; i++)
{
int a = Parse(temp + i * 2);
@@ -339,7 +339,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
block = &_blocks.AddNew();
block->Offset = offs;
}
- memcpy(block->Data.GetCurPtrAndGrow(num), temp + 3, num);
+ block->Data.AddData(temp + 3, (unsigned)num);
}
}
else if (type == kType_Eof)
@@ -486,16 +486,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
+// k_Signature: { ':', '1' }
-static CArcInfo g_ArcInfo =
- { "IHex", "ihex", 0, 0xCD,
- 0, { 0 },
- // 2, { ':', '1' },
+REGISTER_ARC_I_NO_SIG(
+ "IHex", "ihex", 0, 0xCD,
0,
NArcInfoFlags::kStartOpen,
- CreateArc, NULL, IsArc_Ihex };
-
-REGISTER_ARC(Z)
+ IsArc_Ihex)
}}
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
index aef920b0..713764d9 100644
--- a/CPP/7zip/Archive/Iso/IsoHandler.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp
@@ -79,8 +79,7 @@ static void AddString(AString &s, const char *name, const Byte *p, unsigned size
if (i != 0)
{
AString d;
- memcpy(d.GetBuffer(i), p, i);
- d.ReleaseBuffer(i);
+ d.SetFrom((const char *)p, i);
s += '\n';
s += name;
s += ": ";
@@ -170,11 +169,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
- // char name[16];
- // ConvertUInt32ToString(index + 1, name);
AString s = "[BOOT]" STRING_PATH_SEPARATOR;
- // s += name;
- // s += '-';
+ if (_archive.BootEntries.Size() != 1)
+ {
+ char temp[16];
+ ConvertUInt32ToString(index + 1, temp);
+ s += temp;
+ s += '-';
+ }
s += be.GetName();
prop = s;
break;
@@ -197,18 +199,18 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString s;
if (_archive.IsJoliet())
- s = item.GetPathU();
+ item.GetPathU(s);
else
s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP);
- int pos = s.ReverseFind(L';');
- if (pos >= 0 && pos == (int)s.Len() - 2)
- if (s.Back() == L'1')
- s.DeleteFrom(pos);
- if (!s.IsEmpty())
- if (s.Back() == L'.')
- s.DeleteBack();
- prop = (const wchar_t *)NItemName::GetOSName2(s);
+ if (s.Len() >= 2 && s[s.Len() - 2] == ';' && s.Back() == '1')
+ s.DeleteFrom(s.Len() - 2);
+
+ if (!s.IsEmpty() && s.Back() == L'.')
+ s.DeleteBack();
+
+ NItemName::ConvertToOSName2(s);
+ prop = s;
}
break;
case kpidIsDir: prop = item.IsDir(); break;
@@ -319,8 +321,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 offset = 0;
for (UInt32 e = 0; e < ref.NumExtents; e++)
{
- if (e != 0)
- lps->InSize = lps->OutSize = currentTotalSize + offset;
+ lps->InSize = lps->OutSize = currentTotalSize + offset;
const CDir &item2 = ref.Dir->_subItems[ref.Index + e];
RINOK(_stream->Seek((UInt64)item2.ExtentLocation * _archive.BlockSize, STREAM_SEEK_SET, NULL));
streamSpec->Init(item2.Size);
@@ -356,6 +357,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
*stream = 0;
UInt64 blockIndex;
UInt64 currentItemSize;
+
if (index < (UInt32)_archive.Refs.Size())
{
const CRef &ref = _archive.Refs[index];
@@ -402,6 +404,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
currentItemSize = _archive.GetBootItemSize(bootIndex);
blockIndex = be.LoadRBA;
}
+
return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream);
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp
index 1cd2516c..59c283c1 100644
--- a/CPP/7zip/Archive/Iso/IsoHeader.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp
@@ -9,13 +9,4 @@ namespace NIso {
const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0";
-const char *kMediaTypes[5] =
-{
- "NoEmulation"
- , "1.2M"
- , "1.44M"
- , "2.88M"
- , "HardDisk"
-};
-
}}
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h
index ce21b0ff..db0b1df9 100644
--- a/CPP/7zip/Archive/Iso/IsoHeader.h
+++ b/CPP/7zip/Archive/Iso/IsoHeader.h
@@ -34,6 +34,11 @@ namespace NBootEntryId
const Byte kValidationEntry = 1;
const Byte kInitialEntryNotBootable = 0;
const Byte kInitialEntryBootable = 0x88;
+
+ const Byte kMoreHeaders = 0x90;
+ const Byte kFinalHeader = 0x91;
+
+ const Byte kExtensionIndicator = 0x44;
}
namespace NBootPlatformId
@@ -54,9 +59,6 @@ namespace NBootMediaType
const Byte kHardDisk = 4;
}
-const unsigned kNumBootMediaTypes = 5;
-extern const char *kMediaTypes[];
-
}}
#endif
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp
index ba12acae..b72e8687 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.cpp
+++ b/CPP/7zip/Archive/Iso/IsoIn.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../../C/CpuArch.h"
+
#include "../../../Common/MyException.h"
#include "../../Common/StreamUtils.h"
@@ -10,11 +12,78 @@
namespace NArchive {
namespace NIso {
-
+
struct CUnexpectedEndException {};
struct CHeaderErrorException {};
struct CEndianErrorException {};
+static const char * const kMediaTypes[] =
+{
+ "NoEmul"
+ , "1.2M"
+ , "1.44M"
+ , "2.88M"
+ , "HardDisk"
+};
+
+bool CBootInitialEntry::Parse(const Byte *p)
+{
+ Bootable = (p[0] == NBootEntryId::kInitialEntryBootable);
+ BootMediaType = p[1];
+ LoadSegment = GetUi16(p + 2);
+ SystemType = p[4];
+ SectorCount = GetUi16(p + 6);
+ LoadRBA = GetUi32(p + 8);
+ memcpy(VendorSpec, p + 12, 20);
+ if (p[5] != 0)
+ return false;
+ if (p[0] != NBootEntryId::kInitialEntryBootable
+ && p[0] != NBootEntryId::kInitialEntryNotBootable)
+ return false;
+ return true;
+}
+
+AString CBootInitialEntry::GetName() const
+{
+ AString s = (Bootable ? "Boot" : "NotBoot");
+ s += '-';
+
+ if (BootMediaType < ARRAY_SIZE(kMediaTypes))
+ s += kMediaTypes[BootMediaType];
+ else
+ {
+ char name[16];
+ ConvertUInt32ToString(BootMediaType, name);
+ s += name;
+ }
+
+ if (VendorSpec[0] == 1)
+ {
+ // "Language and Version Information (IBM)"
+
+ unsigned i;
+ for (i = 1; i < sizeof(VendorSpec); i++)
+ if (VendorSpec[i] > 0x7F)
+ break;
+ if (i == sizeof(VendorSpec))
+ {
+ s += '-';
+ for (i = 1; i < sizeof(VendorSpec); i++)
+ {
+ char c = VendorSpec[i];
+ if (c == 0)
+ break;
+ if (c == '\\' || c == '/')
+ c = '_';
+ s += c;
+ }
+ }
+ }
+
+ s += ".img";
+ return s;
+}
+
Byte CInArchive::ReadByte()
{
if (m_BufferPos >= BlockSize)
@@ -58,15 +127,6 @@ void CInArchive::SkipZeros(size_t size)
}
}
-UInt16 CInArchive::ReadUInt16Spec()
-{
- UInt16 val = 0;
- for (int i = 0; i < 2; i++)
- val |= ((UInt16)(ReadByte()) << (8 * i));
- return val;
-}
-
-
UInt16 CInArchive::ReadUInt16()
{
Byte b[4];
@@ -179,15 +239,15 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
Byte idLen = ReadByte();
r.FileId.Alloc(idLen);
ReadBytes((Byte *)r.FileId, idLen);
- int padSize = 1 - (idLen & 1);
+ unsigned padSize = 1 - (idLen & 1);
- // SkipZeros(1 - (idLen & 1));
- Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros
+ // SkipZeros(padSize);
+ Skip(padSize); // it's bug in some cd's. Must be zeros
- int curPos = 33 + idLen + padSize;
+ unsigned curPos = 33 + idLen + padSize;
if (curPos > len)
throw CHeaderErrorException();
- int rem = len - curPos;
+ unsigned rem = len - curPos;
r.SystemUse.Alloc(rem);
ReadBytes((Byte *)r.SystemUse, rem);
}
@@ -349,45 +409,94 @@ void CInArchive::ReadBootInfo()
{
if (!_bootIsDefined)
return;
+ HeadersError = true;
+
if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)
return;
- const Byte *p = (const Byte *)_bootDesc.BootSystemUse;
- UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24);
+ UInt32 blockIndex = GetUi32(_bootDesc.BootSystemUse);
SeekToBlock(blockIndex);
- Byte b = ReadByte();
- if (b != NBootEntryId::kValidationEntry)
+
+ Byte buf[32];
+ ReadBytes(buf, 32);
+
+ if (buf[0] != NBootEntryId::kValidationEntry
+ || buf[2] != 0
+ || buf[3] != 0
+ || buf[30] != 0x55
+ || buf[31] != 0xAA)
return;
+
{
+ UInt32 sum = 0;
+ for (unsigned i = 0; i < 32; i += 2)
+ sum += GetUi16(buf + i);
+ if ((sum & 0xFFFF) != 0)
+ return;
+ /*
CBootValidationEntry e;
- e.PlatformId = ReadByte();
- if (ReadUInt16Spec() != 0)
- throw CHeaderErrorException();
- ReadBytes(e.Id, sizeof(e.Id));
- /* UInt16 checkSum = */ ReadUInt16Spec();
- if (ReadByte() != 0x55)
- throw CHeaderErrorException();
- if (ReadByte() != 0xAA)
- throw CHeaderErrorException();
+ e.PlatformId = buf[1];
+ memcpy(e.Id, buf + 4, sizeof(e.Id));
+ // UInt16 checkSum = GetUi16(p + 28);
+ */
}
- b = ReadByte();
- if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable)
+
+ ReadBytes(buf, 32);
{
CBootInitialEntry e;
- e.Bootable = (b == NBootEntryId::kInitialEntryBootable);
- e.BootMediaType = ReadByte();
- e.LoadSegment = ReadUInt16Spec();
- e.SystemType = ReadByte();
- if (ReadByte() != 0)
- throw CHeaderErrorException();
- e.SectorCount = ReadUInt16Spec();
- e.LoadRBA = ReadUInt32Le();
- if (ReadByte() != 0)
- throw CHeaderErrorException();
+ if (!e.Parse(buf))
+ return;
BootEntries.Add(e);
}
- else
- return;
+
+ bool error = false;
+
+ for (;;)
+ {
+ ReadBytes(buf, 32);
+ Byte headerIndicator = buf[0];
+ if (headerIndicator != NBootEntryId::kMoreHeaders
+ && headerIndicator != NBootEntryId::kFinalHeader)
+ break;
+
+ // Section Header
+ // Byte platform = p[1];
+ unsigned numEntries = GetUi16(buf + 2);
+ // id[28]
+
+ for (unsigned i = 0; i < numEntries; i++)
+ {
+ ReadBytes(buf, 32);
+ CBootInitialEntry e;
+ if (!e.Parse(buf))
+ {
+ error = true;
+ break;
+ }
+ if (e.BootMediaType & (1 << 5))
+ {
+ // Section entry extension
+ for (unsigned j = 0;; j++)
+ {
+ ReadBytes(buf, 32);
+ if (j > 32 || buf[0] != NBootEntryId::kExtensionIndicator)
+ {
+ error = true;
+ break;
+ }
+ if ((buf[1] & (1 << 5)) == 0)
+ break;
+ // info += (buf + 2, 30)
+ }
+ }
+ BootEntries.Add(e);
+ }
+
+ if (headerIndicator != NBootEntryId::kMoreHeaders)
+ break;
+ }
+
+ HeadersError = error;
}
HRESULT CInArchive::Open2()
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h
index 614b3744..c2007bce 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.h
+++ b/CPP/7zip/Archive/Iso/IsoIn.h
@@ -25,77 +25,92 @@ struct CDir: public CDirRecord
_subItems.Clear();
}
- unsigned GetLen(bool checkSusp, unsigned skipSize) const
- {
- unsigned len = GetLenCur(checkSusp, skipSize);
- if (Parent != 0)
- if (Parent->Parent != 0)
- len += 1 + Parent->GetLen(checkSusp, skipSize);
- return len;
- }
-
- unsigned GetLenU() const
- {
- unsigned len = (unsigned)(FileId.Size() / 2);
- if (Parent != 0)
- if (Parent->Parent != 0)
- len += 1 + Parent->GetLenU();
- return len;
- }
-
AString GetPath(bool checkSusp, unsigned skipSize) const
{
AString s;
- unsigned len = GetLen(checkSusp, skipSize);
- char *p = s.GetBuffer(len);
- p += len;
- *p = 0;
+
+ unsigned len = 0;
const CDir *cur = this;
+
for (;;)
{
- unsigned curLen = cur->GetLenCur(checkSusp, skipSize);
- p -= curLen;
- memcpy(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen);
+ unsigned curLen;
+ cur->GetNameCur(checkSusp, skipSize, curLen);
+ len += curLen;
cur = cur->Parent;
- if (cur == 0)
+ if (!cur || !cur->Parent)
break;
- if (cur->Parent == 0)
+ len++;
+ }
+
+ char *p = s.GetBuf_SetEnd(len) + len;
+
+ cur = this;
+
+ for (;;)
+ {
+ unsigned curLen;
+ const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen);
+ p -= curLen;
+ if (curLen != 0)
+ memcpy(p, name, curLen);
+ cur = cur->Parent;
+ if (!cur || !cur->Parent)
break;
p--;
*p = CHAR_PATH_SEPARATOR;
}
- s.ReleaseBuffer();
+
return s;
}
- UString GetPathU() const
+ void GetPathU(UString &s) const
{
- UString s;
- unsigned len = GetLenU();
- wchar_t *p = s.GetBuffer(len);
- p += len;
- *p = 0;
+ s.Empty();
+
+ unsigned len = 0;
const CDir *cur = this;
+
for (;;)
{
unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
- p -= curLen;
- for (unsigned i = 0; i < curLen; i++)
- {
- Byte b0 = ((const Byte *)cur->FileId)[i * 2];
- Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1];
- p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1);
- }
+ const Byte *fid = cur->FileId;
+
+ unsigned i;
+ for (i = 0; i < curLen; i++)
+ if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
+ break;
+ len += i;
cur = cur->Parent;
- if (cur == 0)
+ if (!cur || !cur->Parent)
break;
- if (cur->Parent == 0)
+ len++;
+ }
+
+ wchar_t *p = s.GetBuf_SetEnd(len) + len;
+
+ cur = this;
+
+ for (;;)
+ {
+ unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
+ const Byte *fid = cur->FileId;
+
+ unsigned i;
+ for (i = 0; i < curLen; i++)
+ if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
+ break;
+ curLen = i;
+
+ p -= curLen;
+ for (i = 0; i < curLen; i++)
+ p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]);
+ cur = cur->Parent;
+ if (!cur || !cur->Parent)
break;
p--;
*p = WCHAR_PATH_SEPARATOR;
}
- s.ReleaseBuffer();
- return s;
}
};
@@ -109,6 +124,7 @@ struct CDateTime
Byte Second;
Byte Hundredths;
signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
+
bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
@@ -118,7 +134,7 @@ struct CDateTime
bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value);
if (res)
{
- value -= (UInt64)((Int64)GmtOffset * 15 * 60);
+ value -= (Int64)((Int32)GmtOffset * 15 * 60);
value *= 10000000;
}
ft.dwLowDateTime = (DWORD)value;
@@ -157,27 +173,16 @@ struct CBootInitialEntry
UInt32 LoadRBA; // This is the start address of the virtual disk. CD’s use
// Relative/Logical block addressing.
- UInt64 GetSize() const
+ Byte VendorSpec[20];
+
+ UInt32 GetSize() const
{
// if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);
- return SectorCount * 512;
+ return (UInt32)SectorCount * 512;
}
- AString GetName() const
- {
- AString s = (Bootable ? "Bootable" : "NotBootable");
- s += '_';
- if (BootMediaType < kNumBootMediaTypes)
- s += kMediaTypes[BootMediaType];
- else
- {
- char name[16];
- ConvertUInt32ToString(BootMediaType, name);
- s += name;
- }
- s += ".img";
- return s;
- }
+ bool Parse(const Byte *p);
+ AString GetName() const;
};
struct CVolumeDescriptor
@@ -247,7 +252,6 @@ class CInArchive
void SkipZeros(size_t size);
Byte ReadByte();
void ReadBytes(Byte *data, UInt32 size);
- UInt16 ReadUInt16Spec();
UInt16 ReadUInt16();
UInt32 ReadUInt32Le();
UInt32 ReadUInt32Be();
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h
index b6ae21b7..2603afdb 100644
--- a/CPP/7zip/Archive/Iso/IsoItem.h
+++ b/CPP/7zip/Archive/Iso/IsoItem.h
@@ -29,7 +29,7 @@ struct CRecordingDateTime
bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value);
if (res)
{
- value -= (UInt64)((Int64)GmtOffset * 15 * 60);
+ value -= (Int64)((Int32)GmtOffset * 15 * 60);
value *= 10000000;
}
ft.dwLowDateTime = (DWORD)value;
@@ -94,28 +94,23 @@ struct CDirRecord
return 0;
}
- unsigned GetLenCur(bool checkSusp, int skipSize) const
+ const Byte* GetNameCur(bool checkSusp, int skipSize, unsigned &nameLenRes) const
{
+ const Byte *res = NULL;
+ unsigned len = 0;
if (checkSusp)
+ res = FindSuspName(skipSize, len);
+ if (!res)
{
- unsigned len;
- const Byte *res = FindSuspName(skipSize, len);
- if (res != 0)
- return len;
+ res = (const Byte *)FileId;
+ len = (unsigned)FileId.Size();
}
- return (unsigned)FileId.Size();
- }
-
- const Byte* GetNameCur(bool checkSusp, int skipSize) const
- {
- if (checkSusp)
- {
- unsigned len;
- const Byte *res = FindSuspName(skipSize, len);
- if (res != 0)
- return res;
- }
- return (const Byte *)FileId;
+ unsigned i;
+ for (i = 0; i < len; i++)
+ if (res[i] == 0)
+ break;
+ nameLenRes = i;
+ return res;
}
diff --git a/CPP/7zip/Archive/Iso/IsoRegister.cpp b/CPP/7zip/Archive/Iso/IsoRegister.cpp
index c6f4a521..0205238d 100644
--- a/CPP/7zip/Archive/Iso/IsoRegister.cpp
+++ b/CPP/7zip/Archive/Iso/IsoRegister.cpp
@@ -9,15 +9,13 @@
namespace NArchive {
namespace NIso {
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'C', 'D', '0', '0', '1' };
-static CArcInfo g_ArcInfo =
- { "Iso", "iso img", 0, 0xE7,
- 5, { 'C', 'D', '0', '0', '1' },
+REGISTER_ARC_I(
+ "Iso", "iso img", 0, 0xE7,
+ k_Signature,
NArchive::NIso::kStartPos + 1,
0,
- CreateArc };
-
-REGISTER_ARC(Iso)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp
index ef4b4196..c8d3ff6d 100644
--- a/CPP/7zip/Archive/LzhHandler.cpp
+++ b/CPP/7zip/Archive/LzhHandler.cpp
@@ -660,8 +660,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;
CMyComPtr<ICompressCoder> lzhDecoder;
- CMyComPtr<ICompressCoder> lzh1Decoder;
- CMyComPtr<ICompressCoder> arj2Decoder;
+ // CMyComPtr<ICompressCoder> lzh1Decoder;
+ // CMyComPtr<ICompressCoder> arj2Decoder;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
@@ -736,8 +736,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
lzhDecoder = lzhDecoderSpec;
}
- lzhDecoderSpec->SetDictionary(item.GetNumDictBits());
+ lzhDecoderSpec->FinishMode = true;
+ lzhDecoderSpec->SetDictSize(1 << item.GetNumDictBits());
result = lzhDecoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
+ if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
+ result = S_FALSE;
}
/*
else if (item.IsLh1GroupMethod())
@@ -773,15 +776,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { '-', 'l', 'h' };
-static CArcInfo g_ArcInfo =
- { "Lzh", "lzh lha", 0, 6,
- 3, { '-', 'l', 'h' },
+REGISTER_ARC_I(
+ "Lzh", "lzh lha", 0, 6,
+ k_Signature,
2,
0,
- CreateArc, NULL, IsArc_Lzh };
-
-REGISTER_ARC(Lzh)
+ IsArc_Lzh)
}}
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
index 04aa4685..e4ac2a42 100644
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -9,11 +9,12 @@
#include "../../Windows/PropVariant.h"
-#include "../Common/CreateCoder.h"
+#include "../Common/FilterCoder.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
+#include "../Compress/BcjCoder.h"
#include "../Compress/LzmaDecoder.h"
#include "Common/DummyOutStream.h"
@@ -75,14 +76,14 @@ bool CHeader::Parse(const Byte *buf, bool isThereFilter)
class CDecoder
{
- CMyComPtr<ICompressCoder> _lzmaDecoder;
CMyComPtr<ISequentialOutStream> _bcjStream;
+ CFilterCoder *_filterCoder;
+ CMyComPtr<ICompressCoder> _lzmaDecoder;
public:
NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
~CDecoder();
- HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS
- bool filtered, ISequentialInStream *inStream);
+ HRESULT Create(bool filtered, ISequentialInStream *inStream);
HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
@@ -94,11 +95,7 @@ public:
{ return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }
};
-static const UInt32 k_BCJ = 0x03030103;
-
-HRESULT CDecoder::Create(
- DECL_EXTERNAL_CODECS_LOC_VARS
- bool filteredMode, ISequentialInStream *inStream)
+HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
{
if (!_lzmaDecoder)
{
@@ -111,13 +108,10 @@ HRESULT CDecoder::Create(
{
if (!_bcjStream)
{
- CMyComPtr<ICompressCoder> coder;
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false));
- if (!coder)
- return E_NOTIMPL;
- coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream);
- if (!_bcjStream)
- return E_NOTIMPL;
+ _filterCoder = new CFilterCoder(false);
+ CMyComPtr<ICompressCoder> coder = _filterCoder;
+ _filterCoder->Filter = new CBcjCoder(false);
+ _bcjStream = _filterCoder;
}
}
@@ -143,17 +137,13 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));
}
- CMyComPtr<ICompressSetOutStream> setOutStream;
-
bool filteredMode = (header.FilterID == 1);
if (filteredMode)
{
- _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
- if (!setOutStream)
- return E_NOTIMPL;
- RINOK(setOutStream->SetOutStream(outStream));
+ RINOK(_filterCoder->SetOutStream(outStream));
outStream = _bcjStream;
+ RINOK(_filterCoder->SetOutStreamSize(NULL));
}
const UInt64 *Size = header.HasSize() ? &header.Size : NULL;
@@ -161,18 +151,16 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
if (filteredMode)
{
- CMyComPtr<IOutStreamFlush> flush;
- _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush);
- if (flush)
{
- HRESULT res2 = flush->Flush();
+ HRESULT res2 = _filterCoder->OutStreamFinish();
if (res == S_OK)
res = res2;
}
- HRESULT res2 = setOutStream->ReleaseOutStream();
+ HRESULT res2 = _filterCoder->ReleaseOutStream();
if (res == S_OK)
res = res2;
}
+
RINOK(res);
if (header.HasSize())
@@ -186,7 +174,6 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
- PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
CHeader _header;
@@ -210,15 +197,8 @@ class CHandler:
UInt64 _unpackSize;
UInt64 _numStreams;
- DECL_EXTERNAL_CODECS_VARS
- DECL_ISetCompressCodecsInfo
-
public:
- MY_QUERYINTERFACE_BEGIN2(IInArchive)
- MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
- QUERY_ENTRY_ISetCompressCodecsInfo
- MY_QUERYINTERFACE_END
- MY_ADDREF_RELEASE
+ MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
INTERFACE_IInArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
@@ -427,6 +407,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
+
if (numItems == 0)
return S_OK;
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
@@ -466,9 +447,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
_needSeekToStart = true;
CDecoder decoder;
- HRESULT result = decoder.Create(
- EXTERNAL_CODECS_VARS
- _lzma86, _seqStream);
+ HRESULT result = decoder.Create(_lzma86, _seqStream);
RINOK(result);
bool firstItem = true;
@@ -562,43 +541,33 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStream.Release();
return extractCallback->SetOperationResult(opResult);
+
COM_TRY_END
}
-IMPL_ISetCompressCodecsInfo
-
namespace NLzmaAr {
-IMP_CreateArcIn_2(CHandler(false))
+// 2, { 0x5D, 0x00 },
-static CArcInfo g_ArcInfo =
- { "lzma", "lzma", 0, 0xA,
- 0, { 0 },
- // 2, { 0x5D, 0x00 },
+REGISTER_ARC_I_CLS_NO_SIG(
+ CHandler(false),
+ "lzma", "lzma", 0, 0xA,
0,
NArcInfoFlags::kStartOpen |
NArcInfoFlags::kKeepName,
- CreateArc, NULL,
- IsArc_Lzma };
-
-REGISTER_ARC(Lzma)
-
+ IsArc_Lzma)
+
}
namespace NLzma86Ar {
-IMP_CreateArcIn_2(CHandler(true))
-
-static CArcInfo g_ArcInfo =
- { "lzma86", "lzma86", 0, 0xB,
- 0, { 0 },
+REGISTER_ARC_I_CLS_NO_SIG(
+ CHandler(true),
+ "lzma86", "lzma86", 0, 0xB,
0,
NArcInfoFlags::kKeepName,
- CreateArc, NULL,
- IsArc_Lzma86 };
-
-REGISTER_ARC(Lzma86)
-
+ IsArc_Lzma86)
+
}
}}
diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp
index 11ff9703..00dc571b 100644
--- a/CPP/7zip/Archive/MachoHandler.cpp
+++ b/CPP/7zip/Archive/MachoHandler.cpp
@@ -42,7 +42,7 @@ namespace NMacho {
#define CPU_SUBTYPE_POWERPC_970 100
-static const char *k_PowerPc_SubTypes[] =
+static const char * const k_PowerPc_SubTypes[] =
{
NULL
, "601"
@@ -297,7 +297,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
ConvertUInt32ToString(t, temp);
n = temp;
}
- s += ' ';
+ s.Add_Space();
s += n;
}
prop = s;
@@ -310,7 +310,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString s = FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags);
if (!s.IsEmpty())
{
- res += ' ';
+ res.Add_Space();
res += s;
}
prop = res;
@@ -354,7 +354,7 @@ static AString SectFlagsToString(UInt32 flags)
AString s = FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), flags & SECT_ATTR_MASK);
if (!s.IsEmpty())
{
- res += ' ';
+ res.Add_Space();
res += s;
}
return res;
@@ -643,22 +643,18 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = {
+ 4, 0xCE, 0xFA, 0xED, 0xFE,
+ 4, 0xCF, 0xFA, 0xED, 0xFE,
+ 4, 0xFE, 0xED, 0xFA, 0xCE,
+ 4, 0xFE, 0xED, 0xFA, 0xCF };
-#define k_Signature { \
- 4, 0xCE, 0xFA, 0xED, 0xFE, \
- 4, 0xCF, 0xFA, 0xED, 0xFE, \
- 4, 0xFE, 0xED, 0xFA, 0xCE, \
- 4, 0xFE, 0xED, 0xFA, 0xCF }
-
-static CArcInfo g_ArcInfo =
- { "MachO", "macho", 0, 0xDF,
- 4 * 5, k_Signature,
+REGISTER_ARC_I(
+ "MachO", "macho", 0, 0xDF,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kPreArc,
- CreateArc };
-
-REGISTER_ARC(Macho)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp
index abc981f3..c4e4cc60 100644
--- a/CPP/7zip/Archive/MbrHandler.cpp
+++ b/CPP/7zip/Archive/MbrHandler.cpp
@@ -169,7 +169,7 @@ static const CPartType kPartTypes[] =
static int FindPartType(UInt32 type)
{
- for (int i = 0; i < ARRAY_SIZE(kPartTypes); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(kPartTypes); i++)
if (kPartTypes[i].Id == type)
return i;
return -1;
@@ -193,19 +193,19 @@ class CHandler:
UInt64 _totalSize;
CByteBuffer _buffer;
- HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level);
+ HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};
-HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level)
+HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level)
{
if (level >= 128 || _items.Size() >= 128)
return S_FALSE;
- const int kNumHeaderParts = 4;
+ const unsigned kNumHeaderParts = 4;
CPartition parts[kNumHeaderParts];
{
@@ -221,7 +221,7 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int
if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
return S_FALSE;
- for (int i = 0; i < kNumHeaderParts; i++)
+ for (unsigned i = 0; i < kNumHeaderParts; i++)
if (!parts[i].Parse(buf + 0x1BE + 16 * i))
return S_FALSE;
}
@@ -232,13 +232,13 @@ HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int
if (limLba == 0)
return S_FALSE;
- for (int i = 0; i < kNumHeaderParts; i++)
+ for (unsigned i = 0; i < kNumHeaderParts; i++)
{
CPartition &part = parts[i];
if (part.IsEmpty())
continue;
- PRF(printf("\n %2d ", (int)level));
+ PRF(printf("\n %2d ", (unsigned)level));
#ifdef SHOW_DEBUG_INFO
part.Print();
#endif
@@ -402,8 +402,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
int typeIndex = FindPartType(part.Type);
s += '.';
const char *ext = "img";
- if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0)
- ext = kPartTypes[typeIndex].Ext;
+ if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext)
+ ext = kPartTypes[(unsigned)typeIndex].Ext;
s += ext;
}
prop = s;
@@ -416,8 +416,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
ConvertUInt32ToString(part.Type, s);
const char *res = s;
int typeIndex = FindPartType(part.Type);
- if (typeIndex >= 0 && kPartTypes[typeIndex].Name)
- res = kPartTypes[typeIndex].Name;
+ if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Name)
+ res = kPartTypes[(unsigned)typeIndex].Name;
prop = res;
}
break;
@@ -499,17 +499,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-static CArcInfo g_ArcInfo =
- { "MBR", "mbr", 0, 0xDB,
// 3, { 1, 1, 0 },
// 2, { 0x55, 0x1FF },
- 0, { 0 },
+
+REGISTER_ARC_I_NO_SIG(
+ "MBR", "mbr", 0, 0xDB,
0,
NArcInfoFlags::kPureStartOpen,
- CreateArc };
-
-REGISTER_ARC(Mbr)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp
index cb124c40..ec375733 100644
--- a/CPP/7zip/Archive/MslzHandler.cpp
+++ b/CPP/7zip/Archive/MslzHandler.cpp
@@ -111,11 +111,13 @@ static const unsigned kHeaderSize = kSignatureSize + 1 + 4;
static const Byte kSignature[kSignatureSize] = MSLZ_SIGNATURE;
// we support only 3 chars strings here
-static const char *g_Exts[] =
+static const char * const g_Exts[] =
{
- "dll"
+ "bin"
+ , "dll"
, "exe"
, "kmd"
+ , "pdf"
, "sys"
};
@@ -147,14 +149,15 @@ void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback)
for (unsigned i = 0; i < ARRAY_SIZE(g_Exts); i++)
{
const char *ext = g_Exts[i];
- if (s[s.Len() - 2] == ext[0] &&
- s[s.Len() - 1] == ext[1])
+ if (s[s.Len() - 2] == (Byte)ext[0] &&
+ s[s.Len() - 1] == (Byte)ext[1])
{
replaceByte = ext[2];
break;
}
}
}
+
if (replaceByte >= 0x20 && replaceByte < 0x80)
_name += (wchar_t)replaceByte;
}
@@ -225,6 +228,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
Byte buf[kBufSize];
UInt32 dest = 0;
memset(buf, ' ', kBufSize);
+
while (dest < unpackSize)
{
Byte b;
@@ -233,6 +237,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
needMoreData = true;
return S_FALSE;
}
+
for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1)
{
if (!inStream.ReadByte(b))
@@ -240,6 +245,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
needMoreData = true;
return S_FALSE;
}
+
if (mask & 1)
{
buf[dest++ & kMask] = b;
@@ -258,6 +264,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
unsigned len = (b1 & 0xF) + 3;
if (len > kMaxLen || dest + len > unpackSize)
return S_FALSE;
+
do
{
buf[dest++ & kMask] = buf[src++ & kMask];
@@ -267,6 +274,7 @@ static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UIn
}
}
}
+
if (outStream)
RINOK(WriteStream(outStream, buf, dest & kMask));
return S_OK;
@@ -379,15 +387,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "MsLZ", "mslz", 0, 0xD5,
- kSignatureSize, MSLZ_SIGNATURE,
+REGISTER_ARC_I(
+ "MsLZ", "mslz", 0, 0xD5,
+ kSignature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Mslz)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp
index 39f8de27..a84c3120 100644
--- a/CPP/7zip/Archive/MubHandler.cpp
+++ b/CPP/7zip/Archive/MubHandler.cpp
@@ -292,22 +292,18 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
namespace NBe {
-static CArcInfo g_ArcInfo =
- { "Mub", "mub", 0, 0xE2,
- 2 + 7 + 4,
- {
+static const Byte k_Signature[] = {
7, 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0,
- 4, 0xB9, 0xFA, 0xF1, 0x0E
- },
+ 4, 0xB9, 0xFA, 0xF1, 0x0E };
+
+REGISTER_ARC_I(
+ "Mub", "mub", 0, 0xE2,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature,
- CreateArc };
-
-REGISTER_ARC(Mub)
+ NULL)
}
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
index bb73d273..68243129 100644
--- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
@@ -7,7 +7,6 @@
#include "NsisDecode.h"
#include "../../Common/CreateCoder.h"
-#include "../../Common/FilterCoder.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/MethodId.h"
@@ -58,18 +57,11 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
{
if (!_filterInStream)
{
- CFilterCoder *coderSpec = new CFilterCoder;
- CMyComPtr<ICompressCoder> coder = coderSpec;
- coderSpec->Filter = new CBCJ_x86_Decoder();
- coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);
- if (!_filterInStream)
- return E_NOTIMPL;
+ _filter = new CFilterCoder(false);
+ _filterInStream = _filter;
+ _filter->Filter = new CBcjCoder(false);
}
- CMyComPtr<ICompressSetInStream> setInStream;
- _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);
- if (!setInStream)
- return E_NOTIMPL;
- RINOK(setInStream->SetInStream(_codecInStream));
+ RINOK(_filter->SetInStream(_codecInStream));
_decoderInStream = _filterInStream;
}
@@ -99,13 +91,7 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
if (useFilter)
{
- /*
- CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
- _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
- if (!setOutStreamSize)
- return E_NOTIMPL;
- RINOK(setOutStreamSize->SetOutStreamSize(NULL));
- */
+ RINOK(_filter->SetOutStreamSize(NULL));
}
return S_OK;
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h
index 0b95d4b2..7b22181e 100644
--- a/CPP/7zip/Archive/Nsis/NsisDecode.h
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.h
@@ -5,6 +5,7 @@
#include "../../../Common/MyBuffer.h"
+#include "../../Common/FilterCoder.h"
#include "../../Common/StreamUtils.h"
#include "../../Compress/LzmaDecoder.h"
@@ -31,6 +32,7 @@ class CDecoder
{
NMethodType::EEnum _curMethod; // method of created decoder
+ CFilterCoder *_filter;
CMyComPtr<ISequentialInStream> _filterInStream;
CMyComPtr<ISequentialInStream> _codecInStream;
CMyComPtr<ISequentialInStream> _decoderInStream;
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
index 233edd52..971c8464 100644
--- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
@@ -26,7 +26,7 @@ namespace NNsis {
static const char *kBcjMethod = "BCJ";
static const char *kUnknownMethod = "Unknown";
-static const char *kMethods[] =
+static const char * const kMethods[] =
{
"Copy"
, "Deflate"
@@ -84,9 +84,9 @@ static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
if (useFilter)
{
s += kBcjMethod;
- s += ' ';
+ s.Add_Space();
}
- s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
+ s += ((unsigned)method < ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod;
if (method == NMethodType::kLZMA)
{
s += ':';
@@ -102,7 +102,7 @@ AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt3
if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
{
s += kBcjMethod;
- s += ' ';
+ s.Add_Space();
}
s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
if (method == NMethodType::kLZMA)
@@ -126,8 +126,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString s = _archive.GetFormatDescription();
if (!_archive.IsInstaller)
{
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
s += "(Uninstall)";
}
if (!s.IsEmpty())
@@ -138,8 +137,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidMethod: prop = _methodString; break;
case kpidSolid: prop = _archive.IsSolid; break;
case kpidOffset: prop = _archive.StartOffset; break;
- case kpidPhySize: prop = _archive.ExeStub.Size() + _archive.FirstHeader.ArcSize; break;
- case kpidEmbeddedStubSize: prop = _archive.ExeStub.Size(); break;
+ case kpidPhySize: prop = (UInt64)((UInt64)_archive.ExeStub.Size() + _archive.FirstHeader.ArcSize); break;
+ case kpidEmbeddedStubSize: prop = (UInt64)_archive.ExeStub.Size(); break;
case kpidHeadersSize: prop = _archive.FirstHeader.HeaderSize; break;
case kpidErrorFlags:
@@ -611,7 +610,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
HRESULT res = _archive.Decoder.Decode(
writeToTemp1 ? &tempBuf : NULL,
item.IsUninstaller, item.PatchSize,
- item.IsUninstaller ? NULL : realOutStream,
+ item.IsUninstaller ? NULL : (ISequentialOutStream *)realOutStream,
progress,
curPacked, curUnpacked32);
curUnpacked = curUnpacked32;
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp
index dc570ec2..6ca87df4 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp
@@ -20,7 +20,7 @@ namespace NNsis {
static const size_t kInputBufSize = 1 << 20;
-static const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
+const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
static const UInt32 kMask_IsCompressed = (UInt32)1 << 31;
static const unsigned kNumCommandParams = 6;
@@ -30,7 +30,7 @@ static const unsigned kCmdSize = 4 + kNumCommandParams * 4;
#define CR_LF "\x0D\x0A"
#endif
-static const char *kErrorStr = "$_ERROR_STR_";
+static const char * const kErrorStr = "$_ERROR_STR_";
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
@@ -244,7 +244,7 @@ static const CCommandInfo k_Commands[kNumCmds] =
#ifdef NSIS_SCRIPT
-static const char *k_CommandNames[kNumCmds] =
+static const char * const k_CommandNames[kNumCmds] =
{
"Invalid"
, NULL // Return
@@ -331,7 +331,7 @@ static const char *k_CommandNames[kNumCmds] =
Some NSIS shell names are not identical to WIN32 CSIDL_* names.
NSIS doesn't use some CSIDL_* values. But we add name for all CSIDL_ (marked with '+'). */
-static const char *kShellStrings[] =
+static const char * const kShellStrings[] =
{
"DESKTOP" // +
, "INTERNET" // +
@@ -526,7 +526,7 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID)
#define kVar_Spec_OUTDIR 31 // NSIS 2.26+
-static const char *kVarStrings[] =
+static const char * const kVarStrings[] =
{
"CMDLINE"
, "INSTDIR"
@@ -963,8 +963,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
else // if (c == PARK_CODE_LANG)
Add_LangStr(Raw_AString, n);
}
- for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++)
- Raw_UString += *s;
+ Raw_UString.AddAscii(Raw_AString);
continue;
}
c = n;
@@ -1010,8 +1009,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
else // if (c == NS_3_CODE_LANG)
Add_LangStr(Raw_AString, n);
}
- for (const Byte *s = (const Byte *)(const char *)Raw_AString; *s != 0; s++)
- Raw_UString += (wchar_t)*s;
+ Raw_UString.AddAscii(Raw_AString);
}
}
@@ -1147,8 +1145,7 @@ void CInArchive::ReadString2_Raw(UInt32 pos)
GetNsisString_Raw(_data + _stringsPos + pos);
return;
}
- for (const char *s = (const char *)Raw_AString; *s != 0; s++)
- Raw_UString += *s;
+ Raw_UString.SetFromAscii(Raw_AString);
}
bool CInArchive::IsGoodString(UInt32 param) const
@@ -1417,7 +1414,7 @@ static const char *g_WinAttrib[] =
#define FLAGS_DELIMITER '|'
-static void FlagsToString2(CDynLimBuf &s, const char **table, unsigned num, UInt32 flags)
+static void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned num, UInt32 flags)
{
bool filled = false;
for (unsigned i = 0; i < num; i++)
@@ -1536,7 +1533,7 @@ inline bool IsProbablyEndOfFunc(UInt32 flag)
return (flag != 0 && flag != CMD_REF_Goto);
}
-static const char *kOnFunc[] =
+static const char * const kOnFunc[] =
{
"Init"
, "InstSuccess"
@@ -1622,12 +1619,12 @@ static bool NoLabels(const UInt32 *labels, UInt32 num)
return true;
}
-static const char *k_REBOOTOK = " /REBOOTOK";
+static const char * const k_REBOOTOK = " /REBOOTOK";
#define MY__MB_ABORTRETRYIGNORE 2
#define MY__MB_RETRYCANCEL 5
-static const char *k_MB_Buttons[] =
+static const char * const k_MB_Buttons[] =
{
"OK"
, "OKCANCEL"
@@ -1640,7 +1637,7 @@ static const char *k_MB_Buttons[] =
#define MY__MB_ICONSTOP (1 << 4)
-static const char *k_MB_Icons[] =
+static const char * const k_MB_Icons[] =
{
NULL
, "ICONSTOP"
@@ -1649,7 +1646,7 @@ static const char *k_MB_Icons[] =
, "ICONINFORMATION"
};
-static const char *k_MB_Flags[] =
+static const char * const k_MB_Flags[] =
{
"HELP"
, "NOFOCUS"
@@ -1664,7 +1661,7 @@ static const char *k_MB_Flags[] =
#define MY__IDCANCEL 2
#define MY__IDIGNORE 5
-static const char *k_Button_IDs[] =
+static const char * const k_Button_IDs[] =
{
"0"
, "IDOK"
@@ -1702,31 +1699,6 @@ bool CInArchive::IsDirectString_Equal(UInt32 offset, const char *s) const
return strcmp((const char *)(const Byte *)_data + _stringsPos + offset, s) == 0;
}
-static UInt32 ConvertHexStringToUInt32(const char *s, const char **end)
-{
- UInt32 result = 0;
- for (int i = 0; i < 8; i++)
- {
- char c = *s;
- UInt32 v;
- if (c >= '0' && c <= '9') v = (c - '0');
- else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
- else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');
- else
- {
- if (end != NULL)
- *end = s;
- return result;
- }
- result <<= 4;
- result |= v;
- s++;
- }
- if (end != NULL)
- *end = s;
- return 0;
-}
-
static bool StringToUInt32(const char *s, UInt32 &res)
{
const char *end;
@@ -1816,7 +1788,7 @@ void CInArchive::Add_Color(UInt32 v)
#define MY__SW_SHOWMINNOACTIVE 7
#define MY__SW_SHOWNA 8
-static const char *kShowWindow_Commands[] =
+static const char * const kShowWindow_Commands[] =
{
"HIDE"
, "SHOWNORMAL" // "NORMAL"
@@ -1854,7 +1826,7 @@ void CInArchive::Add_ShowWindow_Cmd(UInt32 cmd)
Add_UInt(cmd);
}
-void CInArchive::Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type)
+void CInArchive::Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type)
{
if (type < tableSize)
Script += table[type];
@@ -1886,7 +1858,7 @@ enum
};
// Names for NSIS exec_flags_t structure vars
-static const char *kExecFlags_VarsNames[] =
+static const char * const kExecFlags_VarsNames[] =
{
"AutoClose" // autoclose;
, "ShellVarContext" // all_user_var;
@@ -1940,7 +1912,7 @@ enum
PWP_CUSTOM
};
-static const char *kPageTypes[] =
+static const char * const kPageTypes[] =
{
"license"
, "components"
@@ -2062,7 +2034,7 @@ void CInArchive::AddStringLF(const char *s)
// ---------- Section ----------
-static const char *kSection_VarsNames[] =
+static const char * const kSection_VarsNames[] =
{
"Text"
, "InstTypes"
@@ -2240,7 +2212,7 @@ void CInArchive::NewLine()
static const UInt32 kPageSize = 16 * 4;
-static const char *k_SetOverwrite_Modes[] =
+static const char * const k_SetOverwrite_Modes[] =
{
"on"
, "off"
@@ -2294,7 +2266,7 @@ void CInArchive::MessageBox_MB_Part(UInt32 param)
else if (modal == 2) Script += "|MB_TASKMODAL";
else if (modal == 3) Script += "|0x3000";
UInt32 flags = (param >> 14);
- for (int i = 0; i < ARRAY_SIZE(k_MB_Flags); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(k_MB_Flags); i++)
if ((flags & (1 << i)) != 0)
{
Script += "|MB_";
@@ -2327,8 +2299,7 @@ static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2;
static void AddString(AString &dest, const char *src)
{
- if (!dest.IsEmpty())
- dest += ' ';
+ dest.Add_Space_if_NotEmpty();
dest += src;
}
@@ -3133,7 +3104,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
}
default: continue;
}
- for (int i = 0; mask != 0; i++, mask >>= 1)
+ for (unsigned i = 0; mask != 0; i++, mask >>= 1)
if (mask & 1)
{
UInt32 param = Get32(p + 4 + 4 * i);
@@ -3535,17 +3506,11 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
pars[i] = Get32(p2 + i * 4 + 4);
if (pars[0] == 10 + 4 && pars[2] == 0 && pars[3] == 0) // 10 + 4 means $R4
{
- ReadString2_Raw(pars[1]);
- if (IsUnicode)
- {
- if (!Raw_UString.IsEmpty())
- item.NameU = Raw_UString;
- }
- else
- {
- if (!Raw_AString.IsEmpty())
- item.NameA = Raw_AString;
- }
+ item.Prefix = -1;
+ item.NameA.Empty();
+ item.NameU.Empty();
+ SetItemName(item, pars[1]);
+ // maybe here we can restore original item name, if new name is empty
}
}
}
@@ -5011,7 +4976,7 @@ HRESULT CInArchive::SortItems()
#define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256
#define CH_FLAGS_NO_CUSTOM 512
-static const char *k_PostStrings[] =
+static const char * const k_PostStrings[] =
{
"install_directory_auto_append"
, "uninstchild" // NSIS 2.25+, used by uninstaller:
@@ -5242,7 +5207,7 @@ HRESULT CInArchive::Parse()
AddRegRoot(rootKey);
AddParam(subKey);
AddParam(value);
- NewLine();
+ AddLF();
}
}
@@ -5296,6 +5261,9 @@ HRESULT CInArchive::Parse()
UInt32 langtable_size = Get32(p2 + 32);
if (bhLangTables.Num > 0)
{
+ if (langtable_size == (UInt32)(Int32)-1)
+ return E_NOTIMPL; // maybe it's old NSIS archive()
+
UInt32 numStrings = (langtable_size - 10) / 4;
_numLangStrings = numStrings;
AddLF();
@@ -5310,7 +5278,7 @@ HRESULT CInArchive::Parse()
{
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
LANGID langID = Get16(p);
- UInt32 val = Get32(p + 10 + licenseLangIndex * 4);
+ UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4);
if (val != 0)
{
Script += "LicenseLangString ";
@@ -5902,6 +5870,7 @@ void CInArchive::Clear2()
Script.Empty();
LicenseFiles.Clear();
_numRootLicenses = 0;
+ _numLangStrings = 0;
langStrIDs.Clear();
LangComment.Empty();
noParseStringIndexes.Clear();
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
index 3acd9ee5..2bab5299 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.h
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -24,6 +24,7 @@ namespace NNsis {
const size_t kScriptSizeLimit = 1 << 27;
const unsigned kSignatureSize = 16;
+extern const Byte kSignature[kSignatureSize];
#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' }
const UInt32 kFlagsMask = 0xF;
@@ -261,7 +262,7 @@ private:
void Add_ButtonID(UInt32 buttonID);
void Add_ShowWindow_Cmd(UInt32 cmd);
- void Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type);
+ void Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type);
void Add_ExecFlags(UInt32 flagsType);
void Add_SectOp(UInt32 opType);
diff --git a/CPP/7zip/Archive/Nsis/NsisRegister.cpp b/CPP/7zip/Archive/Nsis/NsisRegister.cpp
index b363bdec..7230c3c2 100644
--- a/CPP/7zip/Archive/Nsis/NsisRegister.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisRegister.cpp
@@ -9,16 +9,12 @@
namespace NArchive {
namespace NNsis {
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Nsis", "nsis", 0, 0x9,
- NArchive::NNsis::kSignatureSize, NSIS_SIGNATURE,
+REGISTER_ARC_I(
+ "Nsis", "nsis", 0, 0x9,
+ kSignature,
4,
NArcInfoFlags::kFindSignature |
NArcInfoFlags::kUseGlobalOffset,
- CreateArc };
-
-REGISTER_ARC(Nsis)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp
index 6661492f..ee630a66 100644
--- a/CPP/7zip/Archive/NtfsHandler.cpp
+++ b/CPP/7zip/Archive/NtfsHandler.cpp
@@ -22,6 +22,7 @@
#include "../Common/MethodProps.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
+#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
@@ -62,6 +63,7 @@ static const wchar_t *kVirtualFolder_Lost_Deleted = L"[UNKNOWN]";
static const unsigned kNumSysRecs = 16;
static const unsigned kRecIndex_Volume = 3;
+static const unsigned kRecIndex_RootDir = 5;
static const unsigned kRecIndex_BadClus = 8;
static const unsigned kRecIndex_Security = 9;
@@ -198,10 +200,18 @@ enum
DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE)
};
-static const Byte kFileNameType_Posix = 0;
-static const Byte kFileNameType_Win32 = 1;
-static const Byte kFileNameType_Dos = 2;
-static const Byte kFileNameType_Win32Dos = 3;
+
+/* WinXP-64:
+ Probably only one short name (dos name) per record is allowed.
+ There are no short names for hard links.
+ The pair (Win32,Dos) can be in any order.
+ Posix name can be after or before Win32 name
+*/
+
+static const Byte kFileNameType_Posix = 0; // for hard links
+static const Byte kFileNameType_Win32 = 1; // after Dos name
+static const Byte kFileNameType_Dos = 2; // short name
+static const Byte kFileNameType_Win32Dos = 3; // short and full name are same
struct CFileNameAttr
{
@@ -215,21 +225,31 @@ struct CFileNameAttr
// UInt64 AllocatedSize;
// UInt64 DataSize;
// UInt16 PackedEaSize;
- UString Name;
+ UString2 Name;
UInt32 Attrib;
Byte NameType;
bool IsDos() const { return NameType == kFileNameType_Dos; }
+ bool IsWin32() const { return (NameType == kFileNameType_Win32); }
+
bool Parse(const Byte *p, unsigned size);
};
-static void GetString(const Byte *p, unsigned len, UString &res)
+static void GetString(const Byte *p, unsigned len, UString2 &res)
{
- wchar_t *s = res.GetBuffer(len);
- for (unsigned i = 0; i < len; i++)
- s[i] = Get16(p + i * 2);
- s[len] = 0;
- res.ReleaseBuffer();
+ if (len == 0 && res.IsEmpty())
+ return;
+ wchar_t *s = res.GetBuf(len);
+ unsigned i;
+ for (i = 0; i < len; i++)
+ {
+ wchar_t c = Get16(p + i * 2);
+ if (c == 0)
+ break;
+ s[i] = c;
+ }
+ s[i] = 0;
+ res.ReleaseBuf_SetLen(i);
}
bool CFileNameAttr::Parse(const Byte *p, unsigned size)
@@ -249,7 +269,8 @@ bool CFileNameAttr::Parse(const Byte *p, unsigned size)
unsigned len = p[0x40];
if (0x42 + len > size)
return false;
- GetString(p + 0x42, len, Name);
+ if (len != 0)
+ GetString(p + 0x42, len, Name);
return true;
}
@@ -321,7 +342,7 @@ struct CAttr
{
UInt32 Type;
// UInt32 Len;
- UString Name;
+ UString2 Name;
// UInt16 Flags;
// UInt16 Instance;
CByteBuffer Data;
@@ -364,7 +385,17 @@ static int CompareAttr(void *const *elem1, void *const *elem2, void *)
const CAttr &a1 = *(*((const CAttr **)elem1));
const CAttr &a2 = *(*((const CAttr **)elem2));
RINOZ(MyCompare(a1.Type, a2.Type));
- RINOZ(wcscmp(a1.Name, a2.Name));
+ if (a1.Name.IsEmpty())
+ {
+ if (!a2.Name.IsEmpty())
+ return -1;
+ }
+ else if (a2.Name.IsEmpty())
+ return 1;
+ else
+ {
+ RINOZ(wcscmp(a1.Name.GetRawPtr(), a2.Name.GetRawPtr()));
+ }
return MyCompare(a1.LowVcn, a2.LowVcn);
}
@@ -387,13 +418,13 @@ UInt32 CAttr::Parse(const Byte *p, unsigned size)
return 0;
NonResident = p[0x08];
{
- unsigned nameLength = p[9];
+ unsigned nameLen = p[9];
UInt32 nameOffset = Get16(p + 0x0A);
- if (nameLength != 0)
+ if (nameLen != 0)
{
- if (nameOffset + nameLength * 2 > len)
+ if (nameOffset + nameLen * 2 > len)
return 0;
- GetString(p + nameOffset, nameLength, Name);
+ GetString(p + nameOffset, nameLen, Name);
PRF(printf(" N="));
PRF_UTF16(Name);
}
@@ -485,10 +516,11 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
if (num == 0 || num > 8 || num > size)
return false;
- int i;
- UInt64 vSize = p[num - 1];
- for (i = (int)num - 2; i >= 0; i--)
- vSize = (vSize << 8) | p[i];
+ UInt64 vSize = 0;
+ {
+ unsigned i = num;
+ do vSize = (vSize << 8) | p[--i]; while(i);
+ }
if (vSize == 0)
return false;
p += num;
@@ -510,8 +542,10 @@ bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax,
else
{
Int64 v = (signed char)p[num - 1];
- for (i = (int)num - 2; i >= 0; i--)
- v = (v << 8) | p[i];
+ {
+ for (unsigned i = num - 1; i != 0;)
+ v = (v << 8) | p[--i];
+ }
p += num;
size -= num;
lcn += v;
@@ -617,7 +651,7 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte
{
if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0)
return 0;
- int numDistBits = 4;
+ unsigned numDistBits = 4;
UInt32 sbOffset = 0;
UInt32 pos = 0;
@@ -669,7 +703,7 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte
STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
if (_virtPos >= Size)
return (Size == _virtPos) ? S_OK: E_FAIL;
@@ -830,7 +864,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
res = Stream->Read(data, size, &size);
_physPos += size;
}
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = size;
_virtPos += size;
_curRem -= size;
@@ -858,54 +892,6 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio
return S_OK;
}
-class CByteBufStream:
- public IInStream,
- public CMyUnknownImp
-{
- UInt64 _virtPos;
-public:
- CByteBuffer Buf;
- void Init() { _virtPos = 0; }
-
- MY_UNKNOWN_IMP1(IInStream)
-
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
- STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
-};
-
-STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize)
-{
- if (processedSize != NULL)
- *processedSize = 0;
- if (_virtPos >= Buf.Size())
- return (_virtPos == Buf.Size()) ? S_OK: E_FAIL;
- UInt64 rem = Buf.Size() - _virtPos;
- if (rem < size)
- size = (UInt32)rem;
- memcpy(data, Buf + (size_t)_virtPos, size);
- if (processedSize != NULL)
- *processedSize = size;
- _virtPos += size;
- return S_OK;
-}
-
-STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
-{
- switch (seekOrigin)
- {
- case STREAM_SEEK_SET: break;
- case STREAM_SEEK_CUR: offset += _virtPos; break;
- case STREAM_SEEK_END: offset += Buf.Size(); break;
- default: return STG_E_INVALIDFUNCTION;
- }
- if (offset < 0)
- return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
- _virtPos = offset;
- if (newPosition)
- *newPosition = offset;
- return S_OK;
-}
-
static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAttr> &attrs,
unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
{
@@ -966,7 +952,9 @@ struct CMftRec
// UInt16 NextAttrInstance;
CMftRef BaseMftRef;
// UInt32 ThisRecNumber;
+
UInt32 MyNumNameLinks;
+ int MyItemIndex; // index in Items[] of main item for that record, or -1 if there is no item for that record
CObjectVector<CAttr> DataAttrs;
CObjectVector<CFileNameAttr> FileNames;
@@ -977,12 +965,40 @@ struct CMftRec
CByteBuffer ReparseData;
+ int FindWin32Name_for_DosName(unsigned dosNameIndex) const
+ {
+ const CFileNameAttr &cur = FileNames[dosNameIndex];
+ if (cur.IsDos())
+ for (unsigned i = 0; i < FileNames.Size(); i++)
+ {
+ const CFileNameAttr &next = FileNames[i];
+ if (next.IsWin32() && cur.ParentDirRef.Val == next.ParentDirRef.Val)
+ return i;
+ }
+ return -1;
+ }
+
+ int FindDosName(unsigned nameIndex) const
+ {
+ const CFileNameAttr &cur = FileNames[nameIndex];
+ if (cur.IsWin32())
+ for (unsigned i = 0; i < FileNames.Size(); i++)
+ {
+ const CFileNameAttr &next = FileNames[i];
+ if (next.IsDos() && cur.ParentDirRef.Val == next.ParentDirRef.Val)
+ return i;
+ }
+ return -1;
+ }
+
+ /*
bool IsAltStream(int dataIndex) const
{
return dataIndex >= 0 && (
(IsDir() ||
!DataAttrs[DataRefs[dataIndex].Start].Name.IsEmpty()));
}
+ */
void MoveAttrsFrom(CMftRec &src)
{
@@ -1016,7 +1032,7 @@ struct CMftRec
UInt64 GetSize(unsigned dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }
- CMftRec(): MyNumNameLinks(0) {}
+ CMftRec(): MyNumNameLinks(0), MyItemIndex(-1) {}
};
void CMftRec::ParseDataNames()
@@ -1040,12 +1056,10 @@ HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,
unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const
{
*destStream = 0;
- CByteBufStream *streamSpec = new CByteBufStream;
+ CBufferInStream *streamSpec = new CBufferInStream;
CMyComPtr<IInStream> streamTemp = streamSpec;
- if (dataIndex < 0)
- return E_FAIL;
-
+ if (dataIndex >= 0)
if ((unsigned)dataIndex < DataRefs.Size())
{
const CDataRef &ref = DataRefs[dataIndex];
@@ -1231,26 +1245,42 @@ bool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 r
return true;
}
+/*
+ NTFS probably creates empty DATA_ATTRIBUTE for empty file,
+ But it doesn't do it for
+ $Secure (:$SDS),
+ $Extend\$Quota
+ $Extend\$ObjId
+ $Extend\$Reparse
+*/
+
+static const int k_Item_DataIndex_IsEmptyFile = -1; // file without unnamed data stream
+static const int k_Item_DataIndex_IsDir = -2;
+
+// static const int k_ParentFolderIndex_Root = -1;
+static const int k_ParentFolderIndex_Lost = -2;
+static const int k_ParentFolderIndex_Deleted = -3;
+
struct CItem
{
unsigned RecIndex; // index in Recs array
unsigned NameIndex; // index in CMftRec::FileNames
int DataIndex; /* index in CMftRec::DataRefs
- -1: for folders
- -1: for files that have no DATA_ATRIBUTE */
+ -1: file without unnamed data stream
+ -2: for directories */
int ParentFolder; /* index in Items array
-1: for root items
-2: [LOST] folder
-3: [UNKNOWN] folder (deleted lost) */
int ParentHost; /* index in Items array, if it's AltStream
- -1: if it's not AltStream
- -1: if there is no Host item */
+ -1: if it's not AltStream */
- CItem(): DataIndex(-1), ParentFolder(-1), ParentHost(-1) {}
+ CItem(): DataIndex(k_Item_DataIndex_IsDir), ParentFolder(-1), ParentHost(-1) {}
- bool IsDir() const { return DataIndex < 0; }
+ bool IsAltStream() const { return ParentHost != -1; }
+ bool IsDir() const { return DataIndex == k_Item_DataIndex_IsDir; }
// check it !!!
// probably NTFS for empty file still creates empty DATA_ATTRIBUTE
// But it doesn't do it for $Secure:$SDS
@@ -1276,7 +1306,9 @@ struct CDatabase
bool _showSystemFiles;
bool _showDeletedFiles;
- UStringVector VirtFolderNames;
+ CObjectVector<UString2> VirtFolderNames;
+ UString EmptyString;
+
int _systemFolderIndex;
int _lostFolderIndex_Normal;
int _lostFolderIndex_Deleted;
@@ -1311,6 +1343,8 @@ struct CDatabase
const CMftRec &rec = Recs[(unsigned)recIndex];
if (!rec.IsDir())
return -1;
+ return rec.MyItemIndex;
+ /*
unsigned left = 0, right = Items.Size();
while (left != right)
{
@@ -1319,9 +1353,9 @@ struct CDatabase
UInt64 midValue = item.RecIndex;
if (recIndex == midValue)
{
- // if (!item.IsAltStream)
- // if (!rec.IsAltStream(item.DataIndex))
- if (item.DataIndex < 0)
+ // if item is not dir (file or alt stream we don't return it)
+ // if (item.DataIndex < 0)
+ if (item.IsDir())
return mid;
right = mid;
}
@@ -1331,6 +1365,7 @@ struct CDatabase
left = mid + 1;
}
return -1;
+ */
}
bool FindSecurityDescritor(UInt32 id, UInt64 &offset, UInt32 &size) const;
@@ -1374,8 +1409,6 @@ void CDatabase::ClearAndClose()
InStream.Release();
}
-#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR
-
void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
{
const CItem *item = &Items[index];
@@ -1383,22 +1416,24 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
const CMftRec &rec = Recs[item->RecIndex];
size += rec.FileNames[item->NameIndex].Name.Len();
- bool isAltStream = rec.IsAltStream(item->DataIndex);
+ bool isAltStream = item->IsAltStream();
+
if (isAltStream)
{
const CAttr &data = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start];
+ if (item->RecIndex == kRecIndex_RootDir)
+ {
+ wchar_t *s = path.AllocBstr(data.Name.Len() + 1);
+ s[0] = L':';
+ if (!data.Name.IsEmpty())
+ MyStringCopy(s + 1, data.Name.GetRawPtr());
+ return;
+ }
+
size += data.Name.Len();
size++;
}
- /*
- if (item->ParentHost >= 0)
- {
- item = &Items[item->ParentHost];
- size += item->Name.Len() + 1;
- }
- */
-
for (unsigned i = 0;; i++)
{
if (i > 256)
@@ -1407,7 +1442,8 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
return;
}
const wchar_t *servName;
- if (item->RecIndex < kNumSysRecs)
+ if (item->RecIndex < kNumSysRecs
+ /* && item->RecIndex != kRecIndex_RootDir */)
servName = kVirtualFolder_System;
else
{
@@ -1420,7 +1456,7 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
}
if (index2 == -1)
break;
- servName = (index2 == -2) ?
+ servName = (index2 == k_ParentFolderIndex_Lost) ?
kVirtualFolder_Lost_Normal :
kVirtualFolder_Lost_Deleted;
}
@@ -1435,47 +1471,31 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
bool needColon = false;
if (isAltStream)
{
- const UString &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name;
- size -= name.Len();
- MyStringCopy(s + size, (const wchar_t *)name);
+ const UString2 &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name;
+ if (!name.IsEmpty())
+ {
+ size -= name.Len();
+ MyStringCopy(s + size, name.GetRawPtr());
+ }
s[--size] = ':';
needColon = true;
}
{
- const UString &name = rec.FileNames[item->NameIndex].Name;
+ const UString2 &name = rec.FileNames[item->NameIndex].Name;
unsigned len = name.Len();
- MyStringCopy(s + size - len, (const wchar_t *)name);
+ if (len != 0)
+ MyStringCopy(s + size - len, name.GetRawPtr());
if (needColon)
s[size] = ':';
size -= len;
}
- /*
- {
- unsigned len = item->Name.Len();
- size -= len;
- MyStringCopy(s + size, (const wchar_t *)item->Name);
- }
- */
-
-
- /*
- if (item->ParentHost >= 0)
- {
- item = &Items[item->ParentHost];
- unsigned len = item->Name.Len();
- size--;
- size -= len;
- MyStringCopy(s + size, (const wchar_t *)item->Name);
- s[size + len] = ':';
- }
- */
-
for (;;)
{
const wchar_t *servName;
- if (item->RecIndex < kNumSysRecs)
+ if (item->RecIndex < kNumSysRecs
+ /* && && item->RecIndex != kRecIndex_RootDir */)
servName = kVirtualFolder_System;
else
{
@@ -1483,17 +1503,20 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
if (index2 >= 0)
{
item = &Items[index2];
- const UString &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name;
+ const UString2 &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name;
unsigned len = name.Len();
size--;
- size -= len;
- MyStringCopy(s + size, (const wchar_t *)name);
+ if (len != 0)
+ {
+ size -= len;
+ MyStringCopy(s + size, name.GetRawPtr());
+ }
s[size + len] = WCHAR_PATH_SEPARATOR;
continue;
}
if (index2 == -1)
break;
- servName = (index2 == -2) ?
+ servName = (index2 == k_ParentFolderIndex_Lost) ?
kVirtualFolder_Lost_Normal :
kVirtualFolder_Lost_Deleted;
}
@@ -1800,120 +1823,110 @@ HRESULT CDatabase::Open()
if (!rec.InUse() && !_showDeletedFiles)
continue;
- unsigned numNames = 0;
+ rec.MyNumNameLinks = rec.FileNames.Size();
+
// printf("\n%4d: ", i);
- FOR_VECTOR (t, rec.FileNames)
- {
- const CFileNameAttr &fna = rec.FileNames[t];
- // PRF(printf("%4d ", (int)fna.NameType));
- // PRF_UTF16(fna.Name)
- // PRF(printf(" | "));
- if (fna.IsDos())
- continue;
- unsigned numDatas = rec.DataRefs.Size();
-
- /*
- // we can use that code to reduce the number of alt streams
- // For hard linked files we show alt streams only for first Name.
- if (numDatas > 1 && numNames > 0)
- numDatas = 1;
- */
+
+ /* Actually DataAttrs / DataRefs are sorted by name.
+ It can not be more than one unnamed stream in DataRefs
+ And indexOfUnnamedStream <= 0.
+ */
- numNames++;
+ int indexOfUnnamedStream = -1;
+ if (!rec.IsDir())
+ {
+ FOR_VECTOR(di, rec.DataRefs)
+ if (rec.DataAttrs[rec.DataRefs[di].Start].Name.IsEmpty())
+ {
+ indexOfUnnamedStream = di;
+ break;
+ }
+ }
- // here we suppose that first stream is main stream (unnamed stream).
- // IS IT SO ????
- int hostIndex = -1;
- if (rec.IsDir())
+ if (rec.FileNames.IsEmpty())
+ {
+ bool needShow = true;
+ if (i < kNumSysRecs)
{
- CItem item;
- item.NameIndex = t;
- item.RecIndex = i;
- // item.ParentRef = fna.ParentDirRef;
- // item.Attrib = rec.SiAttr.Attrib | 0x10;
- // item.Attrib = fna.Attrib;
- hostIndex = Items.Add(item);
+ needShow = false;
+ FOR_VECTOR(di, rec.DataRefs)
+ if (rec.GetSize(di) != 0)
+ {
+ needShow = true;
+ break;
+ }
}
- else
+ if (needShow)
{
-
- // probably NTFS for empty file still creates empty DATA_ATTRIBUTE
- // But it doesn't do it for $Secure:$SDS
- if (rec.DataRefs.IsEmpty() ||
- !rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty())
- {
- CItem item;
- item.NameIndex = t;
- item.RecIndex = i;
- // item.ParentRef = fna.ParentDirRef;
- // item.Attrib = rec.SiAttr.Attrib;
- hostIndex = Items.Add(item);
- }
+ CFileNameAttr &fna = rec.FileNames.AddNew();
+ // we set incorrect ParentDirRef, that will place item to [LOST] folder
+ fna.ParentDirRef.Val = (UInt64)(Int64)-1;
+ char s[16 + 16];
+ ConvertUInt32ToString(i, MyStpCpy(s, "[NONAME]-"));
+ fna.Name.SetFromAscii(s);
+ fna.NameType = kFileNameType_Win32Dos;
+ fna.Attrib = 0;
}
+ }
+
+ // bool isMainName = true;
+
+ FOR_VECTOR (t, rec.FileNames)
+ {
+ #ifdef SHOW_DEBUG_INFO
+ const CFileNameAttr &fna = rec.FileNames[t];
+ #endif
+ PRF(printf("\n %4d ", (int)fna.NameType));
+ PRF_UTF16(fna.Name);
+ // PRF(printf(" | "));
+ if (rec.FindWin32Name_for_DosName(t) >= 0)
{
- bool isThereUnNamedStream = false;
- for (unsigned di = 0; di < numDatas; di++)
- {
- const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
- if (subName.IsEmpty())
- isThereUnNamedStream = true;
- }
- if (!rec.IsDir() && !isThereUnNamedStream)
- {
- // return S_FALSE;
- }
+ rec.MyNumNameLinks--;
+ continue;
}
+
+ CItem item;
+ item.NameIndex = t;
+ item.RecIndex = i;
+ item.DataIndex = rec.IsDir() ?
+ k_Item_DataIndex_IsDir :
+ (indexOfUnnamedStream < 0 ?
+ k_Item_DataIndex_IsEmptyFile :
+ indexOfUnnamedStream);
+
+ if (rec.MyItemIndex < 0)
+ rec.MyItemIndex = Items.Size();
+ item.ParentHost = Items.Add(item);
+
+ /* we can use that code to reduce the number of alt streams:
+ it will not show how alt streams for hard links. */
+ // if (!isMainName) continue; isMainName = false;
+
+ unsigned numAltStreams = 0;
- for (unsigned di = 0; di < numDatas; di++)
+ FOR_VECTOR(di, rec.DataRefs)
{
- CItem item;
- item.NameIndex = t;
- // item.FileNameAttr = fna;
- // item.Name = fna.Name;
- // item.Attrib = rec.SiAttr.Attrib;
- const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
- if (subName.IsEmpty())
- {
- if (hostIndex >= 0)
- continue;
- hostIndex = Items.Size();
- }
- else
+ if (!rec.IsDir() && (int)di == indexOfUnnamedStream)
+ continue;
+
+ const UString2 &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
+
+ PRF(printf("\n alt stream: "));
+ PRF_UTF16(subName);
+
{
// $BadClus:$Bad is sparse file for all clusters. So we skip it.
if (i == kRecIndex_BadClus && subName == L"$Bad")
continue;
- if (hostIndex >= 0)
- {
- // item.Name = subName;
- }
- else
- {
- // there is no host file for some streams
- // return E_FAIL;
- // item.Name += L":";
- // item.Name += subName;
- }
- // item.Attrib = fna.Attrib;
- item.ParentHost = hostIndex;
- // item.IsAltStream = true;
- ThereAreAltStreams = true;
}
-
- PRF(printf("\n%3d", i));
- PRF(printf(" attrib=%2x ", rec.SiAttr.Attrib));
- // PRF_UTF16(item.Name);
-
- item.RecIndex = i;
- item.DataIndex = di;
- // item.ParentRef = fna.ParentDirRef;
+ numAltStreams++;
+ ThereAreAltStreams = true;
+ item.DataIndex = di;
Items.Add(item);
- rec.MyNumNameLinks++;
}
}
- // rec.FileNames.ClearAndFree();
}
if (Recs.Size() > kRecIndex_Security)
@@ -1959,7 +1972,7 @@ HRESULT CDatabase::Open()
const CFileNameAttr &fn = rec.FileNames[item.NameIndex];
const CMftRef &parentDirRef = fn.ParentDirRef;
UInt64 refIndex = parentDirRef.GetIndex();
- if (refIndex == 5)
+ if (refIndex == kRecIndex_RootDir)
item.ParentFolder = -1;
else
{
@@ -1970,12 +1983,12 @@ HRESULT CDatabase::Open()
if (Recs[item.RecIndex].InUse())
{
thereAreUnknownFolders_Normal = true;
- index = -2;
+ index = k_ParentFolderIndex_Lost;
}
else
{
thereAreUnknownFolders_Deleted = true;
- index = -3;
+ index = k_ParentFolderIndex_Deleted;
}
}
item.ParentFolder = index;
@@ -2019,7 +2032,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IArchiveGetRawProps(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
@@ -2038,29 +2051,30 @@ STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)
STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)
{
*parentType = NParentType::kDir;
- *parent = (UInt32)(Int32)-1;
+ int par = -1;
- if (index >= Items.Size())
- return S_OK;
- const CItem &item = Items[index];
-
- if (item.ParentHost >= 0)
- {
- *parentType = NParentType::kAltStream;
- *parent = (UInt32)(Int32)item.ParentHost;
- return S_OK;
- }
- if (item.RecIndex < kNumSysRecs)
+ if (index < Items.Size())
{
- if (_showSystemFiles)
- *parent = _systemFolderIndex;
- }
- else if (item.ParentFolder >= 0)
- *parent = item.ParentFolder;
- else if (item.ParentFolder == -2)
- *parent = _lostFolderIndex_Normal;
- else if (item.ParentFolder == -3)
- *parent = _lostFolderIndex_Deleted;
+ const CItem &item = Items[index];
+
+ if (item.ParentHost >= 0)
+ {
+ *parentType = NParentType::kAltStream;
+ par = (item.RecIndex == kRecIndex_RootDir ? -1 : item.ParentHost);
+ }
+ else if (item.RecIndex < kNumSysRecs)
+ {
+ if (_showSystemFiles)
+ par = _systemFolderIndex;
+ }
+ else if (item.ParentFolder >= 0)
+ par = item.ParentFolder;
+ else if (item.ParentFolder == k_ParentFolderIndex_Lost)
+ par = _lostFolderIndex_Normal;
+ else if (item.ParentFolder == k_ParentFolderIndex_Deleted)
+ par = _lostFolderIndex_Deleted;
+ }
+ *parent = (UInt32)(Int32)par;
return S_OK;
}
@@ -2073,30 +2087,22 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
if (propID == kpidName)
{
#ifdef MY_CPU_LE
- const UString *s;
+ const UString2 *s;
if (index >= Items.Size())
s = &VirtFolderNames[index - Items.Size()];
else
{
const CItem &item = Items[index];
const CMftRec &rec = Recs[item.RecIndex];
-
- // fix it for no HOST case !!
- // if (item.IsAltStream && item.DataIndex >= 0)
- if (rec.IsAltStream(item.DataIndex))
- {
- if (item.ParentHost < 0)
- return S_OK;
- const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
- s = &data.Name;
- }
+ if (item.IsAltStream())
+ s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name;
else
- {
s = &rec.FileNames[item.NameIndex].Name;
- }
- // s = &item.Name;
}
- *data = (const wchar_t *)*s;
+ if (s->IsEmpty())
+ *data = (const wchar_t *)EmptyString;
+ else
+ *data = s->GetRawPtr();
*dataSize = (s->Len() + 1) * sizeof(wchar_t);
*propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE;
#endif
@@ -2209,6 +2215,9 @@ static const Byte kProps[] =
kpidLinks,
kpidINode,
kpidNumBlocks,
+ kpidNumAltStreams,
+ kpidIsAltStream,
+ kpidShortName,
kpidIsDeleted
};
@@ -2293,9 +2302,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
const CAttr &attr = VolAttrs[i];
if (attr.Type == ATTR_TYPE_VOLUME_NAME)
{
- UString name;
+ UString2 name;
GetString(attr.Data, (unsigned)attr.Data.Size() / 2, name);
- prop = name;
+ if (!name.IsEmpty())
+ prop = name.GetRawPtr();
break;
}
}
@@ -2312,7 +2322,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
CVolInfo vi;
if (attr.ParseVolInfo(vi))
{
- s += ' ';
+ s.Add_Space();
char temp[16];
ConvertUInt32ToString(vi.MajorVer, temp);
s += temp;
@@ -2339,6 +2349,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidWarning:
if (_lostFolderIndex_Normal >= 0)
prop = "There are lost files";
+ break;
/*
case kpidWarningFlags:
@@ -2372,7 +2383,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidName:
case kpidPath:
- prop = VirtFolderNames[index - Items.Size()];
+ prop = VirtFolderNames[index - Items.Size()].GetRawPtr();
break;
case kpidIsDir: prop = true; break;
case kpidIsAux: prop = true; break;
@@ -2433,35 +2444,46 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = item.RecIndex;
break;
}
+ case kpidStreamId:
+ {
+ if (item.DataIndex >= 0)
+ prop = ((UInt64)item.RecIndex << 32) | (unsigned)item.DataIndex;
+ break;
+ }
case kpidName:
{
- // prop = item.Name;
- const UString *s;
- if (rec.IsAltStream(item.DataIndex))
+ const UString2 *s;
+ if (item.IsAltStream())
+ s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name;
+ else
+ s = &rec.FileNames[item.NameIndex].Name;
+ if (s->IsEmpty())
+ prop = (const wchar_t *)EmptyString;
+ else
+ prop = s->GetRawPtr();
+ break;
+ }
+
+ case kpidShortName:
+ {
+ if (!item.IsAltStream())
{
- const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
- s = &data.Name;
- if (item.ParentHost < 0)
+ int dosNameIndex = rec.FindDosName(item.NameIndex);
+ if (dosNameIndex >= 0)
{
- UString s2 = rec.FileNames[item.NameIndex].Name;
- s2 += L':';
- s2 += *s;
- prop = s2;
- break;
+ const UString2 &s = rec.FileNames[dosNameIndex].Name;
+ if (s.IsEmpty())
+ prop = (const wchar_t *)EmptyString;
+ else
+ prop = s.GetRawPtr();
}
}
- else
- {
- s = &rec.FileNames[item.NameIndex].Name;
- }
- prop = *s;
-
break;
}
case kpidIsDir: prop = item.IsDir(); break;
- case kpidIsAltStream: prop = rec.IsAltStream(item.DataIndex); break;
+ case kpidIsAltStream: prop = item.IsAltStream(); break;
case kpidIsDeleted: prop = !rec.InUse(); break;
case kpidIsAux: prop = false; break;
@@ -2491,12 +2513,35 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (item.IsDir())
attrib |= FILE_ATTRIBUTE_DIRECTORY;
+ /* some system entries can contain extra flags (Index View).
+ // 0x10000000 (Directory)
+ // 0x20000000 FILE_ATTR_VIEW_INDEX_PRESENT MFT_RECORD_IS_VIEW_INDEX (Index View)
+ But we don't need them */
+ attrib &= 0xFFFF;
+
prop = attrib;
break;
}
- case kpidLinks: prop = rec.MyNumNameLinks; break;
- case kpidSize: if (data) prop = data->GetSize(); break;
- case kpidPackSize: if (data) prop = data->GetPackSize(); break;
+ case kpidLinks: if (rec.MyNumNameLinks != 1) prop = rec.MyNumNameLinks; break;
+
+ case kpidNumAltStreams:
+ {
+ if (!item.IsAltStream())
+ {
+ unsigned num = rec.DataRefs.Size();
+ if (num > 0)
+ {
+ if (!rec.IsDir() && rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty())
+ num--;
+ if (num > 0)
+ prop = num;
+ }
+ }
+ break;
+ }
+
+ case kpidSize: if (data) prop = data->GetSize(); else if (!item.IsDir()) prop = (UInt64)0; break;
+ case kpidPackSize: if (data) prop = data->GetPackSize(); else if (!item.IsDir()) prop = (UInt64)0; break;
case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;
}
prop.Detach(value);
@@ -2603,7 +2648,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStreamSpec->Init();
const CMftRec &rec = Recs[item.RecIndex];
- const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
int res = NExtract::NOperationResult::kDataError;
{
@@ -2626,8 +2670,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
}
- totalPackSize += data.GetPackSize();
- totalSize += data.GetSize();
+ if (item.DataIndex >= 0)
+ {
+ const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
+ totalPackSize += data.GetPackSize();
+ totalSize += data.GetSize();
+ }
outStreamSpec->ReleaseStream();
RINOK(extractCallback->SetOperationResult(res));
}
@@ -2641,7 +2689,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitProps();
@@ -2668,15 +2716,13 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 };
-static CArcInfo g_ArcInfo =
- { "NTFS", "ntfs img", 0, 0xD9,
- 9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 },
+REGISTER_ARC_I(
+ "NTFS", "ntfs img", 0, 0xD9,
+ k_Signature,
3,
0,
- CreateArc };
-
-REGISTER_ARC(Ntfs)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
index ae7553df..43450e80 100644
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -37,7 +37,7 @@ using namespace NWindows;
namespace NArchive {
namespace NPe {
-static const UInt32 k_Signature = 0x00004550;
+static const UInt32 k_Signature32 = 0x00004550;
static HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res)
{
@@ -137,7 +137,7 @@ struct CHeader
bool CHeader::Parse(const Byte *p)
{
- if (Get32(p) != k_Signature)
+ if (Get32(p) != k_Signature32)
return false;
p += 4;
G16( 0, Machine);
@@ -364,19 +364,14 @@ struct CSection
static const unsigned kNameSize = 8;
-static AString GetName(const Byte *name)
+static void GetName(const Byte *name, AString &res)
{
- AString res;
- char *p = res.GetBuffer(kNameSize);
- memcpy(p, name, kNameSize);
- p[kNameSize] = 0;
- res.ReleaseBuffer();
- return res;
+ res.SetFrom_CalcLen((const char *)name, kNameSize);
}
void CSection::Parse(const Byte *p)
{
- Name = GetName(p);
+ GetName(p, Name);
G32( 8, VSize);
G32(12, Va);
G32(16, PSize);
@@ -484,33 +479,33 @@ static const CUInt32PCharPair g_SubSystems[] =
{ 14, "XBOX" }
};
-static const wchar_t *g_ResTypes[] =
+static const char * const g_ResTypes[] =
{
NULL
- , L"CURSOR"
- , L"BITMAP"
- , L"ICON"
- , L"MENU"
- , L"DIALOG"
- , L"STRING"
- , L"FONTDIR"
- , L"FONT"
- , L"ACCELERATOR"
- , L"RCDATA"
- , L"MESSAGETABLE"
- , L"GROUP_CURSOR"
+ , "CURSOR"
+ , "BITMAP"
+ , "ICON"
+ , "MENU"
+ , "DIALOG"
+ , "STRING"
+ , "FONTDIR"
+ , "FONT"
+ , "ACCELERATOR"
+ , "RCDATA"
+ , "MESSAGETABLE"
+ , "GROUP_CURSOR"
, NULL
- , L"GROUP_ICON"
+ , "GROUP_ICON"
, NULL
- , L"VERSION"
- , L"DLGINCLUDE"
+ , "VERSION"
+ , "DLGINCLUDE"
, NULL
- , L"PLUGPLAY"
- , L"VXD"
- , L"ANICURSOR"
- , L"ANIICON"
- , L"HTML"
- , L"MANIFEST"
+ , "PLUGPLAY"
+ , "VXD"
+ , "ANICURSOR"
+ , "ANIICON"
+ , "HTML"
+ , "MANIFEST"
};
static const UInt32 kFlag = (UInt32)1 << 31;
@@ -561,7 +556,10 @@ struct CTextFile
void NewLine();
void AddString(const char *s);
void AddSpaces(int num);
- void AddBytes(const Byte *p, size_t len);
+ void AddBytes(const Byte *p, size_t size)
+ {
+ Buf.AddData(p, size);
+ }
void OpenBlock(int num)
{
@@ -623,12 +621,6 @@ void CTextFile::AddSpaces(int num)
AddChar(' ');
}
-void CTextFile::AddBytes(const Byte *data, size_t size)
-{
- Byte *p = Buf.GetCurPtrAndGrow(size);
- memcpy(p, data, size);
-}
-
struct CStringItem: public CTextFile
{
UInt32 Lang;
@@ -648,7 +640,7 @@ struct CMixItem
int VersionIndex;
CMixItem(): SectionIndex(-1), ResourceIndex(-1), StringIndex(-1), VersionIndex(-1) {}
- bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; };
+ bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; }
};
struct CUsedBitmap
@@ -802,6 +794,7 @@ static const STATPROPSTG kArcProps[] =
{ (LPOLESTR)L"Heap Commit", kpidHeapCommit, VT_UI8},
{ (LPOLESTR)L"Image Base", kpidImageBase, VT_UI8},
{ NULL, kpidComment, VT_BSTR},
+
// { (LPOLESTR)L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},
// { (LPOLESTR)L"Base Of Code", kpidBaseOfCode, VT_UI8},
// { (LPOLESTR)L"Base Of Data", kpidBaseOfData32, VT_UI8},
@@ -913,7 +906,7 @@ HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const
if ((rem - 2) / 2 < len)
return S_FALSE;
dest.Empty();
- wchar_t *destBuf = dest.GetBuffer(len);
+ wchar_t *destBuf = dest.GetBuf(len);
offset += 2;
const Byte *src = _buf + offset;
unsigned i;
@@ -924,7 +917,8 @@ HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const
break;
destBuf[i] = c;
}
- dest.ReleaseBuffer(i);
+ destBuf[i] = 0;
+ dest.ReleaseBuf_SetLen(i);
return S_OK;
}
@@ -960,7 +954,7 @@ void CHandler::AddLangPrefix(UString &s, UInt32 lang) const
if (!_oneLang)
{
AddResNameToString(s, lang);
- s += WCHAR_PATH_SEPARATOR;
+ s.Add_PathSepar();
}
}
@@ -978,7 +972,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString s = _resourcesPrefix;
AddLangPrefix(s, item.Lang);
- s += L"string.txt";
+ s.AddAscii("string.txt");
prop = s;
break;
}
@@ -996,7 +990,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString s = _resourcesPrefix;
AddLangPrefix(s, item.Lang);
- s += L"version.txt";
+ s.AddAscii("version.txt");
prop = s;
break;
}
@@ -1015,22 +1009,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
UString s = _resourcesPrefix;
AddLangPrefix(s, item.Lang);
{
- const wchar_t *p = NULL;
+ const char *p = NULL;
if (item.Type < ARRAY_SIZE(g_ResTypes))
p = g_ResTypes[item.Type];
if (p)
- s += p;
+ s.AddAscii(p);
else
AddResNameToString(s, item.Type);
}
- s += WCHAR_PATH_SEPARATOR;
+ s.Add_PathSepar();
AddResNameToString(s, item.ID);
if (item.HeaderSize != 0)
{
if (item.IsBmp())
- s += L".bmp";
+ s.AddAscii(".bmp");
else if (item.IsIcon())
- s += L".ico";
+ s.AddAscii(".ico");
}
prop = s;
break;
@@ -1199,11 +1193,14 @@ static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size)
return 0;
if (h.YSize < 0)
h.YSize = -h.YSize;
- if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32 ||
- h.Compression != 0) // BI_RGB
+ if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32)
return 0;
if (h.SizeImage == 0)
+ {
+ if (h.Compression != 0) // BI_RGB
+ return 0;
h.SizeImage = GetImageSize(h.XSize, h.YSize, h.BitCount);
+ }
UInt32 totalSize = kBmpHeaderSize + size;
UInt32 offBits = totalSize - h.SizeImage;
// BITMAPFILEHEADER
@@ -1413,7 +1410,7 @@ static void PrintVersion(UString &s, UInt32 ms, UInt32 ls)
PrintUInt32(s, LOWORD(ls));
}
-static const char *k_VS_FileFlags[] =
+static const char * const k_VS_FileFlags[] =
{
"DEBUG"
, "PRERELEASE"
@@ -1432,7 +1429,7 @@ static const CUInt32PCharPair k_VS_FileOS[] =
{ 0x40004, "VOS_NT_WINDOWS32" }
};
-static const char *k_VS_FileOS_High[] =
+static const char * const k_VS_FileOS_High[] =
{
"VOS_UNKNOWN"
, "VOS_DOS"
@@ -1445,7 +1442,7 @@ static const char *k_VS_FileOS_High[] =
static const UInt32 kMY_VFT_DRV = 3;
static const UInt32 kMY_VFT_FONT = 4;
-static const char *k_VS_FileOS_Low[] =
+static const char * const k_VS_FileOS_Low[] =
{
"VOS__BASE"
, "VOS__WINDOWS16"
@@ -1454,7 +1451,7 @@ static const char *k_VS_FileOS_Low[] =
, "VOS__WINDOWS32"
};
-static const char *k_VS_FileType[] =
+static const char * const k_VS_FileType[] =
{
"VFT_UNKNOWN"
, "VFT_APP"
@@ -1467,7 +1464,7 @@ static const char *k_VS_FileType[] =
};
// Subtype for VFT_DRV Type
-static const char *k_VS_FileSubType_DRV[] =
+static const char * const k_VS_FileSubType_DRV[] =
{
"0"
, "PRINTER"
@@ -1485,7 +1482,7 @@ static const char *k_VS_FileSubType_DRV[] =
};
// Subtype for VFT_FONT Type
-static const char *k_VS_FileSubType_FONT[] =
+static const char * const k_VS_FileSubType_FONT[] =
{
"0"
, "VFT2_FONT_RASTER"
@@ -1493,10 +1490,10 @@ static const char *k_VS_FileSubType_FONT[] =
, "VFT2_FONT_TRUETYPE"
};
-static int FindKey(CObjectVector<CStringKeyValue> &v, const UString &key)
+static int FindKey(CObjectVector<CStringKeyValue> &v, const char *key)
{
FOR_VECTOR (i, v)
- if (v[i].Key == key)
+ if (v[i].Key.IsEqualTo(key))
return i;
return -1;
}
@@ -1665,7 +1662,7 @@ struct CVersionBlock
UInt32 TotalLen;
UInt32 ValueLen;
bool IsTextValue;
- int StrSize;
+ unsigned StrSize;
bool Parse(const Byte *p, UInt32 size);
};
@@ -1691,7 +1688,7 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
return false;
TotalLen = Get16(p);
ValueLen = Get16(p + 2);
- if (TotalLen > size)
+ if (TotalLen == 0 || TotalLen > size)
return false;
switch (Get16(p + 4))
{
@@ -1699,8 +1696,12 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
case 1: IsTextValue = true; break;
default: return false;
}
- StrSize = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size);
- return StrSize >= 0;
+ StrSize = 0;
+ int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size);
+ if (t < 0)
+ return false;
+ StrSize = t;
+ return true;
}
static void AddParamString(CTextFile &f, const Byte *p, size_t sLen)
@@ -1868,7 +1869,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
int sLen = Get_Utf16Str_Len_InBytes(p + pos, endPos3 - pos);
if (sLen < 0)
return false;
- AddParamString(f, p + pos, sLen);
+ AddParamString(f, p + pos, (unsigned)sLen);
CopyToUString(p + pos, value);
pos += sLen + 2;
}
@@ -2276,6 +2277,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
// _parseResources = false;
UInt64 mainSize = 0, mainSize2 = 0;
+
for (i = 0; i < _sections.Size(); i++)
{
const CSection &sect = _sections[i];
@@ -2287,7 +2289,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
if (res == S_OK)
{
_resourcesPrefix.SetFromAscii(sect.Name);
- _resourcesPrefix += WCHAR_PATH_SEPARATOR;
+ _resourcesPrefix.Add_PathSepar();
FOR_VECTOR (j, _items)
{
const CResItem &item = _items[j];
@@ -2348,7 +2350,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
mainSize = sect.PSize;
_mainSubfile = _mixItems.Size();
}
- else
+ else if (sect.PSize >= mainSize2)
mainSize2 = sect.PSize;
}
_mixItems.Add(mixItem);
@@ -2370,7 +2372,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
for (i = 0; i < _versionKeys.Size(); i++)
{
if (i != 0)
- _versionFullString += L'\n';
+ _versionFullString.Add_LF();
const CStringKeyValue &k = _versionKeys[i];
_versionFullString += k.Key;
_versionFullString += L": ";
@@ -2378,20 +2380,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
}
{
- int keyIndex = FindKey(_versionKeys, L"OriginalFilename");
+ int keyIndex = FindKey(_versionKeys, "OriginalFilename");
if (keyIndex >= 0)
_originalFilename = _versionKeys[keyIndex].Value;
}
{
- int keyIndex = FindKey(_versionKeys, L"FileDescription");
+ int keyIndex = FindKey(_versionKeys, "FileDescription");
if (keyIndex >= 0)
_versionShortString = _versionKeys[keyIndex].Value;
}
{
- int keyIndex = FindKey(_versionKeys, L"FileVersion");
+ int keyIndex = FindKey(_versionKeys, "FileVersion");
if (keyIndex >= 0)
{
- _versionShortString += L' ';
+ _versionShortString.Add_Space();
_versionShortString += _versionKeys[keyIndex].Value;
}
}
@@ -2597,7 +2599,8 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
}
referenceBuf->Buf.Alloc(item.HeaderSize + item.Size);
memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);
- memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
+ if (item.Size != 0)
+ memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
}
inStreamSpec->Init(referenceBuf);
@@ -2612,17 +2615,15 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'M', 'Z' };
-static CArcInfo g_ArcInfo =
- { "PE", "exe dll sys", 0, 0xDD,
- 2, { 'M', 'Z' },
+REGISTER_ARC_I(
+ "PE", "exe dll sys", 0, 0xDD,
+ k_Signature,
0,
NArcInfoFlags::kPreArc,
- CreateArc, NULL, IsArc_Pe };
-
-REGISTER_ARC(Pe)
-
+ IsArc_Pe)
+
}
@@ -2836,7 +2837,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CSection &item = _items[index];
switch (propID)
{
- case kpidPath: prop = MultiByteToUnicodeString(NPe::GetName(item.Name)); break;
+ case kpidPath:
+ {
+ AString name;
+ NPe::GetName(item.Name, name);
+ prop = MultiByteToUnicodeString(name);
+ break;
+ }
case kpidSize:
case kpidPackSize: prop = (UInt64)item.PSize; break;
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
@@ -2995,16 +3002,14 @@ STDMETHODIMP CHandler::AllowTail(Int32 allowTail)
return S_OK;
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'V', 'Z' };
-static CArcInfo g_ArcInfo =
- { "TE", "te", 0, 0xCF,
- 2, { 'V', 'Z' },
+REGISTER_ARC_I(
+ "TE", "te", 0, 0xCF,
+ k_Signature,
0,
NArcInfoFlags::kPreArc,
- CreateArc, NULL, IsArc_Te };
-
-REGISTER_ARC(TE)
+ IsArc_Te)
}
}
diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp
index 70e9ffac..86927f8f 100644
--- a/CPP/7zip/Archive/PpmdHandler.cpp
+++ b/CPP/7zip/Archive/PpmdHandler.cpp
@@ -28,10 +28,6 @@ using namespace NWindows;
namespace NArchive {
namespace NPpmd {
-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
static const UInt32 kBufSize = (1 << 20);
struct CBuf
@@ -90,11 +86,10 @@ HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
nameLen &= 0x3FFF;
if (nameLen > (1 << 9))
return S_FALSE;
- char *name = Name.GetBuffer(nameLen + 1);
+ char *name = Name.GetBuf(nameLen);
HRESULT res = ReadStream_FALSE(s, name, nameLen);
- name[nameLen] = 0;
+ Name.ReleaseBuf_CalcLen(nameLen);
headerSize = kHeaderSize + nameLen;
- Name.ReleaseBuffer();
return res;
}
@@ -449,15 +444,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return extractCallback->SetOperationResult(opRes);
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0x8F, 0xAF, 0xAC, 0x84 };
-static CArcInfo g_ArcInfo =
- { "Ppmd", "pmd", 0, 0xD,
- 4, { 0x8F, 0xAF, 0xAC, 0x84 },
+REGISTER_ARC_I(
+ "Ppmd", "pmd", 0, 0xD,
+ k_Signature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Ppmd)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
index c26d72f9..516e5d7f 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.cpp
+++ b/CPP/7zip/Archive/Rar/RarHandler.cpp
@@ -89,7 +89,7 @@ UInt32 CItem::GetWinAttrib() const
return a;
}
-static const char *kHostOS[] =
+static const char * const kHostOS[] =
{
"MS DOS"
, "OS/2"
@@ -354,7 +354,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
}
#define READ_TIME(_mask_, _ttt_) \
- { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += size2, size -= size2; }
+ { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += (unsigned)size2, size -= (unsigned)size2; }
#define READ_TIME_2(_mask_, _def_, _ttt_) \
_def_ = ((_mask_ & 8) != 0); if (_def_) \
@@ -421,7 +421,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
{
item.IsAltStream = true;
item.Name.Empty();
- item.UnicodeName = L".ACL";
+ item.UnicodeName.SetFromAscii(".ACL");
}
else if (item.Name == "STM" && size != 0 && (size & 1) == 0)
{
@@ -517,7 +517,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
RINOK(getTextPassword->CryptoGetTextPassword(&password))
unsigned len = 0;
if (password)
- len = MyStringLen((BSTR)password);
+ len = MyStringLen(password);
CByteBuffer buffer(len * 2);
for (unsigned i = 0; i < len; i++)
{
@@ -645,6 +645,8 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
error = k_ErrorType_Corrupted;
ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset);
}
+
+ ArcInfo.EndOfArchive_was_Read = true;
}
m_Position += processed;
FinishCryptoBlock();
@@ -668,7 +670,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item);
if (okItem)
{
- if (!CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize - item.CommentSize))
+ if (!CheckHeaderCrc(m_FileHeaderData, (unsigned)m_BlockHeader.HeadSize - item.CommentSize))
{
error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
return S_OK;
@@ -802,8 +804,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
// FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop);
if (_arcInfo.Is_DataCRC_Defined())
{
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
s += "VolCRC";
}
prop = s;
@@ -1008,27 +1009,28 @@ public:
{
_first = true;
_newStyle = newStyle;
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
UString basePart = name;
+
if (dotPos >= 0)
{
UString ext = name.Ptr(dotPos + 1);
- if (ext.IsEqualToNoCase(L"rar"))
+ if (ext.IsEqualTo_Ascii_NoCase("rar"))
{
_afterPart = name.Ptr(dotPos);
basePart = name.Left(dotPos);
}
- else if (ext.IsEqualToNoCase(L"exe"))
+ else if (ext.IsEqualTo_Ascii_NoCase("exe"))
{
- _afterPart = L".rar";
+ _afterPart.SetFromAscii(".rar");
basePart = name.Left(dotPos);
}
else if (!_newStyle)
{
- if (ext.IsEqualToNoCase(L"000") ||
- ext.IsEqualToNoCase(L"001") ||
- ext.IsEqualToNoCase(L"r00") ||
- ext.IsEqualToNoCase(L"r01"))
+ if (ext.IsEqualTo_Ascii_NoCase("000") ||
+ ext.IsEqualTo_Ascii_NoCase("001") ||
+ ext.IsEqualTo_Ascii_NoCase("r00") ||
+ ext.IsEqualTo_Ascii_NoCase("r01"))
{
_afterPart.Empty();
_first = false;
@@ -1042,18 +1044,21 @@ public:
if (!_newStyle)
{
_afterPart.Empty();
- _unchangedPart = basePart + UString(L".");
- _changedPart = L"r00";
+ _unchangedPart = basePart;
+ _unchangedPart += L'.';
+ _changedPart.SetFromAscii("r00");
return true;
}
if (basePart.IsEmpty())
return false;
unsigned i = basePart.Len();
+
do
if (!IsDigit(basePart[i - 1]))
break;
while (--i);
+
_unchangedPart = basePart.Left(i);
_changedPart = basePart.Ptr(i);
return true;
@@ -1071,34 +1076,59 @@ public:
UString GetNextName()
{
- UString newName;
if (_newStyle || !_first)
{
- for (int i = (int)_changedPart.Len() - 1; i >= 0; i--)
+ unsigned i = _changedPart.Len();
+ for (;;)
{
- wchar_t c = _changedPart[i];
+ wchar_t c = _changedPart[--i];
if (c == L'9')
{
c = L'0';
- newName.InsertAtFront(c);
+ _changedPart.ReplaceOneCharAtPos(i, c);
if (i == 0)
- newName.InsertAtFront(L'1');
+ {
+ _changedPart.InsertAtFront(L'1');
+ break;
+ }
continue;
}
c++;
- newName = UString(c) + newName;
- i--;
- for (; i >= 0; i--)
- newName.InsertAtFront(_changedPart[i]);
+ _changedPart.ReplaceOneCharAtPos(i, c);
break;
}
- _changedPart = newName;
}
+
_first = false;
return _unchangedPart + _changedPart + _afterPart;
}
};
+static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
+{
+ areThereNonZeros = false;
+ numZeros = 0;
+ const size_t kBufSize = 1 << 9;
+ Byte buf[kBufSize];
+ for (;;)
+ {
+ UInt32 size = 0;
+ HRESULT(stream->Read(buf, kBufSize, &size));
+ if (size == 0)
+ return S_OK;
+ for (UInt32 i = 0; i < size; i++)
+ if (buf[i] != 0)
+ {
+ areThereNonZeros = true;
+ numZeros += i;
+ return S_OK;
+ }
+ numZeros += size;
+ if (numZeros > maxSize)
+ return S_OK;
+ }
+}
+
HRESULT CHandler::Open2(IInStream *stream,
const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *openCallback)
@@ -1174,6 +1204,7 @@ HRESULT CHandler::Open2(IInStream *stream,
RINOK(archive.Open(inStream, maxCheckStartPosition));
_isArc = true;
CItem item;
+
for (;;)
{
if (archive.m_Position > endPos)
@@ -1181,11 +1212,13 @@ HRESULT CHandler::Open2(IInStream *stream,
_errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
break;
}
+
EErrorType error;
// bool decryptionError;
// AString errorMessageLoc;
bool filled;
HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error);
+
if (error != k_ErrorType_OK)
{
if (error == k_ErrorType_UnexpectedEnd)
@@ -1198,16 +1231,33 @@ HRESULT CHandler::Open2(IInStream *stream,
// AddErrorMessage(errorMessageLoc);
}
RINOK(result);
+
if (!filled)
{
if (error == k_ErrorType_DecryptionError && _items.IsEmpty())
return S_FALSE;
+
+ if (archive.ArcInfo.ExtraZeroTail_is_Possible())
+ {
+ /* if there is recovery record for multivolume archive,
+ RAR adds 18 bytes (ZERO bytes) at the end for alignment.
+ We must skip these bytes to prevent phySize warning. */
+ RINOK(inStream->Seek(archive.ArcInfo.EndPos, STREAM_SEEK_SET, NULL));
+ bool areThereNonZeros;
+ UInt64 numZeros;
+ const UInt64 maxSize = 1 << 12;
+ RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize));
+ if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)
+ archive.ArcInfo.EndPos += numZeros;
+ }
break;
}
+
if (item.IgnoreItem())
continue;
bool needAdd = true;
+
if (item.IsSplitBefore())
{
if (!_refItems.IsEmpty())
@@ -1217,6 +1267,7 @@ HRESULT CHandler::Open2(IInStream *stream,
needAdd = false;
}
}
+
if (needAdd)
{
CRefItem refItem;
@@ -1225,7 +1276,9 @@ HRESULT CHandler::Open2(IInStream *stream,
refItem.VolumeIndex = _arcs.Size();
_refItems.Add(refItem);
}
+
_items.Add(item);
+
if (openCallback && _items.Size() % 100 == 0)
{
UInt64 numFiles = _items.Size();
@@ -1256,7 +1309,7 @@ HRESULT CHandler::Open2(IInStream *stream,
/*
int baseFileIndex = -1;
- for (int i = 0; i < _refItems.Size(); i++)
+ for (unsigned i = 0; i < _refItems.Size(); i++)
{
CItem &item = _items[_refItems[i].ItemIndex];
if (item.IsAltStream)
@@ -1430,7 +1483,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (numItems == 0)
return S_OK;
unsigned lastIndex = 0;
- CRecordVector<int> importantIndexes;
+ CRecordVector<unsigned> importantIndexes;
CRecordVector<bool> extractStatuses;
for (UInt32 t = 0; t < numItems; t++)
@@ -1470,7 +1523,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
- CFilterCoder *filterStreamSpec = new CFilterCoder;
+ CFilterCoder *filterStreamSpec = new CFilterCoder(false);
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
@@ -1576,22 +1629,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
// unpackedPos += 0;
CMyComPtr<ISequentialInStream> inStream;
+
if (item.IsEncrypted())
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+
if (item.UnPackVersion >= 29)
{
if (!rar29CryptoDecoder)
{
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
rar29CryptoDecoder = rar29CryptoDecoderSpec;
- // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));
}
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
+ /*
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
&cryptoProperties));
- RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
+ */
+ RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
filterStreamSpec->Filter = rar29CryptoDecoder;
}
else if (item.UnPackVersion >= 20)
@@ -1600,7 +1656,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
rar20CryptoDecoder = rar20CryptoDecoderSpec;
- // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));
}
filterStreamSpec->Filter = rar20CryptoDecoder;
}
@@ -1610,8 +1665,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
continue;
}
- RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,
- &cryptoSetPassword));
+
+ RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
if (!getTextPassword)
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
@@ -1624,7 +1679,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UString unicodePassword;
unsigned len = 0;
if (password)
- len = MyStringLen((BSTR)password);
+ len = MyStringLen(password);
CByteBuffer buffer(len * 2);
for (unsigned i = 0; i < len; i++)
{
@@ -1646,14 +1701,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
}
+
filterStreamSpec->SetInStream(folderInStream);
+ filterStreamSpec->SetOutStreamSize(NULL);
inStream = filterStream;
}
else
{
inStream = folderInStream;
}
+
CMyComPtr<ICompressCoder> commonCoder;
+
switch(item.Method)
{
case '0':
@@ -1679,14 +1738,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
mi.Coder.Release();
if (item.UnPackVersion <= 40)
{
- UInt32 methodID = 0x040300;
+ UInt32 methodID = 0x40300;
if (item.UnPackVersion < 20)
methodID += 1;
else if (item.UnPackVersion < 29)
methodID += 2;
else
methodID += 3;
- RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false));
+ RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, false, mi.Coder));
}
if (mi.Coder == 0)
@@ -1722,7 +1781,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
continue;
}
+
HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);
+
if (item.IsEncrypted())
filterStreamSpec->ReleaseInStream();
if (result == S_FALSE)
@@ -1771,15 +1832,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
IMPL_ISetCompressCodecsInfo
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Rar", "rar r00", 0, 3,
- NHeader::kMarkerSize, SIGNATURE,
+REGISTER_ARC_I(
+ "Rar", "rar r00", 0, 3,
+ kMarker,
0,
NArcInfoFlags::kFindSignature,
- CreateArc };
-
-REGISTER_ARC(Rar)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h
index 81191be9..dd3daa5d 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.h
+++ b/CPP/7zip/Archive/Rar/RarHandler.h
@@ -1,4 +1,4 @@
-// Rar/Handler.h
+// RarHandler.h
#ifndef __RAR_HANDLER_H
#define __RAR_HANDLER_H
@@ -24,18 +24,25 @@ struct CInArcInfo
UInt32 EndFlags;
UInt32 VolNumber;
UInt32 DataCRC;
+ bool EndOfArchive_was_Read;
- CInArcInfo(): EndFlags(0) {}
+ CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false) {}
UInt64 GetPhySize() const { return EndPos - StartPos; }
- bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
- bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
+ bool ExtraZeroTail_is_Possible() const { return IsVolume() && IsRecovery() && EndOfArchive_was_Read; }
+
bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; }
+ bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
+ // kLock
+ bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; }
- bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; }
+ // kAuthenticity
+ bool IsRecovery() const { return (Flags & NHeader::NArchive::kRecovery) != 0; }
bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
+ bool IsFirstVolume() const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; }
bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
+
bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; }
diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h
index 56d25f2c..13daa1cb 100644
--- a/CPP/7zip/Archive/Rar/RarItem.h
+++ b/CPP/7zip/Archive/Rar/RarItem.h
@@ -84,10 +84,10 @@ struct CItem
CItem() { Clear(); }
- UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; };
- // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; };
- UInt64 GetCommentPosition() const { return Position + MainPartSize; };
- UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; };
+ UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; }
+ // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; }
+ UInt64 GetCommentPosition() const { return Position + MainPartSize; }
+ UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; }
};
}}
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp
index 220bc650..268e0837 100644
--- a/CPP/7zip/Archive/RpmHandler.cpp
+++ b/CPP/7zip/Archive/RpmHandler.cpp
@@ -77,7 +77,7 @@ enum
k_EntryType_I18NSTRING
};
-static const char *k_CPUs[] =
+static const char * const k_CPUs[] =
{
"noarch"
, "i386"
@@ -101,7 +101,7 @@ static const char *k_CPUs[] =
, "aarch64" // 19
};
-static const char *k_OS[] =
+static const char * const k_OS[] =
{
"0"
, "Linux"
@@ -299,12 +299,7 @@ AString CHandler::GetBaseName() const
}
}
else
- {
- char *p = s.GetBuffer(kNameSize);
- memcpy(p, _lead.Name, kNameSize);
- p[kNameSize] = 0;
- s.ReleaseBuffer();
- }
+ s.SetFrom_CalcLen(_lead.Name, kNameSize);
s += '.';
if (_lead.Type == kRpmType_Src)
@@ -553,7 +548,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
for (UInt32 t = 0; t < entry.Count; t++)
{
if (t != 0)
- _metadata += ' ';
+ _metadata.Add_Space();
char temp[16];
ConvertUInt32ToString(Get32(p + t * 4), temp);
_metadata += temp;
@@ -592,7 +587,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
for (UInt32 t = 0; t < entry.Count; t++)
{
if (t != 0)
- _metadata += ' ';
+ _metadata.Add_Space();
char temp[16];
ConvertUInt32ToString(Get16(p + t * 2), temp);
_metadata += temp;
@@ -777,15 +772,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0xED, 0xAB, 0xEE, 0xDB};
-static CArcInfo g_ArcInfo =
- { "Rpm", "rpm", 0, 0xEB,
- 4, { 0xED, 0xAB, 0xEE, 0xDB},
+REGISTER_ARC_I(
+ "Rpm", "rpm", 0, 0xEB,
+ k_Signature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Rpm)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
index 19dc1b47..23187064 100644
--- a/CPP/7zip/Archive/SplitHandler.cpp
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -71,68 +71,53 @@ struct CSeqName
UString _changedPart;
bool _splitStyle;
- UString GetNextName()
+ bool GetNextName(UString &s)
{
- UString newName;
- if (_splitStyle)
{
- int i;
- int numLetters = _changedPart.Len();
- for (i = numLetters - 1; i >= 0; i--)
+ unsigned i = _changedPart.Len();
+ for (;;)
{
- wchar_t c = _changedPart[i];
- if (c == 'z')
+ wchar_t c = _changedPart[--i];
+
+ if (_splitStyle)
{
- newName.InsertAtFront('a');
- continue;
+ if (c == 'z')
+ {
+ _changedPart.ReplaceOneCharAtPos(i, L'a');
+ if (i == 0)
+ return false;
+ continue;
+ }
+ else if (c == 'Z')
+ {
+ _changedPart.ReplaceOneCharAtPos(i, L'A');
+ if (i == 0)
+ return false;
+ continue;
+ }
}
- else if (c == 'Z')
+ else
{
- newName.InsertAtFront('A');
- continue;
- }
- c++;
- if ((c == 'z' || c == 'Z') && i == 0)
- {
- _unchangedPart += c;
- wchar_t newChar = (c == 'z') ? L'a' : L'A';
- newName.Empty();
- numLetters++;
- for (int k = 0; k < numLetters; k++)
- newName += newChar;
- break;
- }
- newName.InsertAtFront(c);
- i--;
- for (; i >= 0; i--)
- newName.InsertAtFront(_changedPart[i]);
- break;
- }
- }
- else
- {
- int i;
- int numLetters = _changedPart.Len();
- for (i = numLetters - 1; i >= 0; i--)
- {
- wchar_t c = _changedPart[i];
- if (c == '9')
- {
- newName.InsertAtFront('0');
- if (i == 0)
- newName.InsertAtFront('1');
- continue;
+ if (c == '9')
+ {
+ _changedPart.ReplaceOneCharAtPos(i, L'0');
+ if (i == 0)
+ {
+ _changedPart.InsertAtFront(L'1');
+ break;
+ }
+ continue;
+ }
}
+
c++;
- newName.InsertAtFront(c);
- i--;
- for (; i >= 0; i--)
- newName.InsertAtFront(_changedPart[i]);
+ _changedPart.ReplaceOneCharAtPos(i, c);
break;
}
}
- _changedPart = newName;
- return _unchangedPart + _changedPart;
+
+ s = _unchangedPart + _changedPart;
+ return true;
}
};
@@ -156,7 +141,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
name = prop.bstrVal;
}
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
const UString prefix = name.Left(dotPos + 1);
const UString ext = name.Ptr(dotPos + 1);
UString ext2 = ext;
@@ -196,7 +181,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
seqName._splitStyle = splitStyle;
if (prefix.Len() < 1)
- _subName = L"file";
+ _subName.SetFromAscii("file");
else
_subName.SetFrom(prefix, prefix.Len() - 1);
@@ -220,7 +205,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
for (;;)
{
- const UString fullName = seqName.GetNextName();
+ UString fullName;
+ if (!seqName.GetNextName(fullName))
+ break;
CMyComPtr<IInStream> nextStream;
HRESULT result = volumeCallback->GetStream(fullName, &nextStream);
if (result == S_FALSE)
@@ -355,15 +342,10 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "Split", "001", 0, 0xEA,
- 0, { 0 },
+REGISTER_ARC_I_NO_SIG(
+ "Split", "001", 0, 0xEA,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Split)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp
index 1f70bb8e..c65067af 100644
--- a/CPP/7zip/Archive/SquashfsHandler.cpp
+++ b/CPP/7zip/Archive/SquashfsHandler.cpp
@@ -28,10 +28,6 @@
namespace NArchive {
namespace NSquashfs {
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
static const UInt32 kNumFilesMax = (1 << 28);
static const unsigned kNumDirLevelsMax = (1 << 10);
@@ -68,7 +64,7 @@ static const UInt32 kSignature32_LZ = 0x71736873;
#define kMethod_LZO 3
#define kMethod_XZ 4
-static const char *k_Methods[] =
+static const char * const k_Methods[] =
{
"Unknown"
, "ZLIB"
@@ -1652,13 +1648,12 @@ AString CHandler::GetPath(int index) const
len--;
AString path;
- char *dest = path.GetBuffer(len) + len;
+ char *dest = path.GetBuf_SetEnd(len) + len;
index = indexMem;
for (;;)
{
const CItem &item = _items[index];
index = item.Parent;
-
const Byte *p = _dirs.Data + item.Ptr;
unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;
p += _h.GetFileNameOffset();
@@ -1670,7 +1665,6 @@ AString CHandler::GetPath(int index) const
break;
*(--dest) = CHAR_PATH_SEPARATOR;
}
- path.ReleaseBuffer(len);
return path;
}
@@ -1846,7 +1840,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString res = "SquashFS";
if (_h.SeveralMethods)
res += "-LZMA";
- res += ' ';
+ res.Add_Space();
char s[16];
ConvertUInt32ToString(_h.Major, s);
res += s;
@@ -2049,7 +2043,8 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
}
if (offsetInBlock + blockSize > _cachedUnpackBlockSize)
return S_FALSE;
- memcpy(dest, _cachedBlock + offsetInBlock, blockSize);
+ if (blockSize != 0)
+ memcpy(dest, _cachedBlock + offsetInBlock, blockSize);
return S_OK;
}
@@ -2208,20 +2203,16 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "SquashFS", "squashfs", 0, 0xD2,
- 3 * (1 + 4),
- {
+static const Byte k_Signature[] = {
4, 'h', 's', 'q', 's',
4, 's', 'q', 's', 'h',
- 4, 's', 'h', 's', 'q',
- },
+ 4, 's', 'h', 's', 'q' };
+
+REGISTER_ARC_I(
+ "SquashFS", "squashfs", 0, 0xD2,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature,
- CreateArc };
-
-REGISTER_ARC(Cramfs)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp
index 85c61fe2..77d2ad7d 100644
--- a/CPP/7zip/Archive/SwfHandler.cpp
+++ b/CPP/7zip/Archive/SwfHandler.cpp
@@ -170,7 +170,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
};
static const Byte kProps[] =
@@ -218,7 +218,7 @@ static void DicSizeToString(char *s, UInt32 val)
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
}
::ConvertUInt32ToString(val, s);
- int pos = MyStringLen(s);
+ unsigned pos = MyStringLen(s);
s[pos++] = c;
s[pos] = 0;
}
@@ -558,11 +558,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return NCompress::CopyStream(_seqStream, outStream, NULL);
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
_lzmaMode = false;
RINOK(_props.SetProperties(names, values, numProps));
- UString m = _props.MethodName;
+ AString m = _props.MethodName;
m.MakeLower_Ascii();
if (m.IsEqualTo("lzma"))
{
@@ -576,21 +576,16 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
return S_OK;
}
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "SWFc", "swf", "~.swf", 0xD8,
- 2 + 3 + 3,
- {
+static const Byte k_Signature[] = {
3, 'C', 'W', 'S',
- 3, 'Z', 'W', 'S',
- },
+ 3, 'Z', 'W', 'S' };
+
+REGISTER_ARC_IO(
+ "SWFc", "swf", "~.swf", 0xD8,
+ k_Signature,
0,
NArcInfoFlags::kMultiSignature,
- REF_CreateArc_Pair, IsArc_Swfc };
-
-REGISTER_ARC(Swfc)
+ IsArc_Swfc)
}
@@ -978,15 +973,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'F', 'W', 'S' };
-static CArcInfo g_ArcInfo =
- { "SWF", "swf", 0, 0xD7,
- 3, { 'F', 'W', 'S' },
+REGISTER_ARC_I(
+ "SWF", "swf", 0, 0xD7,
+ k_Signature,
0,
NArcInfoFlags::kKeepName,
- CreateArc, NULL, NSwfc::IsArc_Swf };
-
-REGISTER_ARC(Swf)
+ NSwfc::IsArc_Swf)
}}
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
index 5b587529..d1eec144 100644
--- a/CPP/7zip/Archive/Tar/TarHandler.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandler.cpp
@@ -143,10 +143,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
if (!_forceCodePage)
{
- if (utf8_OK) utf8_OK = CheckUTF8(item.Name);
+ if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced);
+ if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName, item.LinkNameCouldBeReduced);
if (utf8_OK) utf8_OK = CheckUTF8(item.User);
if (utf8_OK) utf8_OK = CheckUTF8(item.Group);
- if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName);
}
RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize));
@@ -298,19 +298,12 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant
{
UString dest;
if (_curCodePage == CP_UTF8)
- {
- if (!ConvertUTF8ToUnicode(s, dest))
- {
- prop = "[ERROR-NAME]";
- return;
- }
- }
+ ConvertUTF8ToUnicode(s, dest);
else
- dest = MultiByteToUnicodeString(s, _curCodePage);
+ MultiByteToUnicodeString2(dest, s, _curCodePage);
if (toOs)
- prop = NItemName::GetOSName2(dest);
- else
- prop = dest;
+ NItemName::ConvertToOSName2(dest);
+ prop = dest;
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
@@ -632,10 +625,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (item.IsSymLink())
{
- CBufInStream *streamSpec = new CBufInStream;
- CMyComPtr<IInStream> streamTemp = streamSpec;
- streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this);
- *stream = streamTemp.Detach();
+ Create_BufInStream_WithReference((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this, stream);
return S_OK;
}
@@ -651,7 +641,7 @@ void CHandler::Init()
_curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP;
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
Init();
diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h
index 23854767..42d57d45 100644
--- a/CPP/7zip/Archive/Tar/TarHandler.h
+++ b/CPP/7zip/Archive/Tar/TarHandler.h
@@ -67,7 +67,7 @@ public:
INTERFACE_IOutArchive(;)
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
void Init();
CHandler();
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
index b909e96c..ae005ac5 100644
--- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -36,8 +36,8 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
s = NItemName::MakeLegalName(s);
if (codePage == CP_UTF8)
{
- if (!ConvertUnicodeToUTF8(s, res))
- return E_INVALIDARG;
+ ConvertUnicodeToUTF8(s, res);
+ // if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG;
}
else
UnicodeStringToMultiByte2(res, s, codePage);
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
index 1584a520..80200c3b 100644
--- a/CPP/7zip/Archive/Tar/TarIn.cpp
+++ b/CPP/7zip/Archive/Tar/TarIn.cpp
@@ -180,6 +180,9 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
error = k_ErrorType_Corrupted;
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
+ item.NameCouldBeReduced =
+ (item.Name.Len() == NFileHeader::kNameSize ||
+ item.Name.Len() == NFileHeader::kNameSize - 1);
RIF(OctalToNumber32(p, 8, item.Mode)); p += 8;
@@ -198,6 +201,9 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
item.LinkFlag = *p++;
ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;
+ item.LinkNameCouldBeReduced =
+ (item.LinkName.Len() == NFileHeader::kNameSize ||
+ item.LinkName.Len() == NFileHeader::kNameSize - 1);
memcpy(item.Magic, p, 8); p += 8;
@@ -207,12 +213,17 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
item.DeviceMajorDefined = (p[0] != 0); if (item.DeviceMajorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMajor)); } p += 8;
item.DeviceMinorDefined = (p[0] != 0); if (item.DeviceMinorDefined) { RIF(OctalToNumber32(p, 8, item.DeviceMinor)); } p += 8;
- AString prefix;
- ReadString(p, NFileHeader::kPrefixSize, prefix);
+ if (p[0] != 0)
+ {
+ AString prefix;
+ ReadString(p, NFileHeader::kPrefixSize, prefix);
+ if (!prefix.IsEmpty()
+ && item.IsUstarMagic()
+ && (item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
+ item.Name = prefix + '/' + item.Name;
+ }
+
p += NFileHeader::kPrefixSize;
- if (!prefix.IsEmpty() && item.IsUstarMagic() &&
- (item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
- item.Name = prefix + AString('/') + item.Name;
if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink)
{
@@ -353,12 +364,11 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
if (item.PackSize > (1 << 14))
return S_OK;
unsigned packSize = (unsigned)item.GetPackSizeAligned();
- char *buf = name->GetBuffer(packSize);
+ char *buf = name->GetBuf(packSize);
size_t processedSize = packSize;
HRESULT res = ReadStream(stream, buf, &processedSize);
item.HeaderSize += (unsigned)processedSize;
- buf[(size_t)item.PackSize] = 0;
- name->ReleaseBuffer();
+ name->ReleaseBuf_CalcLen((unsigned)item.PackSize);
RINOK(res);
if (processedSize != packSize)
{
@@ -392,8 +402,18 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
return S_OK;
}
- if (flagL) item.Name = nameL;
- if (flagK) item.LinkName = nameK;
+ if (flagL)
+ {
+ item.Name = nameL;
+ item.NameCouldBeReduced = false;
+ }
+
+ if (flagK)
+ {
+ item.LinkName = nameK;
+ item.LinkNameCouldBeReduced = false;
+ }
+
error = k_ErrorType_OK;
return S_OK;
}
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h
index 805a2e7c..5245aaa4 100644
--- a/CPP/7zip/Archive/Tar/TarItem.h
+++ b/CPP/7zip/Archive/Tar/TarItem.h
@@ -86,6 +86,8 @@ struct CItemEx: public CItem
{
UInt64 HeaderPos;
unsigned HeaderSize;
+ bool NameCouldBeReduced;
+ bool LinkNameCouldBeReduced;
UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
UInt64 GetFullSize() const { return HeaderSize + PackSize; }
diff --git a/CPP/7zip/Archive/Tar/TarRegister.cpp b/CPP/7zip/Archive/Tar/TarRegister.cpp
index 9e0f6f21..f7b256df 100644
--- a/CPP/7zip/Archive/Tar/TarRegister.cpp
+++ b/CPP/7zip/Archive/Tar/TarRegister.cpp
@@ -9,18 +9,15 @@
namespace NArchive {
namespace NTar {
-IMP_CreateArcIn
-IMP_CreateArcOut
+static const Byte k_Signature[] = { 'u', 's', 't', 'a', 'r' };
-static CArcInfo g_ArcInfo =
- { "tar", "tar", 0, 0xEE,
- 5, { 'u', 's', 't', 'a', 'r' },
+REGISTER_ARC_IO(
+ "tar", "tar", 0, 0xEE,
+ k_Signature,
NFileHeader::kUstarMagic_Offset,
NArcInfoFlags::kStartOpen |
NArcInfoFlags::kSymLinks |
NArcInfoFlags::kHardLinks,
- REF_CreateArc_Pair, IsArc_Tar };
-
-REGISTER_ARC(Tar)
-
+ IsArc_Tar)
+
}}
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp
index fdbce395..3adbdee9 100644
--- a/CPP/7zip/Archive/Tar/TarUpdate.cpp
+++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp
@@ -31,6 +31,9 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
CMyComPtr<IOutStream> outSeekStream;
outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream);
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+
UInt64 complexity = 0;
unsigned i;
@@ -224,6 +227,13 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
}
streamSpec->Init(size);
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArchive,
+ NUpdateNotifyOp::kReplicate))
+ }
+
RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
if (copyCoderSpec->TotalSize != size)
return E_FAIL;
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp
index 6aa53ea9..d35db9fb 100644
--- a/CPP/7zip/Archive/Udf/UdfHandler.cpp
+++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp
@@ -26,7 +26,7 @@ static void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop
if (!NWindows::NTime::GetSecondsSince1601(t.GetYear(), d[4], d[5], d[6], d[7], d[8], numSecs))
return;
if (t.IsLocal())
- numSecs -= t.GetMinutesOffset() * 60;
+ numSecs -= (Int64)((Int32)t.GetMinutesOffset() * 60);
FILETIME ft;
UInt64 v = (((numSecs * 100 + d[9]) * 100 + d[10]) * 100 + d[11]) * 10;
ft.dwLowDateTime = (UInt32)v;
@@ -227,13 +227,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (item.IsInline)
{
- CBufInStream *inStreamSpec = new CBufInStream;
- CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
- CReferenceBuf *referenceBuf = new CReferenceBuf;
- CMyComPtr<IUnknown> ref = referenceBuf;
- referenceBuf->Buf = item.InlineData;
- inStreamSpec->Init(referenceBuf);
- *stream = inStream.Detach();
+ Create_BufInStream_WithNewBuffer(item.InlineData, stream);
return S_OK;
}
@@ -366,18 +360,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
-
static const UInt32 kIsoStartPos = 0x8000;
-static CArcInfo g_ArcInfo =
- { "Udf", "udf iso img", 0, 0xE0,
- // 5, { 0, 'N', 'S', 'R', '0' },
- 6, { 1, 'C', 'D', '0', '0', '1' },
+// 5, { 0, 'N', 'S', 'R', '0' },
+static const Byte k_Signature[] = { 1, 'C', 'D', '0', '0', '1' };
+
+REGISTER_ARC_I(
+ "Udf", "udf iso img", 0, 0xE0,
+ k_Signature,
kIsoStartPos,
NArcInfoFlags::kStartOpen,
- CreateArc, NULL, IsArc_Udf };
-
-REGISTER_ARC(Udf)
+ IsArc_Udf)
}}
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
index 3053a0c1..62df64dc 100644
--- a/CPP/7zip/Archive/Udf/UdfIn.cpp
+++ b/CPP/7zip/Archive/Udf/UdfIn.cpp
@@ -82,13 +82,13 @@ void CDString::Parse(const Byte *p, unsigned size)
static UString ParseDString(const Byte *data, unsigned size)
{
UString res;
- wchar_t *p;
if (size > 0)
{
+ wchar_t *p;
Byte type = data[0];
if (type == 8)
{
- p = res.GetBuffer(size);
+ p = res.GetBuf(size);
for (unsigned i = 1; i < size; i++)
{
wchar_t c = data[i];
@@ -99,7 +99,7 @@ static UString ParseDString(const Byte *data, unsigned size)
}
else if (type == 16)
{
- p = res.GetBuffer(size / 2);
+ p = res.GetBuf(size / 2);
for (unsigned i = 1; i + 2 <= size; i += 2)
{
wchar_t c = GetBe16(data + i);
@@ -110,8 +110,8 @@ static UString ParseDString(const Byte *data, unsigned size)
}
else
return L"[unknow]";
- *p++ = 0;
- res.ReleaseBuffer();
+ *p = 0;
+ res.ReleaseBuf_SetLen((unsigned)(p - (const wchar_t *)res));
}
return res;
}
@@ -432,6 +432,8 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la
CTag tag;
const Byte *p = buf;
RINOK(tag.Parse(p, size));
+ if (size < 176)
+ return S_FALSE;
if (tag.Id != DESC_TYPE_File)
return S_FALSE;
@@ -449,7 +451,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la
if ((extendedAttrLen & 3) != 0)
return S_FALSE;
- int pos = 176;
+ size_t pos = 176;
if (extendedAttrLen > size - pos)
return S_FALSE;
/*
@@ -595,7 +597,7 @@ API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size)
if (SecLogSize < 8)
return res;
UInt32 offset = (UInt32)256 << SecLogSize;
- size_t bufSize = 1 << SecLogSize;
+ size_t bufSize = (UInt32)1 << SecLogSize;
if (offset + bufSize > size)
res = k_IsArc_Res_NEED_MORE;
else
@@ -652,7 +654,7 @@ HRESULT CInArchive::Open2()
if (offset >= fileSize)
continue;
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
- size_t bufSize = 1 << SecLogSize;
+ size_t bufSize = (UInt32)1 << SecLogSize;
size_t readSize = bufSize;
RINOK(ReadStream(_stream, buf, &readSize));
if (readSize == bufSize)
@@ -677,7 +679,7 @@ HRESULT CInArchive::Open2()
for (UInt32 location = 0; ; location++)
{
- size_t bufSize = 1 << SecLogSize;
+ size_t bufSize = (UInt32)1 << SecLogSize;
size_t pos = 0;
if (((UInt64)(location + 1) << SecLogSize) > extentVDS.Len)
return S_FALSE;
@@ -950,7 +952,7 @@ HRESULT CInArchive::Open2()
if (PhySize < fileSize)
{
RINOK(_stream->Seek(PhySize, STREAM_SEEK_SET, NULL));
- size_t bufSize = 1 << SecLogSize;
+ size_t bufSize = (UInt32)1 << SecLogSize;
size_t readSize = bufSize;
RINOK(ReadStream(_stream, buf, &readSize));
if (readSize == bufSize)
@@ -1018,8 +1020,8 @@ UString CInArchive::GetComment() const
UString res;
FOR_VECTOR (i, LogVols)
{
- if (i > 0)
- res += L" ";
+ if (i != 0)
+ res.Add_Space();
res += LogVols[i].GetName();
}
return res;
diff --git a/CPP/7zip/Archive/Udf/UdfRegister.cpp b/CPP/7zip/Archive/Udf/UdfRegister.cpp
deleted file mode 100644
index ed32f12e..00000000
--- a/CPP/7zip/Archive/Udf/UdfRegister.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// UdfRegister.cpp
-
-#include "StdAfx.h"
-
-#include "../../Common/RegisterArc.h"
-
-#include "UdfHandler.h"
diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp
index a6760b36..3de6351a 100644
--- a/CPP/7zip/Archive/UefiHandler.cpp
+++ b/CPP/7zip/Archive/UefiHandler.cpp
@@ -26,6 +26,7 @@
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
+#include "../Compress/LzhDecoder.h"
#ifdef SHOW_DEBUG_INFO
#define PRF(x) x
@@ -41,22 +42,18 @@
namespace NArchive {
namespace NUefi {
-static const UInt32 kBufTotalSizeMax = (1 << 29);
-static const UInt32 kNumFilesMax = (1 << 18);
-static const int kLevelMax = 64;
+static const size_t kBufTotalSizeMax = (1 << 29);
+static const unsigned kNumFilesMax = (1 << 18);
+static const unsigned kLevelMax = 64;
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+static const unsigned kFvHeaderSize = 0x38;
-static const UInt32 kFvHeaderSize = 0x38;
-static const UInt32 kGuidSize = 16;
-static const UInt32 kCapsuleSigSize = kGuidSize;
+static const unsigned kGuidSize = 16;
#define CAPSULE_SIGNATURE \
{ 0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0 }
-static const Byte kCapsuleSig[kCapsuleSigSize] = CAPSULE_SIGNATURE;
+static const Byte kCapsuleSig[kGuidSize] = CAPSULE_SIGNATURE;
-static const UInt32 kFfsGuidOffset = 16;
+static const unsigned kFfsGuidOffset = 16;
#define FFS_SIGNATURE \
{ 0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF }
static const Byte k_FFS_Guid[kGuidSize] = FFS_SIGNATURE;
@@ -84,7 +81,7 @@ static const Byte kGuids[][kGuidSize] =
};
-static const char *kGuidNames[] =
+static const char * const kGuidNames[] =
{
"CRC"
, "VolumeTopFile"
@@ -175,7 +172,7 @@ static bool AreGuidsEq(const Byte *p1, const Byte *p2)
static int FindGuid(const Byte *p)
{
- for (int i = 0; i < ARRAY_SIZE(kGuids); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(kGuids); i++)
if (AreGuidsEq(p, kGuids[i]))
return i;
return -1;
@@ -325,7 +322,7 @@ static const CUInt32PCharPair g_SECTION_TYPE[] =
#define COMPRESSION_TYPE_LZH 1
#define COMPRESSION_TYPE_LZMA 2
-static const char *g_Methods[] =
+static const char * const g_Methods[] =
{
"COPY"
, "LZH"
@@ -367,7 +364,7 @@ static AString GuidToString(const Byte *p, bool full)
return s;
}
-static const char *kExpressionCommands[] =
+static const char * const kExpressionCommands[] =
{
"BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "TRUE", "FALSE", "END", "SOR"
};
@@ -385,7 +382,7 @@ static bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res)
{
if (i + kGuidSize > size)
return false;
- res += " ";
+ res.Add_Space();
res += GuidToString(p + i, false);
i += kGuidSize;
}
@@ -427,9 +424,11 @@ static const UInt32 kFileHeaderSize = 24;
static void AddSpaceAndString(AString &res, const AString &newString)
{
- if (!res.IsEmpty() && !newString.IsEmpty())
- res += ' ';
- res += newString;
+ if (!newString.IsEmpty())
+ {
+ res.Add_Space_if_NotEmpty();
+ res += newString;
+ }
}
class CFfsFileHeader
@@ -604,7 +603,7 @@ void CItem::SetGuid(const Byte *guidName, bool full)
ThereIsUniqueName = true;
int index = FindGuid(guidName);
if (index >= 0)
- Name = kGuidNames[index];
+ Name = kGuidNames[(unsigned)index];
else
Name = GuidToString(guidName, full);
}
@@ -617,9 +616,9 @@ AString CItem::GetName(int numChildsInParent) const
char sz2[32];
ConvertUInt32ToString(NameIndex, sz);
ConvertUInt32ToString(numChildsInParent - 1, sz2);
- int numZeros = (int)strlen(sz2) - (int)strlen(sz);
+ unsigned numZeros = (unsigned)strlen(sz2) - (unsigned)strlen(sz);
AString res;
- for (int i = 0; i < numZeros; i++)
+ for (unsigned i = 0; i < numZeros; i++)
res += '0';
return res + (AString)sz + '.' + Name;
}
@@ -646,7 +645,7 @@ class CHandler:
UInt32 _methodsMask;
bool _capsuleMode;
- UInt32 _totalBufsSize;
+ size_t _totalBufsSize;
CCapsuleHeader _h;
UInt64 _phySize;
@@ -654,9 +653,9 @@ class CHandler:
int AddItem(const CItem &item);
int AddFileItemWithIndex(CItem &item);
int AddDirItem(CItem &item);
- int AddBuf(UInt32 size);
+ unsigned AddBuf(size_t size);
- HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, int level);
+ HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, unsigned level);
HRESULT ParseVolume(int bufIndex, UInt32 posBase,
UInt32 exactSize, UInt32 limitSize,
int parent, int method, int level);
@@ -711,7 +710,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
}
case kpidIsDir: prop = item.IsDir; break;
- case kpidMethod: if (item.Method >= 0) prop = g_Methods[item.Method]; break;
+ case kpidMethod: if (item.Method >= 0) prop = g_Methods[(unsigned)item.Method]; break;
case kpidCharacts: if (!item2.Characts.IsEmpty()) prop = item2.Characts; break;
case kpidSize: if (!item.IsDir) prop = (UInt64)item.Size; break;
}
@@ -739,15 +738,15 @@ void CHandler::AddCommentString(const wchar_t *name, UInt32 pos)
c = Get16(buf + i);
if (c == 0)
break;
- s += L'\n';
+ s.Add_LF();
}
s += c;
}
if (s.IsEmpty())
return;
- _comment += L'\n';
+ _comment.Add_LF();
_comment += name;
- _comment += L": ";
+ _comment.AddAscii(": ");
_comment += s;
}
@@ -760,7 +759,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidMethod:
{
AString s;
- for (int i = 0; i < 32; i++)
+ for (unsigned i = 0; i < 32; i++)
if ((_methodsMask & ((UInt32)1 << i)) != 0)
AddSpaceAndString(s, g_Methods[i]);
if (!s.IsEmpty())
@@ -792,341 +791,7 @@ static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name)
#define MyPrint(posBase, size, level, name)
#endif
-static const unsigned kNumBigValueBits = 8 * 4;
-static const unsigned kNumValueBytes = 3;
-static const unsigned kNumValueBits = 8 * kNumValueBytes;
-static const UInt32 kMask = (1 << kNumValueBits) - 1;
-
-class CBitmMemDecoder
-{
- unsigned _bitPos;
- UInt32 _value;
- const Byte *_buf;
- size_t _pos;
- size_t _size;
- size_t _extra;
-public:
- void Init(const Byte *buf, size_t size)
- {
- _buf = buf;
- _size = size;
- _pos = 0;
- _extra = 0;
- _bitPos = kNumBigValueBits;
- Normalize();
- }
-
- bool IsFullFinished() const { return (_extra * 8) == (kNumBigValueBits - _bitPos); }
-
- void Normalize()
- {
- for (; _bitPos >= 8; _bitPos -= 8)
- {
- Byte b;
- if (_pos < _size)
- b = _buf[_pos++];
- else
- {
- b = 0;
- _extra++;
- }
- _value = (_value << 8) | b;
- }
- }
-
- UInt32 GetValue(unsigned numBits) const
- {
- return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits);
- }
-
- void MovePos(unsigned numBits)
- {
- _bitPos += numBits;
- Normalize();
- }
-
- UInt32 ReadBitsFast(unsigned numBits)
- {
- UInt32 res = GetValue(numBits);
- MovePos(numBits);
- return res;
- }
-
- UInt32 ReadBits(unsigned numBits);
- UInt32 ReadAlignBits() { return ReadBits((32 - _bitPos) & 7); }
-};
-
-UInt32 CBitmMemDecoder::ReadBits(unsigned numBits)
-{
- UInt32 res = GetValue(numBits);
- MovePos(numBits);
- return res;
-}
-
-namespace NHuffman {
-
-static const int kNumTableBits = 9;
-static const int kNumBitsMax = 16;
-
-class CDecoder
-{
- UInt32 m_Limits[kNumBitsMax + 1];
- UInt32 m_Positions[kNumBitsMax + 1];
- Byte m_Lengths[1 << kNumTableBits];
- Int32 m_MainSymbol;
-
-public:
- UInt32 *m_Symbols;
- UInt32 m_NumSymbols;
-
- void SetSingleSymbolMode(UInt32 symbol) { m_MainSymbol = symbol; }
- bool SetCodeLengths(const Byte *codeLengths);
- UInt32 DecodeSymbol(CBitmMemDecoder *bitStream)
- {
- if (m_MainSymbol != -1)
- return (UInt32)m_MainSymbol;
- int numBits;
- UInt32 value = bitStream->GetValue(kNumBitsMax);
- if (value < m_Limits[kNumTableBits])
- numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
- else
- for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);
- bitStream->MovePos(numBits);
- return m_Symbols[m_Positions[numBits] + ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits))];
- }
-};
-
-bool CDecoder::SetCodeLengths(const Byte *codeLengths)
-{
- m_MainSymbol = -1;
- int lenCounts[kNumBitsMax + 1];
- UInt32 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;
- }
- }
- if (startPos != kMaxValue)
- return false;
- for (symbol = 0; symbol < m_NumSymbols; symbol++)
- {
- int len = codeLengths[symbol];
- if (len != 0)
- m_Symbols[tmpPositions[len]++] = symbol;
- }
- return true;
-}
-
-}
-
-static const int kMaxHuffmanLen = 16;
-static const int kExtraSize = kMaxHuffmanLen + 3;
-static const int kMinMatchLen = 3;
-static const int kMaxMatchLen = 256;
-static const int kNumAlphaSymsMax = 256 + kMaxMatchLen - kMinMatchLen + 1;
-static const int kNumDistSymsMax = 24 + 2; // it's limited by bit decoder.
-
-#define HUFF_START_CODE(huff, numSymsMax, numSymBits) \
- UInt32 numSyms = bitDec.ReadBits(numSymBits); \
- Byte lens[numSymsMax]; memset(lens, 0, sizeof(lens)); \
- if (numSyms > (numSymsMax)) return S_FALSE; \
- huff.m_NumSymbols = numSyms; \
- if (numSyms == 0) { \
- numSyms = bitDec.ReadBits(numSymBits); \
- if (numSyms >= (numSymsMax)) return S_FALSE; \
- huff.SetSingleSymbolMode(numSyms); } \
-
-static HRESULT LzhDecode(Byte *dest, UInt32 destSize, const Byte *src, UInt32 srcSize)
-{
- if (srcSize < 8)
- return S_FALSE;
- {
- UInt32 packSize = Get32(src);
- UInt32 unpackSize = Get32(src + 4);
- src += 8;
- srcSize -= 8;
- if (destSize != unpackSize || srcSize != packSize)
- return S_FALSE;
- }
-
- CBitmMemDecoder bitDec;
- bitDec.Init(src, srcSize);
- UInt32 pos = 0;
- for (;;)
- {
- UInt32 blockSize = bitDec.ReadBits(16);
- UInt32 symbols[kExtraSize + kNumAlphaSymsMax + kNumDistSymsMax];
-
- NHuffman::CDecoder extraHuff;
- extraHuff.m_Symbols = symbols;
- {
- HUFF_START_CODE(extraHuff, kExtraSize, 5)
- else
- {
- for (UInt32 i = 0; i < numSyms; i++)
- {
- if (i == 3)
- {
- UInt32 numZeros = bitDec.ReadBits(2);
- if (i + numZeros > numSyms)
- return S_FALSE;
- for (UInt32 j = 0; j < numZeros; j++, i++)
- lens[i] = (Byte)0;
- if (i == numSyms)
- break;
- }
-
- UInt32 len = bitDec.ReadBits(3);
- if (len == 7)
- {
- for(;; len++)
- {
- if (len > kMaxHuffmanLen)
- return S_FALSE;
- if (bitDec.ReadBits(1) == 0)
- break;
- }
- }
- lens[i] = (Byte)len;
- }
- if (!extraHuff.SetCodeLengths(lens))
- return S_FALSE;
- }
- }
-
- NHuffman::CDecoder symHuff;
- symHuff.m_Symbols = symbols + kExtraSize;
- {
- HUFF_START_CODE(symHuff, kNumAlphaSymsMax, 9)
- else
- {
- for (UInt32 i = 0; i < numSyms;)
- {
- UInt32 c = extraHuff.DecodeSymbol(&bitDec);
- if (c > 2)
- lens[i++] = (Byte)(c - 2);
- else
- {
- UInt32 numZeros;
- if (c == 0)
- numZeros = 1;
- else if (c == 1)
- numZeros = bitDec.ReadBits(4) + 3;
- else
- numZeros = bitDec.ReadBits(9) + 20;
- if (i + numZeros > numSyms)
- return S_FALSE;
- for (UInt32 j = 0; j < numZeros; j++, i++)
- lens[i] = (Byte)0;
- }
- }
- if (!symHuff.SetCodeLengths(lens))
- return S_FALSE;
- }
- }
-
- NHuffman::CDecoder distHuff;
- distHuff.m_Symbols = symbols + kExtraSize + kNumAlphaSymsMax;
- {
- const UInt32 version = 1;
- const UInt32 numDistBits = version + 4;
- HUFF_START_CODE(distHuff, kNumDistSymsMax, numDistBits)
- else
- {
- for (UInt32 i = 0; i < numSyms; i++)
- {
- UInt32 len = bitDec.ReadBits(3);
- if (len == 7)
- {
- for(;; len++)
- {
- if (len > kMaxHuffmanLen)
- return S_FALSE;
- if (bitDec.ReadBits(1) == 0)
- break;
- }
- }
- lens[i] = (Byte)len;
- }
- if (!distHuff.SetCodeLengths(lens))
- return S_FALSE;
- }
- }
-
- while (blockSize)
- {
- blockSize--;
- UInt32 c = symHuff.DecodeSymbol(&bitDec);
- if (c < 256)
- {
- if (destSize == 0)
- return S_FALSE;
- *dest++ = (Byte)c;
- destSize--;
- pos++;
- continue;
- }
- c = c - 256 + kMinMatchLen;
- if (destSize < c)
- return S_FALSE;
- UInt32 dist = distHuff.DecodeSymbol(&bitDec);
- if (dist > 1)
- dist = ((UInt32)1 << (dist - 1)) + bitDec.ReadBits(dist - 1);
- dist++;
- if (dist > pos)
- return S_FALSE;
- pos += c;
- destSize -= c;
- do
- {
- *dest = dest[0 - (Int32)dist];
- dest++;
- }
- while (--c);
- }
-
- // PRF(printf("\ndestSize = %6d", destSize));
- if (destSize == 0)
- {
- if (bitDec.ReadAlignBits() != 0)
- return S_FALSE;
- if (bitDec.ReadBits(8) != 0)
- return S_FALSE;
- if (!bitDec.IsFullFinished())
- return S_FALSE;
- break;
- }
- }
- return S_OK;
-}
int CHandler::AddItem(const CItem &item)
{
@@ -1153,17 +818,17 @@ int CHandler::AddDirItem(CItem &item)
return AddItem(item);
}
-int CHandler::AddBuf(UInt32 size)
+unsigned CHandler::AddBuf(size_t size)
{
if (size > kBufTotalSizeMax - _totalBufsSize)
throw 1;
_totalBufsSize += size;
- int index = _bufs.Size();
+ unsigned index = _bufs.Size();
_bufs.AddNew().Alloc(size);
return index;
}
-HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, int level)
+HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level)
{
if (level > kLevelMax)
return S_FALSE;
@@ -1229,9 +894,55 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
}
else if (compressionType == COMPRESSION_TYPE_LZH)
{
- int newBufIndex = AddBuf(uncompressedSize);
+ unsigned newBufIndex = AddBuf(uncompressedSize);
CByteBuffer &buf = _bufs[newBufIndex];
- RINOK(LzhDecode(buf, uncompressedSize, pStart, newSectSize));
+
+ NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;
+ CMyComPtr<ICompressCoder> lzhDecoder;
+
+ lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
+ lzhDecoder = lzhDecoderSpec;
+
+ {
+ const Byte *src = pStart;
+ if (newSectSize < 8)
+ return S_FALSE;
+ UInt32 packSize = Get32(src);
+ UInt32 unpackSize = Get32(src + 4);
+ if (uncompressedSize != unpackSize || newSectSize - 8 != packSize)
+ return S_FALSE;
+ if (packSize < 1)
+ return S_FALSE;
+ packSize--;
+ src += 8;
+ if (src[packSize] != 0)
+ return S_FALSE;
+
+ CBufInStream *inStreamSpec = new CBufInStream;
+ CMyComPtr<IInStream> inStream = inStreamSpec;
+ inStreamSpec->Init(src, packSize);
+
+ CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+ outStreamSpec->Init(buf, uncompressedSize);
+
+ UInt64 uncompressedSize64 = uncompressedSize;
+ lzhDecoderSpec->FinishMode = true;
+ /*
+ EFI 1.1 probably used small dictionary and (pbit = 4) in LZH. We don't support such archives.
+ New version of compression code (named Tiano) uses LZH with (1 << 19) dictionary.
+ But maybe LZH decoder in UEFI decoder supports larger than (1 << 19) dictionary.
+ */
+ lzhDecoderSpec->SetDictSize(1 << 19);
+
+ HRESULT res = lzhDecoder->Code(inStream, outStream, NULL, &uncompressedSize64, NULL);
+ if (res != S_OK)
+ return res;
+
+ if (lzhDecoderSpec->GetInputProcessedSize() != packSize)
+ return S_FALSE;
+ }
+
RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level));
}
else
@@ -1258,7 +969,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
if (lzmaUncompressedSize < uncompressedSize)
return S_FALSE;
SizeT destLen = (SizeT)lzmaUncompressedSize;
- int newBufIndex = AddBuf((UInt32)lzmaUncompressedSize);
+ unsigned newBufIndex = AddBuf((size_t)lzmaUncompressedSize);
CByteBuffer &buf = _bufs[newBufIndex];
ELzmaStatus status;
SizeT srcLen = newSectSize - (addSize + 5 + 8);
@@ -1278,7 +989,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
}
else if (type == SECTION_GUID_DEFINED)
{
- const UInt32 kHeaderSize = 4 + kGuidSize + 4;
+ const unsigned kHeaderSize = 4 + kGuidSize + 4;
if (sectSize < kHeaderSize)
return S_FALSE;
item.SetGuid(p + 4);
@@ -1373,7 +1084,8 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
{
item.BufIndex = AddBuf(s.Len());
CByteBuffer &buf0 = _bufs[item.BufIndex];
- memcpy(buf0, s, s.Len());
+ if (s.Len() != 0)
+ memcpy(buf0, s, s.Len());
item.Offset = 0;
item.Size = s.Len();
}
@@ -1389,7 +1101,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
{
AString s2 = "ver:";
s2 += UInt32ToString(Get16(p + 4));
- s2 += ' ';
+ s2.Add_Space();
s2 += s;
AddSpaceAndString(_items[item.Parent].Characts, s2);
needAdd = false;
@@ -1617,7 +1329,7 @@ HRESULT CHandler::ParseVolume(
HRESULT CHandler::OpenCapsule(IInStream *stream)
{
- const UInt32 kHeaderSize = 80;
+ const unsigned kHeaderSize = 80;
Byte buf[kHeaderSize];
RINOK(ReadStream_FALSE(stream, buf, kHeaderSize));
_h.Parse(buf);
@@ -1632,7 +1344,7 @@ HRESULT CHandler::OpenCapsule(IInStream *stream)
_h.OffsetToSplitInformation != 0 )
return E_NOTIMPL;
- int bufIndex = AddBuf(_h.CapsuleImageSize);
+ unsigned bufIndex = AddBuf(_h.CapsuleImageSize);
CByteBuffer &buf0 = _bufs[bufIndex];
memcpy(buf0, buf, kHeaderSize);
ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize);
@@ -1662,7 +1374,7 @@ HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosit
_phySize = ffsHeader.VolSize;
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
UInt32 fvSize32 = (UInt32)ffsHeader.VolSize;
- int bufIndex = AddBuf(fvSize32);
+ unsigned bufIndex = AddBuf(fvSize32);
RINOK(ReadStream_FALSE(stream, _bufs[bufIndex], fvSize32));
return ParseVolume(bufIndex, 0, fvSize32, fvSize32, -1, -1, 0);
}
@@ -1680,14 +1392,17 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
unsigned num = _items.Size();
CIntArr numChilds(num);
+
unsigned i;
+
for (i = 0; i < num; i++)
numChilds[i] = 0;
+
for (i = 0; i < num; i++)
{
int parent = _items[i].Parent;
if (parent >= 0)
- numChilds[parent]++;
+ numChilds[(unsigned)parent]++;
}
for (i = 0; i < num; i++)
@@ -1696,14 +1411,15 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
int parent = item.Parent;
if (parent >= 0)
{
- CItem &parentItem = _items[parent];
- if (numChilds[parent] == 1)
+ CItem &parentItem = _items[(unsigned)parent];
+ if (numChilds[(unsigned)parent] == 1)
if (!item.ThereIsUniqueName || !parentItem.ThereIsUniqueName || !parentItem.ThereAreSubDirs)
parentItem.Skip = true;
}
}
CUIntVector mainToReduced;
+
for (i = 0; i < _items.Size(); i++)
{
mainToReduced.Add(_items2.Size());
@@ -1714,14 +1430,15 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
int numItems = -1;
int parent = item.Parent;
if (parent >= 0)
- numItems = numChilds[parent];
+ numItems = numChilds[(unsigned)parent];
AString name2 = item.GetName(numItems);
AString characts2 = item.Characts;
if (item.KeepName)
name = name2;
+
while (parent >= 0)
{
- const CItem &item3 = _items[parent];
+ const CItem &item3 = _items[(unsigned)parent];
if (!item3.Skip)
break;
if (item3.KeepName)
@@ -1735,6 +1452,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
AddSpaceAndString(characts2, item3.Characts);
parent = item3.Parent;
}
+
if (name.IsEmpty())
name = name2;
@@ -1743,7 +1461,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
item2.Name = name;
item2.Characts = characts2;
if (parent >= 0)
- item2.Parent = mainToReduced[parent];
+ item2.Parent = mainToReduced[(unsigned)parent];
_items2.Add(item2);
/*
CItem2 item2;
@@ -1753,6 +1471,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
_items2.Add(item2);
*/
}
+
return S_OK;
}
@@ -1873,30 +1592,26 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
namespace UEFIc {
-IMP_CreateArcIn_2(CHandler(true))
-
-static CArcInfo g_ArcInfo =
- { "UEFIc", "scap", 0, 0xD0,
- kCapsuleSigSize, CAPSULE_SIGNATURE,
+REGISTER_ARC_I_CLS(
+ CHandler(true),
+ "UEFIc", "scap", 0, 0xD0,
+ kCapsuleSig,
0,
NArcInfoFlags::kFindSignature,
- CreateArc };
+ NULL)
-REGISTER_ARC(UEFIc)
}
namespace UEFIf {
-IMP_CreateArcIn_2(CHandler(false))
-
-static CArcInfo g_ArcInfo =
- { "UEFIf", "uefif", 0, 0xD1,
- kGuidSize, FFS_SIGNATURE,
+REGISTER_ARC_I_CLS(
+ CHandler(false),
+ "UEFIf", "uefif", 0, 0xD1,
+ k_FFS_Guid,
kFfsGuidOffset,
NArcInfoFlags::kFindSignature,
- CreateArc };
-
-REGISTER_ARC(UEFIf)
+ NULL)
+
}
}}
diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp
index a2126811..7508adfa 100644
--- a/CPP/7zip/Archive/VhdHandler.cpp
+++ b/CPP/7zip/Archive/VhdHandler.cpp
@@ -6,8 +6,6 @@
#include "../../Common/ComTry.h"
#include "../../Common/IntToString.h"
-#include "../../Common/MyBuffer.h"
-#include "../../Common/MyString.h"
#include "../../Windows/PropVariant.h"
@@ -41,7 +39,7 @@ static const UInt32 kDiskType_Fixed = 2;
static const UInt32 kDiskType_Dynamic = 3;
static const UInt32 kDiskType_Diff = 4;
-static const char *kDiskTypes[] =
+static const char * const kDiskTypes[] =
{
"0"
, "1"
@@ -201,11 +199,17 @@ bool CDynHeader::Parse(const Byte *p)
memcpy(ParentId, p + 0x28, 16);
{
const unsigned kNameLen = 256;
- wchar_t *s = ParentName.GetBuffer(kNameLen);
- for (unsigned i = 0; i < kNameLen; i++)
- s[i] = Get16(p + 0x40 + i * 2);
- s[kNameLen] = 0;
- ParentName.ReleaseBuffer();
+ wchar_t *s = ParentName.GetBuf(kNameLen);
+ unsigned i;
+ for (i = 0; i < kNameLen; i++)
+ {
+ wchar_t c = Get16(p + 0x40 + i * 2);
+ if (c == 0)
+ break;
+ s[i] = c;
+ }
+ s[i] = 0;
+ ParentName.ReleaseBuf_SetLen(i);
}
for (unsigned i = 0; i < 8; i++)
if (!ParentLocators[i].Parse(p + 0x240 + i * 24))
@@ -240,7 +244,7 @@ class CHandler:
void AddErrorMessage(const wchar_t *s)
{
if (!_errorMessage.IsEmpty())
- _errorMessage += L'\n';
+ _errorMessage.Add_LF();
_errorMessage += s;
}
void UpdatePhySize(UInt64 value)
@@ -265,7 +269,7 @@ class CHandler:
while (p && p->NeedParent())
{
if (!res.IsEmpty())
- res += L" -> ";
+ res.AddAscii(" -> ");
UString mainName;
UString anotherName;
if (Dyn.RelativeNameWasUsed)
@@ -281,7 +285,7 @@ class CHandler:
res += mainName;
if (mainName != anotherName && !anotherName.IsEmpty())
{
- res += L' ';
+ res.Add_Space();
res += L'(';
res += anotherName;
res += L')';
@@ -425,12 +429,20 @@ HRESULT CHandler::Open3()
Byte nameBuf[kNameBufSizeMax];
UString tempString;
unsigned len = (locator.DataLen >> 1);
- wchar_t *s = tempString.GetBuffer(len);
- RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen));
- for (unsigned j = 0; j < len; j++)
- s[j] = GetUi16(nameBuf + j * 2);
- s[len] = 0;
- tempString.ReleaseBuffer();
+ {
+ wchar_t *s = tempString.GetBuf(len);
+ RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen));
+ unsigned j;
+ for (j = 0; j < len; j++)
+ {
+ wchar_t c = GetUi16(nameBuf + j * 2);
+ if (c == 0)
+ break;
+ s[j] = c;
+ }
+ s[j] = 0;
+ tempString.ReleaseBuf_SetLen(j);
+ }
if (tempString[0] == L'.' && tempString[1] == L'\\')
tempString.DeleteFrontal(2);
Dyn.RelativeParentNameFromLocator = tempString;
@@ -518,10 +530,10 @@ HRESULT CHandler::Open3()
STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
if (_virtPos >= Footer.CurrentSize)
- return (Footer.CurrentSize == _virtPos) ? S_OK: E_FAIL;
+ return S_OK;
UInt64 rem = Footer.CurrentSize - _virtPos;
if (size > rem)
size = (UInt32)rem;
@@ -576,7 +588,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
cur += rem;
}
}
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = size;
_virtPos += size;
return res;
@@ -705,7 +717,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString res = s;
res.Trim();
ConvertUInt32ToString(Footer.CreatorVersion >> 16, s);
- res += ' ';
+ res.Add_Space();
res += s;
res += '.';
ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s);
@@ -971,15 +983,11 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
COM_TRY_END
}
-IMP_CreateArcIn
-
-static CArcInfo g_ArcInfo =
- { "VHD", "vhd", ".mbr", 0xDC,
- kSignatureSize, SIGNATURE,
+REGISTER_ARC_I(
+ "VHD", "vhd", ".mbr", 0xDC,
+ kSignature,
0,
NArcInfoFlags::kUseGlobalOffset,
- CreateArc };
-
-REGISTER_ARC(Vhd)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
index 886d8d77..bca551a6 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -37,7 +37,9 @@ static const Byte kProps[] =
kpidMethod,
kpidShortName,
kpidINode,
- kpidLinks
+ kpidLinks,
+ kpidIsAltStream,
+ kpidNumAltStreams,
#ifdef WIM_DETAILS
, kpidVolume
@@ -269,14 +271,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
res = kMethodLZX;
if (xpress)
{
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += kMethodXpress;
}
if (copy)
{
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += kMethodCopy;
}
prop = res;
@@ -308,6 +308,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AddErrorMessage(s, "Some files have incorrect reference count");
if (!s.IsEmpty())
prop = s;
+ break;
+ }
+
+ case kpidReadOnly:
+ {
+ bool readOnly = false;
+ if (ThereIsError())
+ readOnly = true;
+ else if (_volumes.Size() != 0)
+ {
+ if (_version != kWimVersion
+ || _volumes.Size() != 2
+ || _volumes[0].Stream
+ // || _db.Images.Size() > kNumImagesMax
+ )
+ readOnly = true;
+ }
+ if (readOnly)
+ prop = readOnly;
+ break;
}
}
prop.Detach(value);
@@ -397,6 +417,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidSize: prop = (UInt64)(si ? si->Resource.UnpackSize : 0); break;
case kpidIsDir: prop = item.IsDir; break;
case kpidIsAltStream: prop = item.IsAltStream; break;
+ case kpidNumAltStreams:
+ {
+ if (!item.IsAltStream && mainItem->HasMetadata())
+ {
+ UInt32 dirRecordSize = _db.IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;
+ UInt32 numAltStreams = Get16(metadata + dirRecordSize - 6);
+ if (numAltStreams != 0)
+ {
+ if (!item.IsDir)
+ numAltStreams--;
+ prop = numAltStreams;
+ }
+ }
+ break;
+ }
+
case kpidAttrib:
if (!item.IsAltStream && mainItem->ImageIndex >= 0)
{
@@ -481,7 +517,7 @@ STDMETHODIMP CHandler::GetRootProp(PROPID propID, PROPVARIANT *value)
{
// COM_TRY_BEGIN
NCOM::CPropVariant prop;
- if (_db.Images.Size() != 0 && _db.NumExludededItems != 0)
+ if (_db.Images.Size() != 0 && _db.NumExcludededItems != 0)
{
const CImage &image = _db.Images[_db.IndexOfUserImage];
const CItem &item = _db.Items[image.StartItem];
@@ -532,7 +568,7 @@ STDMETHODIMP CHandler::GetRootRawProp(PROPID propID, const void **data, UInt32 *
*data = 0;
*dataSize = 0;
*propType = 0;
- if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExludededItems != 0)
+ if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExcludededItems != 0)
{
const CImage &image = _db.Images[_db.IndexOfUserImage];
const CItem &item = _db.Items[image.StartItem];
@@ -705,7 +741,7 @@ class CVolumeName
public:
void InitName(const UString &name)
{
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
if (dotPos < 0)
dotPos = name.Len();
_before = name.Left(dotPos);
@@ -798,11 +834,11 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal
if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data)
{
- wchar_t sz[16];
+ char sz[16];
ConvertUInt32ToString(xml.VolIndex, sz);
xml.FileName = L'[';
- xml.FileName += sz;
- xml.FileName += L"].xml";
+ xml.FileName.AddAscii(sz);
+ xml.FileName.AddAscii("].xml");
_xmls.Add(xml);
}
@@ -957,11 +993,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
int streamIndex = item.StreamIndex;
if (streamIndex < 0)
{
- if (!testMode && !realOutStream)
- continue;
+ if (!item.IsDir)
+ if (!testMode && !realOutStream)
+ continue;
RINOK(extractCallback->PrepareOperation(askMode));
realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(_db.ItemHasStream(item) ?
+ RINOK(extractCallback->SetOperationResult(!item.IsDir && _db.ItemHasStream(item) ?
NExtract::NOperationResult::kDataError :
NExtract::NOperationResult::kOK));
continue;
@@ -1016,7 +1053,7 @@ CHandler::CHandler()
_xmlError = false;
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitDefaults();
diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h
index 416e11ca..00de1b87 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.h
+++ b/CPP/7zip/Archive/Wim/WimHandler.h
@@ -70,7 +70,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IArchiveGetRootProps(;)
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
STDMETHOD(KeepModeForNextOpen)();
INTERFACE_IOutArchive(;)
};
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
index 149989d1..145ede42 100644
--- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
@@ -21,7 +21,7 @@
#include "../../Common/UniqBlocks.h"
#include "../../Crypto/RandGen.h"
-#include "../../Crypto/Sha1.h"
+#include "../../Crypto/Sha1Cls.h"
#include "WimHandler.h"
@@ -676,6 +676,8 @@ static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaI
trees.AddNew().Dirs.AddNew().MetaIndex = metaItems.Add(ri);
}
+#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 numItems, IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN
@@ -789,7 +791,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
unsigned imageIndex = (unsigned)val - 1;
if (imageIndex < _db.Images.Size())
isChangedImage[imageIndex] = true;
- if (_defaultImageNumber > 0 && val != _defaultImageNumber)
+ if (_defaultImageNumber > 0 && val != (unsigned)_defaultImageNumber)
return E_INVALIDARG;
}
}
@@ -1065,9 +1067,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
int colonPos = fileName.Find(L':');
if (colonPos < 0)
return E_INVALIDARG;
+
+ // we want to support cases of c::substream, where c: is drive name
+ if (colonPos == 1 && fileName[2] == L':' && IS_LETTER_CHAR(fileName[0]))
+ colonPos = 2;
const UString mainName = fileName.Left(colonPos);
unsigned indexOfDir;
- if (curItem->FindDir(db.MetaItems, mainName, indexOfDir))
+
+ if (mainName.IsEmpty())
+ ui.MetaIndex = curItem->MetaIndex;
+ else if (curItem->FindDir(db.MetaItems, mainName, indexOfDir))
ui.MetaIndex = curItem->Dirs[indexOfDir].MetaIndex;
else
{
@@ -1082,6 +1091,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
}
}
}
+
if (ui.MetaIndex >= 0)
{
CAltStream ss;
@@ -1126,7 +1136,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
NCOM::CPropVariant prop;
RINOK(GetOutProperty(callback, i, arcIndex, kpidShortName, &prop));
if (prop.vt == VT_BSTR)
- mi.ShortName = prop.bstrVal;
+ mi.ShortName.SetFromBstr(prop.bstrVal);
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
@@ -1235,7 +1245,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
{
const CItem &item = _db.Items[k];
if (item.StreamIndex >= 0)
- streamsRefs[item.StreamIndex]++;
+ streamsRefs[(unsigned)item.StreamIndex]++;
}
}
@@ -1250,7 +1260,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
continue;
const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]];
if (item.StreamIndex >= 0)
- streamsRefs[item.StreamIndex]++;
+ streamsRefs[(unsigned)item.StreamIndex]++;
}
else
{
@@ -1614,7 +1624,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
db.DefaultDirItem = ri;
pos += db.WriteTree_Dummy(tree);
- CByteBuffer meta(pos);
+ CByteArr meta(pos);
Set32((Byte *)meta + 4, secBufs.Size()); // num security entries
pos = kSecuritySize;
@@ -1637,8 +1647,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
{
const CByteBuffer &buf = secBufs[i];
size_t size = buf.Size();
- memcpy(meta + pos, buf, size);
- pos += size;
+ if (size != 0)
+ {
+ memcpy(meta + pos, buf, size);
+ pos += size;
+ }
}
while ((pos & 7) != 0)
meta[pos++] = 0;
@@ -1740,15 +1753,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
size_t xmlSize;
{
- UString utf16String;
- if (!ConvertUTF8ToUnicode(xml, utf16String))
+ UString utf16;
+ if (!ConvertUTF8ToUnicode(xml, utf16))
return S_FALSE;
- xmlSize = (utf16String.Len() + 1) * 2;
+ xmlSize = (utf16.Len() + 1) * 2;
- CByteBuffer xmlBuf(xmlSize);
+ CByteArr xmlBuf(xmlSize);
Set16((Byte *)xmlBuf, 0xFEFF);
- for (i = 0; i < (unsigned)utf16String.Len(); i++)
- Set16((Byte *)xmlBuf + 2 + i * 2, utf16String[i]);
+ for (i = 0; i < (unsigned)utf16.Len(); i++)
+ Set16((Byte *)xmlBuf + 2 + i * 2, utf16[i]);
RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize));
}
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp
index cec037cc..12b8525c 100644
--- a/CPP/7zip/Archive/Wim/WimIn.cpp
+++ b/CPP/7zip/Archive/Wim/WimIn.cpp
@@ -325,10 +325,13 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
{
unsigned size = 0;
int index = index1;
- unsigned newLevel;
int imageIndex = Items[index].ImageIndex;
const CImage &image = Images[imageIndex];
- for (newLevel = 0;;)
+
+ unsigned newLevel = 0;
+ bool needColon = false;
+
+ for (;;)
{
const CItem &item = Items[index];
index = item.Parent;
@@ -338,10 +341,11 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
meta += item.IsAltStream ?
(IsOldVersion ? 0x10 : 0x24) :
(IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);
+ needColon = item.IsAltStream;
size += Get16(meta) / 2;
size += newLevel;
newLevel = 1;
- if ((UInt32)size >= ((UInt32)1 << 15))
+ if (size >= ((UInt32)1 << 15))
{
path = kLongPath;
return;
@@ -356,7 +360,9 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
size += image.RootName.Len();
size += newLevel;
}
-
+ else if (needColon)
+ size++;
+
wchar_t *s = path.AllocBstr(size);
s[size] = 0;
@@ -364,28 +370,31 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
{
MyStringCopy(s, (const wchar_t *)image.RootName);
if (newLevel)
- s[image.RootName.Len()] = WCHAR_PATH_SEPARATOR;
+ s[image.RootName.Len()] = (wchar_t)(needColon ? L':' : WCHAR_PATH_SEPARATOR);
}
+ else if (needColon)
+ s[0] = L':';
index = index1;
wchar_t separator = 0;
+
for (;;)
{
const CItem &item = Items[index];
index = item.Parent;
if (index >= 0 || image.NumEmptyRootItems == 0)
{
- if (separator)
+ if (separator != 0)
s[--size] = separator;
const Byte *meta = image.Meta + item.Offset;
meta += (item.IsAltStream) ?
(IsOldVersion ? 0x10: 0x24) :
(IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);
- UInt32 len = Get16(meta) / 2;
+ unsigned len = Get16(meta) / 2;
size -= len;
wchar_t *dest = s + size;
meta += 2;
- for (UInt32 i = 0; i < len; i++)
+ for (unsigned i = 0; i < len; i++)
dest[i] = Get16(meta + i * 2);
}
if (index < 0)
@@ -394,6 +403,14 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
}
}
+static bool IsEmptySha(const Byte *data)
+{
+ for (unsigned i = 0; i < kHashSize; i++)
+ if (data[i] != 0)
+ return false;
+ return true;
+}
+
// Root folders in OLD archives (ver = 1.10) conatin real items.
// Root folders in NEW archives (ver > 1.11) contain only one folder with empty name.
@@ -472,6 +489,8 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
pos += (size_t)len;
+ unsigned numItems2 = Items.Size();
+
for (UInt32 i = 0; i < numAltStreams; i++)
{
size_t rem = DirSize - pos;
@@ -522,7 +541,13 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
return S_FALSE;
}
- if (fileNameLen == 0)
+
+ /* wim uses alt sreams list, if there is at least one alt stream.
+ And alt stream without name is main stream. */
+
+ if (fileNameLen == 0 &&
+ (attrib & FILE_ATTRIBUTE_REPARSE_POINT
+ || !item.IsDir /* && (IsOldVersion || IsEmptySha(prevMeta + 0x40)) */ ))
{
Byte *prevMeta = DirData + item.Offset;
if (IsOldVersion)
@@ -546,7 +571,7 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
if (parent < 0 && numItems == 0 && shortNameLen == 0 && fileNameLen == 0 && item.IsDir)
{
CImage &image = Images.Back();
- image.NumEmptyRootItems = Items.Size() - image.StartItem;
+ image.NumEmptyRootItems = numItems2 - image.StartItem; // Items.Size()
}
if (item.IsDir && subdirOffset != 0)
@@ -732,14 +757,6 @@ static HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
return (i == offsetBuf.Size()) ? S_OK : S_FALSE;
}
-static bool IsEmptySha(const Byte *data)
-{
- for (unsigned i = 0; i < kHashSize; i++)
- if (data[i] != 0)
- return false;
- return true;
-}
-
HRESULT CDatabase::OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml)
{
return UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL);
@@ -1046,7 +1063,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
SortedItems.Clear();
VirtualRoots.Clear();
IndexOfUserImage = imageIndex;
- NumExludededItems = 0;
+ NumExcludededItems = 0;
ExludedItem = -1;
if (Images.Size() != 1 && imageIndex < 0)
@@ -1054,6 +1071,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
unsigned startItem = 0;
unsigned endItem = 0;
+
if (imageIndex < 0)
{
endItem = Items.Size();
@@ -1062,7 +1080,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
IndexOfUserImage = 0;
const CImage &image = Images[0];
if (!showImageNumber)
- NumExludededItems = image.NumEmptyRootItems;
+ NumExcludededItems = image.NumEmptyRootItems;
}
}
else if ((unsigned)imageIndex < Images.Size())
@@ -1071,12 +1089,13 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
startItem = image.StartItem;
endItem = startItem + image.NumItems;
if (!showImageNumber)
- NumExludededItems = image.NumEmptyRootItems;
+ NumExcludededItems = image.NumEmptyRootItems;
}
- if (NumExludededItems != 0)
+
+ if (NumExcludededItems != 0)
{
ExludedItem = startItem;
- startItem += NumExludededItems;
+ startItem += NumExcludededItems;
}
unsigned num = endItem - startItem;
@@ -1205,7 +1224,8 @@ HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes,
Byte *dest = (Byte *)reparse;
SetUi32(dest, tag);
SetUi32(dest + 4, (UInt32)buf.Size());
- memcpy(dest + 8, buf, buf.Size());
+ if (buf.Size() != 0)
+ memcpy(dest + 8, buf, buf.Size());
ItemToReparse[i] = ReparseItems.Size() - 1;
}
@@ -1278,20 +1298,28 @@ void CWimXml::ToUnicode(UString &s)
const Byte *p = Data;
if (Get16(p) != 0xFEFF)
return;
- wchar_t *chars = s.GetBuffer((unsigned)size / 2);
+ wchar_t *chars = s.GetBuf((unsigned)(size / 2));
for (size_t i = 2; i < size; i += 2)
- *chars++ = (wchar_t)Get16(p + i);
+ {
+ wchar_t c = Get16(p + i);
+ if (c == 0)
+ break;
+ *chars++ = c;
+ }
*chars = 0;
- s.ReleaseBuffer();
+ s.ReleaseBuf_SetLen((unsigned)(chars - (const wchar_t *)s));
}
bool CWimXml::Parse()
{
- UString s;
- ToUnicode(s);
AString utf;
- if (!ConvertUnicodeToUTF8(s, utf))
- return false;
+ {
+ UString s;
+ ToUnicode(s);
+ // if (!ConvertUnicodeToUTF8(s, utf)) return false;
+ ConvertUnicodeToUTF8(s, utf);
+ }
+
if (!Xml.Parse(utf))
return false;
if (Xml.Root.Name != "WIM")
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h
index 4b7c6d95..c3b93a8d 100644
--- a/CPP/7zip/Archive/Wim/WimIn.h
+++ b/CPP/7zip/Archive/Wim/WimIn.h
@@ -406,7 +406,7 @@ public:
CUIntVector SortedItems;
int IndexOfUserImage; // -1 : if more than one images was filled to Sorted Items
- unsigned NumExludededItems;
+ unsigned NumExcludededItems;
int ExludedItem; // -1 : if there are no exclude items
CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives
@@ -418,7 +418,7 @@ public:
return 0;
if (imageIndex >= Images.Size())
return 0;
- return Images[imageIndex].NumItems - NumExludededItems;
+ return Images[imageIndex].NumItems - NumExcludededItems;
}
bool ItemHasStream(const CItem &item) const;
diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp
index 35d78314..3063dec4 100644
--- a/CPP/7zip/Archive/Wim/WimRegister.cpp
+++ b/CPP/7zip/Archive/Wim/WimRegister.cpp
@@ -9,19 +9,14 @@
namespace NArchive {
namespace NWim {
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "wim", "wim swm", 0, 0xE6,
- 8, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 },
+REGISTER_ARC_IO(
+ "wim", "wim swm", 0, 0xE6,
+ kSignature,
0,
NArcInfoFlags::kAltStreams |
NArcInfoFlags::kNtSecure |
NArcInfoFlags::kSymLinks |
NArcInfoFlags::kHardLinks
- , REF_CreateArc_Pair };
-
-REGISTER_ARC(Wim)
+ , NULL)
}}
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp
index 918ef736..7e89bf48 100644
--- a/CPP/7zip/Archive/XarHandler.cpp
+++ b/CPP/7zip/Archive/XarHandler.cpp
@@ -35,15 +35,15 @@ using namespace NWindows;
namespace NArchive {
namespace NXar {
-static const UInt32 kXmlSizeMax = ((UInt32)1 << 30) - (1 << 14);
-static const UInt32 kXmlPackSizeMax = kXmlSizeMax;
+static const size_t kXmlSizeMax = ((size_t )1 << 30) - (1 << 14);
+static const size_t kXmlPackSizeMax = kXmlSizeMax;
/*
#define XAR_CKSUM_NONE 0
#define XAR_CKSUM_SHA1 1
#define XAR_CKSUM_MD5 2
-static const char *k_ChecksumAlgos[] =
+static const char * const k_ChecksumAlgos[] =
{
"None"
, "SHA-1"
@@ -76,8 +76,8 @@ struct CFile
bool Sha1IsDefined;
// bool packSha1IsDefined;
- Byte Sha1[NCrypto::NSha1::kDigestSize];
- // Byte packSha1[NCrypto::NSha1::kDigestSize];
+ Byte Sha1[SHA1_DIGEST_SIZE];
+ // Byte packSha1[SHA1_DIGEST_SIZE];
int Parent;
@@ -107,7 +107,8 @@ class CHandler:
{
UInt64 _dataStartPos;
CMyComPtr<IInStream> _inStream;
- AString _xml;
+ CByteArr _xml;
+ size_t _xmlLen;
CObjectVector<CFile> _files;
// UInt32 _checkSumAlgo;
UInt64 _phySize;
@@ -182,7 +183,7 @@ static UInt64 ParseTime(const CXmlItem &item, const char *name)
return numSecs * 10000000;
}
-static int HexToByte(char c)
+static int HexToByte(unsigned char c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
@@ -200,7 +201,7 @@ static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest)
if (style == "SHA1")
{
const AString s = checkItem.GetSubString();
- if (s.Len() != NCrypto::NSha1::kDigestSize * 2)
+ if (s.Len() != SHA1_DIGEST_SIZE * 2)
return false;
for (unsigned i = 0; i < s.Len(); i += 2)
{
@@ -321,8 +322,9 @@ HRESULT CHandler::Open2(IInStream *stream)
_dataStartPos = kHeaderSize + packSize;
_phySize = _dataStartPos;
- char *ss = _xml.GetBuffer((unsigned)unpackSize);
-
+ _xml.Alloc((size_t)unpackSize + 1);
+ _xmlLen = (size_t)unpackSize;
+
NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();
CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;
@@ -333,18 +335,18 @@ HRESULT CHandler::Open2(IInStream *stream)
CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream;
CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec);
- outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize);
+ outStreamLimSpec->Init(_xml, (size_t)unpackSize);
RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL));
if (outStreamLimSpec->GetPos() != (size_t)unpackSize)
return S_FALSE;
- ss[(size_t)unpackSize] = 0;
- _xml.ReleaseBuffer();
+ _xml[(size_t)unpackSize] = 0;
+ if (strlen((const char *)(const Byte *)_xml) != unpackSize) return S_FALSE;
CXml xml;
- if (!xml.Parse(_xml))
+ if (!xml.Parse((const char *)(const Byte *)_xml))
return S_FALSE;
if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1)
@@ -390,7 +392,8 @@ STDMETHODIMP CHandler::Close()
_phySize = 0;
_inStream.Release();
_files.Clear();
- _xml.Empty();
+ _xmlLen = 0;
+ _xml.Free();
_mainSubfile = -1;
_is_pkg = false;
return S_OK;
@@ -456,7 +459,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath: prop = "[TOC].xml"; break;
case kpidSize:
- case kpidPackSize: prop = (UInt64)_xml.Len(); break;
+ case kpidPackSize: prop = (UInt64)_xmlLen; break;
}
}
else
@@ -531,7 +534,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt32 index = (allFilesMode ? i : indices[i]);
#ifdef XAR_SHOW_RAW
if (index == _files.Size())
- totalSize += _xml.Len();
+ totalSize += _xmlLen;
else
#endif
totalSize += _files[index].Size;
@@ -614,9 +617,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (index == _files.Size())
{
outStreamSha1Spec->Init(false);
- outStreamLimSpec->Init(_xml.Len());
- RINOK(WriteStream(outStream, (const char *)_xml, _xml.Len()));
- currentPackSize = currentUnpSize = _xml.Len();
+ outStreamLimSpec->Init(_xmlLen);
+ RINOK(WriteStream(outStream, _xml, _xmlLen));
+ currentPackSize = currentUnpSize = _xmlLen;
}
else
#endif
@@ -670,9 +673,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
else if (item.Sha1IsDefined)
{
- Byte digest[NCrypto::NSha1::kDigestSize];
+ Byte digest[SHA1_DIGEST_SIZE];
outStreamSha1Spec->Final(digest);
- if (memcmp(digest, item.Sha1, NCrypto::NSha1::kDigestSize) != 0)
+ if (memcmp(digest, item.Sha1, SHA1_DIGEST_SIZE) != 0)
opRes = NExtract::NOperationResult::kCRCError;
}
}
@@ -695,7 +698,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
#ifdef XAR_SHOW_RAW
if (index == _files.Size())
{
- Create_BufInStream_WithNewBuf((const void *)(const char *)_xml, _xml.Len(), stream);
+ Create_BufInStream_WithNewBuffer(_xml, _xmlLen, stream);
return S_OK;
}
else
@@ -709,15 +712,13 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 'x', 'a', 'r', '!', 0, 0x1C };
-static CArcInfo g_ArcInfo =
- { "Xar", "xar pkg", 0, 0xE1,
- 6, { 'x', 'a', 'r', '!', 0, 0x1C },
+REGISTER_ARC_I(
+ "Xar", "xar pkg", 0, 0xE1,
+ k_Signature,
0,
0,
- CreateArc };
-
-REGISTER_ARC(Xar)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 0de58a44..ada14fbf 100644
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -23,6 +23,8 @@
#include "Common/HandlerOut.h"
+#include "XzHandler.h"
+
using namespace NWindows;
namespace NCompress {
@@ -32,92 +34,36 @@ HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzm
}}
-static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }
-static void SzFree(void *, void *address) { MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
namespace NArchive {
namespace NXz {
struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
-static const wchar_t *k_LZMA2_Name = L"LZMA2";
+static const char *k_LZMA2_Name = "LZMA2";
-struct CStatInfo
+void CStatInfo::Clear()
{
- UInt64 InSize;
- UInt64 OutSize;
- UInt64 PhySize;
-
- UInt64 NumStreams;
- UInt64 NumBlocks;
-
- bool UnpackSize_Defined;
-
- bool NumStreams_Defined;
- bool NumBlocks_Defined;
-
- bool IsArc;
- bool UnexpectedEnd;
- bool DataAfterEnd;
- bool Unsupported;
- bool HeadersError;
- bool DataError;
- bool CrcError;
-
- CStatInfo() { Clear(); }
-
- void Clear()
- {
- InSize = 0;
- OutSize = 0;
- PhySize = 0;
-
- NumStreams = 0;
- NumBlocks = 0;
-
- UnpackSize_Defined = false;
+ InSize = 0;
+ OutSize = 0;
+ PhySize = 0;
- NumStreams_Defined = false;
- NumBlocks_Defined = false;
-
- UnexpectedEnd = false;
- DataAfterEnd = false;
- Unsupported = false;
- HeadersError = false;
- DataError = false;
- CrcError = false;
- IsArc = false;
- }
-
-};
-
-struct IDecodeState: public CStatInfo
-{
- SRes DecodeRes;
-
- IDecodeState(): DecodeRes(SZ_OK) {}
- virtual HRESULT Progress() = 0;
-
- HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream);
-};
-
-struct CVirtProgress_To_LocalProgress: public IDecodeState
-{
- CLocalProgress *lps;
- CMyComPtr<ICompressProgressInfo> progress;
-
- HRESULT Progress();
-};
-
-HRESULT CVirtProgress_To_LocalProgress::Progress()
-{
- lps->InSize = InSize;
- lps->OutSize = OutSize;
- return lps->SetCur();
+ NumStreams = 0;
+ NumBlocks = 0;
+
+ UnpackSize_Defined = false;
+
+ NumStreams_Defined = false;
+ NumBlocks_Defined = false;
+
+ IsArc = false;
+ UnexpectedEnd = false;
+ DataAfterEnd = false;
+ Unsupported = false;
+ HeadersError = false;
+ DataError = false;
+ CrcError = false;
}
-
class CHandler:
public IInArchive,
public IArchiveOpenSeq,
@@ -148,10 +94,11 @@ class CHandler:
HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);
- HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, IDecodeState &progress)
+ HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
+ CDecoder &decoder, ICompressProgressInfo *progress)
{
- RINOK(progress.Decode(seqInStream, outStream));
- _stat = progress;
+ RINOK(decoder.Decode(seqInStream, outStream, progress));
+ _stat = decoder;
_phySize_Defined = true;
return S_OK;
}
@@ -171,7 +118,7 @@ public:
#ifndef EXTRACT_ONLY
INTERFACE_IOutArchive(;)
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
CHandler();
@@ -295,12 +242,11 @@ static AString GetMethodString(const CXzFilter &f)
static void AddString(AString &dest, const AString &src)
{
- if (!dest.IsEmpty())
- dest += ' ';
+ dest.Add_Space_if_NotEmpty();
dest += src;
}
-static const char *kChecks[] =
+static const char * const kChecks[] =
{
"NoCheck"
, "CRC32"
@@ -423,26 +369,6 @@ struct CXzsCPP
~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }
};
-
-struct CVirtProgress_To_OpenProgress: public IDecodeState
-{
- IArchiveOpenCallback *Callback;
- UInt64 Offset;
-
- HRESULT Progress();
-};
-
-HRESULT CVirtProgress_To_OpenProgress::Progress()
-{
- if (Callback)
- {
- UInt64 files = 0;
- UInt64 value = Offset + InSize;
- return Callback->SetCompleted(&files, &value);
- }
- return S_OK;
-}
-
static HRESULT SRes_to_Open_HRESULT(SRes res)
{
switch (res)
@@ -527,6 +453,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
{
res = SZ_OK;
}
+
RINOK(SRes_to_Open_HRESULT(res));
_stream = inStream;
_seqStream = inStream;
@@ -587,38 +514,32 @@ STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSi
STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; }
-struct CXzUnpackerCPP
+CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0)
{
- Byte *InBuf;
- Byte *OutBuf;
- CXzUnpacker p;
-
- CXzUnpackerCPP(): InBuf(0), OutBuf(0)
- {
- XzUnpacker_Construct(&p, &g_Alloc);
- }
- ~CXzUnpackerCPP()
- {
- XzUnpacker_Free(&p);
- MyFree(InBuf);
- MyFree(OutBuf);
- }
-};
+ XzUnpacker_Construct(&p, &g_Alloc);
+}
+
+CXzUnpackerCPP::~CXzUnpackerCPP()
+{
+ XzUnpacker_Free(&p);
+ MyFree(InBuf);
+ MyFree(OutBuf);
+}
-HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream)
+HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
const size_t kInBufSize = 1 << 15;
const size_t kOutBufSize = 1 << 21;
+ Clear();
DecodeRes = SZ_OK;
- CXzUnpackerCPP xzu;
XzUnpacker_Init(&xzu.p);
- xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
- xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
- if (!xzu.InBuf || !xzu.OutBuf)
- return E_OUTOFMEMORY;
-
+ if (!xzu.InBuf)
+ xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
+ if (!xzu.OutBuf)
+ xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
+
UInt32 inSize = 0;
SizeT inPos = 0;
SizeT outPos = 0;
@@ -664,7 +585,10 @@ HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStr
else
outPos = 0;
- RINOK(Progress());
+ if (progress)
+ {
+ RINOK(progress->SetRatioInfo(&InSize, &OutSize));
+ }
if (finished)
{
@@ -730,6 +654,30 @@ HRESULT IDecodeState::Decode(ISequentialInStream *seqInStream, ISequentialOutStr
return S_OK;
}
+Int32 CDecoder::Get_Extract_OperationResult() const
+{
+ Int32 opRes;
+ if (!IsArc)
+ opRes = NExtract::NOperationResult::kIsNotArc;
+ else if (UnexpectedEnd)
+ opRes = NExtract::NOperationResult::kUnexpectedEnd;
+ else if (DataAfterEnd)
+ opRes = NExtract::NOperationResult::kDataAfterEnd;
+ else if (CrcError)
+ opRes = NExtract::NOperationResult::kCRCError;
+ else if (Unsupported)
+ opRes = NExtract::NOperationResult::kUnsupportedMethod;
+ else if (HeadersError)
+ opRes = NExtract::NOperationResult::kDataError;
+ else if (DataError)
+ opRes = NExtract::NOperationResult::kDataError;
+ else if (DecodeRes != SZ_OK)
+ opRes = NExtract::NOperationResult::kDataError;
+ else
+ opRes = NExtract::NOperationResult::kOK;
+ return opRes;
+}
+
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
@@ -739,7 +687,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
return E_INVALIDARG;
- extractCallback->SetTotal(_stat.PhySize);
+ if (_phySize_Defined)
+ extractCallback->SetTotal(_stat.PhySize);
+
UInt64 currentTotalPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
@@ -754,11 +704,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
extractCallback->PrepareOperation(askMode);
- CVirtProgress_To_LocalProgress vp;
- vp.lps = new CLocalProgress;
- vp.progress = vp.lps;
- vp.lps->Init(extractCallback, true);
-
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> lpsRef = lps;
+ lps->Init(extractCallback, true);
if (_needSeekToStart)
{
@@ -769,28 +717,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else
_needSeekToStart = true;
- RINOK(Decode2(_seqStream, realOutStream, vp));
-
- Int32 opRes;
-
- if (!vp.IsArc)
- opRes = NExtract::NOperationResult::kIsNotArc;
- else if (vp.UnexpectedEnd)
- opRes = NExtract::NOperationResult::kUnexpectedEnd;
- else if (vp.DataAfterEnd)
- opRes = NExtract::NOperationResult::kDataAfterEnd;
- else if (vp.CrcError)
- opRes = NExtract::NOperationResult::kCRCError;
- else if (vp.Unsupported)
- opRes = NExtract::NOperationResult::kUnsupportedMethod;
- else if (vp.HeadersError)
- opRes = NExtract::NOperationResult::kDataError;
- else if (vp.DataError)
- opRes = NExtract::NOperationResult::kDataError;
- else if (vp.DecodeRes != SZ_OK)
- opRes = NExtract::NOperationResult::kDataError;
- else
- opRes = NExtract::NOperationResult::kOK;
+ CDecoder decoder;
+ RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef));
+ Int32 opRes = decoder.Get_Extract_OperationResult();
realOutStream.Release();
return extractCallback->SetOperationResult(opRes);
@@ -808,6 +737,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *updateCallback)
{
+ COM_TRY_BEGIN
+
CSeqOutStreamWrap seqOutStream(outStream);
if (numItems == 0)
@@ -927,16 +858,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
return SResToHRESULT(res);
}
+
if (indexInArchive != 0)
return E_INVALIDARG;
+
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate))
+ }
+
if (_stream)
+ {
+ if (_phySize_Defined)
+ RINOK(updateCallback->SetTotal(_stat.PhySize));
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
- return NCompress::CopyStream(_stream, outStream, NULL);
+ }
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ return NCompress::CopyStream(_stream, outStream, progress);
+
+ COM_TRY_END
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
+
Init();
for (UInt32 i = 0; i < numProps; i++)
{
@@ -964,28 +916,25 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
return E_INVALIDARG;
if (_methods.Size() == 1)
{
- UString &methodName = _methods[0].MethodName;
+ AString &methodName = _methods[0].MethodName;
if (methodName.IsEmpty())
methodName = k_LZMA2_Name;
- else if (!methodName.IsEqualToNoCase(k_LZMA2_Name))
+ else if (!methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name))
return E_INVALIDARG;
}
+
return S_OK;
+
COM_TRY_END
}
#endif
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "xz", "xz txz", "* .tar", 0xC,
- 6, { 0xFD, '7' , 'z', 'X', 'Z', 0 },
+REGISTER_ARC_IO(
+ "xz", "xz txz", "* .tar", 0xC,
+ XZ_SIG,
0,
NArcInfoFlags::kKeepName,
- REF_CreateArc_Pair };
-
-REGISTER_ARC(xz)
+ NULL)
}}
diff --git a/CPP/7zip/Archive/XzHandler.h b/CPP/7zip/Archive/XzHandler.h
new file mode 100644
index 00000000..4a59e356
--- /dev/null
+++ b/CPP/7zip/Archive/XzHandler.h
@@ -0,0 +1,65 @@
+// XzHandler.h
+
+#ifndef __XZ_HANDLER_H
+#define __XZ_HANDLER_H
+
+#include "../../../C/Xz.h"
+
+#include "../ICoder.h"
+
+namespace NArchive {
+namespace NXz {
+
+struct CXzUnpackerCPP
+{
+ Byte *InBuf;
+ Byte *OutBuf;
+ CXzUnpacker p;
+
+ CXzUnpackerCPP();
+ ~CXzUnpackerCPP();
+};
+
+struct CStatInfo
+{
+ UInt64 InSize;
+ UInt64 OutSize;
+ UInt64 PhySize;
+
+ UInt64 NumStreams;
+ UInt64 NumBlocks;
+
+ bool UnpackSize_Defined;
+
+ bool NumStreams_Defined;
+ bool NumBlocks_Defined;
+
+ bool IsArc;
+ bool UnexpectedEnd;
+ bool DataAfterEnd;
+ bool Unsupported;
+ bool HeadersError;
+ bool DataError;
+ bool CrcError;
+
+ CStatInfo() { Clear(); }
+
+ void Clear();
+};
+
+struct CDecoder: public CStatInfo
+{
+ CXzUnpackerCPP xzu;
+ SRes DecodeRes; // it's not HRESULT
+
+ CDecoder(): DecodeRes(SZ_OK) {}
+
+ /* Decode() can return ERROR code only if there is progress or stream error.
+ Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */
+ HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress);
+ Int32 Get_Extract_OperationResult() const;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/ZHandler.cpp b/CPP/7zip/Archive/ZHandler.cpp
index 7635f22d..29934367 100644
--- a/CPP/7zip/Archive/ZHandler.cpp
+++ b/CPP/7zip/Archive/ZHandler.cpp
@@ -224,15 +224,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMP_CreateArcIn
+static const Byte k_Signature[] = { 0x1F, 0x9D };
-static CArcInfo g_ArcInfo =
- { "Z", "z taz", "* .tar", 5,
- 2, { 0x1F, 0x9D },
+REGISTER_ARC_I(
+ "Z", "z taz", "* .tar", 5,
+ k_Signature,
0,
0,
- CreateArc, NULL, IsArc_Z };
-
-REGISTER_ARC(Z)
+ IsArc_Z)
}}
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
index 9a0d7515..c9c290aa 100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "../../../../C/7zCrc.h"
+#include "../../../../C/Alloc.h"
#include "../../../Windows/PropVariant.h"
@@ -77,32 +78,46 @@ STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStr
CAddCommon::CAddCommon(const CCompressionMethodMode &options):
- _options(options),
- _copyCoderSpec(NULL),
- _cryptoStreamSpec(0)
- {}
+ _options(options),
+ _copyCoderSpec(NULL),
+ _cryptoStreamSpec(NULL),
+ _buf(NULL)
+ {}
-static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
+CAddCommon::~CAddCommon()
{
+ MidFree(_buf);
+}
+
+static const UInt32 kBufSize = ((UInt32)1 << 16);
+
+HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
+{
+ if (!_buf)
+ {
+ _buf = (Byte *)MidAlloc(kBufSize);
+ if (!_buf)
+ return E_OUTOFMEMORY;
+ }
+
UInt32 crc = CRC_INIT_VAL;
- const UInt32 kBufSize = (1 << 14);
- Byte buf[kBufSize];
for (;;)
{
UInt32 processed;
- RINOK(inStream->Read(buf, kBufSize, &processed));
+ RINOK(inStream->Read(_buf, kBufSize, &processed));
if (processed == 0)
{
resultCRC = CRC_GET_DIGEST(crc);
return S_OK;
}
- crc = CrcUpdate(crc, buf, (size_t)processed);
+ crc = CrcUpdate(crc, _buf, (size_t)processed);
}
}
HRESULT CAddCommon::Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
+ UInt32 /* fileTime */,
ICompressProgressInfo *progress, CCompressingResult &opRes)
{
if (!inStream)
@@ -111,13 +126,14 @@ HRESULT CAddCommon::Compress(
return E_INVALIDARG;
}
- CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL;
+ // CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL;
CInStreamWithCRC *inCrcStreamSpec = NULL;
CMyComPtr<ISequentialInStream> inCrcStream;
{
CMyComPtr<IInStream> inStream2;
- // we don't support stdin, since stream from stdin can require 64-bit size header
- RINOK(inStream->QueryInterface(IID_IInStream, (void **)&inStream2));
+
+ inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
+
if (inStream2)
{
inCrcStreamSpec = new CInStreamWithCRC;
@@ -127,28 +143,29 @@ HRESULT CAddCommon::Compress(
}
else
{
+ // we don't support stdin, since stream from stdin can require 64-bit size header
+ return E_NOTIMPL;
+ /*
inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
inCrcStream = inSecCrcStreamSpec;
inSecCrcStreamSpec->SetStream(inStream);
inSecCrcStreamSpec->Init();
+ */
}
}
unsigned numTestMethods = _options.MethodSequence.Size();
- if (numTestMethods > 1 || _options.PasswordIsDefined)
- {
- if (!inCrcStreamSpec)
- {
- if (_options.PasswordIsDefined)
- return E_NOTIMPL;
- numTestMethods = 1;
- }
- }
+ if (numTestMethods > 1 && !inCrcStreamSpec)
+ numTestMethods = 1;
+
+ UInt32 crc = 0;
+ bool crc_IsCalculated = false;
Byte method = 0;
- COutStreamReleaser outStreamReleaser;
+ CFilterCoder::C_OutStream_Releaser outStreamReleaser;
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
+ opRes.FileTimeWasUsed = false;
for (unsigned i = 0; i < numTestMethods; i++)
{
@@ -164,7 +181,7 @@ HRESULT CAddCommon::Compress(
if (!_cryptoStream)
{
- _cryptoStreamSpec = new CFilterCoder;
+ _cryptoStreamSpec = new CFilterCoder(true);
_cryptoStream = _cryptoStreamSpec;
}
@@ -186,13 +203,32 @@ HRESULT CAddCommon::Compress(
_cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
_filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len());
}
- UInt32 crc = 0;
- RINOK(GetStreamCRC(inStream, crc));
- RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
- RINOK(_filterSpec->WriteHeader(outStream, crc));
+
+ UInt32 check;
+
+ // if (inCrcStreamSpec)
+ {
+ if (!crc_IsCalculated)
+ {
+ RINOK(CalcStreamCRC(inStream, crc));
+ crc_IsCalculated = true;
+ RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+ check = (crc >> 16);
+ }
+ /*
+ else
+ {
+ opRes.FileTimeWasUsed = true;
+ check = (fileTime & 0xFFFF);
+ }
+ */
+
+ RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
}
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
+ RINOK(_cryptoStreamSpec->InitEncoder());
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
}
@@ -250,7 +286,7 @@ HRESULT CAddCommon::Compress(
}
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- methodId, _compressEncoder, true));
+ methodId, true, _compressEncoder));
if (!_compressEncoder)
return E_NOTIMPL;
@@ -284,34 +320,42 @@ HRESULT CAddCommon::Compress(
}
}
+ if (_options.PasswordIsDefined)
+ {
+ RINOK(_cryptoStreamSpec->OutStreamFinish());
+
+ if (_options.IsAesMode)
+ {
+ RINOK(_filterAesSpec->WriteFooter(outStream));
+ }
+ }
+
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
- if (inCrcStreamSpec)
+ // if (inCrcStreamSpec)
{
opRes.CRC = inCrcStreamSpec->GetCRC();
opRes.UnpackSize = inCrcStreamSpec->GetSize();
}
+ /*
else
{
opRes.CRC = inSecCrcStreamSpec->GetCRC();
opRes.UnpackSize = inSecCrcStreamSpec->GetSize();
}
+ */
if (_options.PasswordIsDefined)
{
if (opRes.PackSize < opRes.UnpackSize +
- (_options.IsAesMode ? _filterAesSpec->GetHeaderSize() : NCrypto::NZip::kHeaderSize))
+ (_options.IsAesMode ? _filterAesSpec->GetAddPackSize() : NCrypto::NZip::kHeaderSize))
break;
}
else if (opRes.PackSize < opRes.UnpackSize)
break;
}
-
- if (_options.PasswordIsDefined && _options.IsAesMode)
- {
- RINOK(_filterAesSpec->WriteFooter(outStream));
- RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
- }
+
+
opRes.Method = method;
return S_OK;
}
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h
index e4c02db3..1e0c3bfa 100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.h
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h
@@ -26,6 +26,7 @@ struct CCompressingResult
UInt32 CRC;
UInt16 Method;
Byte ExtractVersion;
+ bool FileTimeWasUsed;
};
class CAddCommon
@@ -43,11 +44,16 @@ class CAddCommon
NCrypto::NZip::CEncoder *_filterSpec;
NCrypto::NWzAes::CEncoder *_filterAesSpec;
+ Byte *_buf;
+
+ HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC);
public:
CAddCommon(const CCompressionMethodMode &options);
+ ~CAddCommon();
HRESULT Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
+ UInt32 fileTime,
ICompressProgressInfo *progress, CCompressingResult &operationResult);
};
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index f556068c..3e29a880 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -28,6 +28,8 @@
#include "../Common/ItemNameUtils.h"
#include "../Common/OutStreamWithCRC.h"
+#include "../XzHandler.h"
+
#include "ZipHandler.h"
using namespace NWindows;
@@ -38,7 +40,7 @@ namespace NZip {
static const CMethodId kMethodId_ZipBase = 0x040100;
static const CMethodId kMethodId_BZip2 = 0x040202;
-static const char *kHostOS[] =
+static const char * const kHostOS[] =
{
"FAT"
, "AMIGA"
@@ -62,7 +64,7 @@ static const char *kHostOS[] =
, "OS/X"
};
-static const char *kMethods[] =
+static const char * const kMethods[] =
{
"Store"
, "Shrink"
@@ -91,6 +93,7 @@ static const CIdToNamePair k_MethodIdNamePairs[] =
{
{ NFileHeader::NCompressionMethod::kBZip2, "BZip2" },
{ NFileHeader::NCompressionMethod::kLZMA, "LZMA" },
+ { NFileHeader::NCompressionMethod::kXz, "xz" },
{ NFileHeader::NCompressionMethod::kJpeg, "Jpeg" },
{ NFileHeader::NCompressionMethod::kWavPack, "WavPack" },
{ NFileHeader::NCompressionMethod::kPPMd, "PPMd" }
@@ -156,14 +159,7 @@ CHandler::CHandler()
static AString BytesToString(const CByteBuffer &data)
{
AString s;
- unsigned size = (unsigned)data.Size();
- if (size > 0)
- {
- char *p = s.GetBuffer(size);
- memcpy(p, (const Byte *)data, size);
- p[size] = 0;
- s.ReleaseBuffer();
- }
+ s.SetFrom_CalcLen((const char *)(const Byte *)data, (unsigned)data.Size());
return s;
}
@@ -220,6 +216,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
prop = v;
break;
}
+
+ case kpidReadOnly:
+ {
+ if (m_Archive.IsOpen())
+ if (!m_Archive.CanUpdate())
+ prop = true;
+ break;
+ }
}
prop.Detach(value);
COM_TRY_END
@@ -334,12 +338,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidMethod:
{
- UInt16 methodId = item.Method;
+ unsigned id = item.Method;
AString m;
if (item.IsEncrypted())
{
- if (methodId == NFileHeader::NCompressionMethod::kWzAES)
+ if (id == NFileHeader::NCompressionMethod::kWzAES)
{
m += kMethod_AES;
CWzAesExtra aesField;
@@ -349,7 +353,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
s[0] = '-';
ConvertUInt32ToString(((unsigned)aesField.Strength + 1) * 64 , s + 1);
m += s;
- methodId = aesField.Method;
+ id = aesField.Method;
}
}
else if (item.IsStrongEncrypted())
@@ -381,19 +385,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
char temp[16];
const char *s = NULL;
- if (methodId < ARRAY_SIZE(kMethods))
- s = kMethods[methodId];
+ if (id < ARRAY_SIZE(kMethods))
+ s = kMethods[id];
else
{
- s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), methodId);
+ s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), id);
if (!s)
{
- ConvertUInt32ToString(methodId, temp);
+ ConvertUInt32ToString(id, temp);
s = temp;
}
}
m += s;
- if (methodId == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS())
+ if (id == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS())
m += ":EOS";
}
@@ -507,9 +511,36 @@ HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *
return Decoder->Code(inStream, outStream, NULL, outSize, progress);
}
+
+class CXzDecoder:
+ public ICompressCoder,
+ public CMyUnknownImp
+{
+ NArchive::NXz::CDecoder _decoder;
+public:
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+
+ MY_UNKNOWN_IMP
+};
+
+HRESULT CXzDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
+{
+ RINOK(_decoder.Decode(inStream, outStream, progress));
+ Int32 opRes = _decoder.Get_Extract_OperationResult();
+ if (opRes == NExtract::NOperationResult::kUnsupportedMethod)
+ return E_NOTIMPL;
+ if (opRes != NExtract::NOperationResult::kOK)
+ return S_FALSE;
+ return S_OK;
+}
+
+
struct CMethodItem
{
- UInt16 ZipMethod;
+ unsigned ZipMethod;
CMyComPtr<ICompressCoder> Coder;
};
@@ -559,12 +590,13 @@ HRESULT CZipDecoder::Decode(
Int32 &res)
{
res = NExtract::NOperationResult::kDataError;
- CInStreamReleaser inStreamReleaser;
+ CFilterCoder::C_InStream_Releaser inStreamReleaser;
bool needCRC = true;
bool wzAesMode = false;
bool pkAesMode = false;
- UInt16 methodId = item.Method;
+ unsigned id = item.Method;
+
if (item.IsEncrypted())
{
if (item.IsStrongEncrypted())
@@ -580,7 +612,7 @@ HRESULT CZipDecoder::Decode(
return S_OK;
}
}
- if (!pkAesMode && methodId == NFileHeader::NCompressionMethod::kWzAES)
+ if (!pkAesMode && id == NFileHeader::NCompressionMethod::kWzAES)
{
CWzAesExtra aesField;
if (item.CentralExtra.GetWzAes(aesField))
@@ -613,6 +645,7 @@ HRESULT CZipDecoder::Decode(
}
CMyComPtr<ICompressFilter> cryptoFilter;
+
if (item.IsEncrypted())
{
if (wzAesMode)
@@ -620,15 +653,18 @@ HRESULT CZipDecoder::Decode(
CWzAesExtra aesField;
if (!item.CentralExtra.GetWzAes(aesField))
return S_OK;
- methodId = aesField.Method;
+ id = aesField.Method;
if (!_wzAesDecoder)
{
_wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder;
_wzAesDecoder = _wzAesDecoderSpec;
}
cryptoFilter = _wzAesDecoder;
- Byte properties = aesField.Strength;
- RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1));
+ if (!_wzAesDecoderSpec->SetKeyMode(aesField.Strength))
+ {
+ res = NExtract::NOperationResult::kUnsupportedMethod;
+ return S_OK;
+ }
}
else if (pkAesMode)
{
@@ -648,6 +684,7 @@ HRESULT CZipDecoder::Decode(
}
cryptoFilter = _zipCryptoDecoder;
}
+
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
@@ -699,39 +736,41 @@ HRESULT CZipDecoder::Decode(
unsigned m;
for (m = 0; m < methodItems.Size(); m++)
- if (methodItems[m].ZipMethod == methodId)
+ if (methodItems[m].ZipMethod == id)
break;
if (m == methodItems.Size())
{
CMethodItem mi;
- mi.ZipMethod = methodId;
- if (methodId == NFileHeader::NCompressionMethod::kStored)
+ mi.ZipMethod = id;
+ if (id == NFileHeader::NCompressionMethod::kStored)
mi.Coder = new NCompress::CCopyCoder;
- else if (methodId == NFileHeader::NCompressionMethod::kShrunk)
+ else if (id == NFileHeader::NCompressionMethod::kShrunk)
mi.Coder = new NCompress::NShrink::CDecoder;
- else if (methodId == NFileHeader::NCompressionMethod::kImploded)
+ else if (id == NFileHeader::NCompressionMethod::kImploded)
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
- else if (methodId == NFileHeader::NCompressionMethod::kLZMA)
+ else if (id == NFileHeader::NCompressionMethod::kLZMA)
mi.Coder = new CLzmaDecoder;
- else if (methodId == NFileHeader::NCompressionMethod::kPPMd)
+ else if (id == NFileHeader::NCompressionMethod::kXz)
+ mi.Coder = new CXzDecoder;
+ else if (id == NFileHeader::NCompressionMethod::kPPMd)
mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
else
{
CMethodId szMethodID;
- if (methodId == NFileHeader::NCompressionMethod::kBZip2)
+ if (id == NFileHeader::NCompressionMethod::kBZip2)
szMethodID = kMethodId_BZip2;
else
{
- if (methodId > 0xFF)
+ if (id > 0xFF)
{
res = NExtract::NOperationResult::kUnsupportedMethod;
return S_OK;
}
- szMethodID = kMethodId_ZipBase + (Byte)methodId;
+ szMethodID = kMethodId_ZipBase + (Byte)id;
}
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false));
+ RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder));
if (mi.Coder == 0)
{
@@ -741,6 +780,7 @@ HRESULT CZipDecoder::Decode(
}
m = methodItems.Add(mi);
}
+
ICompressCoder *coder = methodItems[m].Coder;
{
@@ -771,13 +811,23 @@ HRESULT CZipDecoder::Decode(
{
if (!filterStream)
{
- filterStreamSpec = new CFilterCoder;
+ filterStreamSpec = new CFilterCoder(false);
filterStream = filterStreamSpec;
}
+
filterStreamSpec->Filter = cryptoFilter;
+
if (wzAesMode)
{
result = _wzAesDecoderSpec->ReadHeader(inStream);
+ if (result == S_OK)
+ {
+ if (!_wzAesDecoderSpec->Init_and_CheckPassword())
+ {
+ res = NExtract::NOperationResult::kWrongPassword;
+ return S_OK;
+ }
+ }
}
else if (pkAesMode)
{
@@ -785,43 +835,64 @@ HRESULT CZipDecoder::Decode(
if (result == S_OK)
{
bool passwOK;
- result = _pkAesDecoderSpec->CheckPassword(passwOK);
+ result = _pkAesDecoderSpec->Init_and_CheckPassword(passwOK);
if (result == S_OK && !passwOK)
- result = S_FALSE;
+ {
+ res = NExtract::NOperationResult::kWrongPassword;
+ return S_OK;
+ }
}
}
else
{
result = _zipCryptoDecoderSpec->ReadHeader(inStream);
+ if (result == S_OK)
+ {
+ _zipCryptoDecoderSpec->Init_BeforeDecode();
+
+ /* Info-ZIP modification to ZipCrypto format:
+ if bit 3 of the general purpose bit flag is set,
+ it uses high byte of 16-bit File Time.
+ Info-ZIP code probably writes 2 bytes of File Time.
+ We check only 1 byte. */
+
+ // UInt32 v1 = GetUi16(_zipCryptoDecoderSpec->_header + NCrypto::NZip::kHeaderSize - 2);
+ // UInt32 v2 = (item.HasDescriptor() ? (item.Time & 0xFFFF) : (item.Crc >> 16));
+
+ Byte v1 = _zipCryptoDecoderSpec->_header[NCrypto::NZip::kHeaderSize - 1];
+ Byte v2 = (Byte)(item.HasDescriptor() ? (item.Time >> 8) : (item.Crc >> 24));
+
+ if (v1 != v2)
+ {
+ res = NExtract::NOperationResult::kWrongPassword;
+ return S_OK;
+ }
+ }
}
if (result == S_OK)
{
- if (pkAesMode)
- {
- /* 9.31: The BUG in 9.24-9.30 was fixed. pkAes archives didn't work.
- We don't need to call CAesCbcCoder::Init() to reset IV for data. */
- filterStreamSpec->SetInStream_NoSubFilterInit(inStream);
- }
- else
- {
- RINOK(filterStreamSpec->SetInStream(inStream));
- }
inStreamReleaser.FilterCoder = filterStreamSpec;
+ RINOK(filterStreamSpec->SetInStream(inStream));
+
+ /* IFilter::Init() does nothing in all zip crypto filters.
+ So we can call any Initialize function in CFilterCoder. */
+
+ RINOK(filterStreamSpec->Init_NoSubFilterInit());
+ // RINOK(filterStreamSpec->SetOutStreamSize(NULL));
+
inStreamNew = filterStream;
- if (wzAesMode)
- {
- if (!_wzAesDecoderSpec->CheckPasswordVerifyCode())
- result = S_FALSE;
- }
}
}
else
inStreamNew = inStream;
+
if (result == S_OK)
result = coder->Code(inStreamNew, outStream, NULL, &item.Size, compressProgress);
+
if (result == S_FALSE)
return S_OK;
+
if (result == E_NOTIMPL)
{
res = NExtract::NOperationResult::kUnsupportedMethod;
@@ -830,6 +901,7 @@ HRESULT CZipDecoder::Decode(
RINOK(result);
}
+
bool crcOK = true;
bool authOk = true;
if (needCRC)
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h
index 7f1d2eba..c2a362a7 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.h
+++ b/CPP/7zip/Archive/Zip/ZipHandler.h
@@ -33,7 +33,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
DECL_ISetCompressCodecsInfo
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index ae58cbe2..f1c8b227 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -34,15 +34,16 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
return S_OK;
}
-static bool IsAsciiString(const UString &s)
+static bool IsSimpleAsciiString(const wchar_t *s)
{
- for (unsigned i = 0; i < s.Len(); i++)
+ for (;;)
{
- wchar_t c = s[i];
+ wchar_t c = *s++;
+ if (c == 0)
+ return true;
if (c < 0x20 || c > 0x7F)
return false;
}
- return true;
}
#define COM_TRY_BEGIN2 try {
@@ -180,11 +181,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (tryUtf8)
{
- unsigned i;
- for (i = 0; i < name.Len() && (unsigned)name[i] < 0x80; i++);
- ui.IsUtf8 = (i != name.Len());
- if (!ConvertUnicodeToUTF8(name, ui.Name))
- return E_INVALIDARG;
+ ui.IsUtf8 = !name.IsAscii();
+ ConvertUnicodeToUTF8(name, ui.Name);
}
if (ui.Name.Len() >= (1 << 16))
@@ -249,10 +247,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (!m_ForceAesMode)
options.IsAesMode = thereAreAesUpdates;
- if (!IsAsciiString((BSTR)password))
+ if (!IsSimpleAsciiString(password))
return E_INVALIDARG;
if (password)
- options.Password = UnicodeStringToMultiByte((BSTR)password, CP_OEMCP);
+ options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP);
if (options.IsAesMode)
{
if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax)
@@ -297,7 +295,7 @@ static const CMethodIndexToName k_SupportedMethods[] =
{ NFileHeader::NCompressionMethod::kPPMd, "ppmd" }
};
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitMethodProps();
#ifndef _7ZIP_ST
@@ -318,7 +316,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
UInt32 level = 9;
RINOK(ParsePropToUInt32(name.Ptr(1), prop, level));
_props.Level = level;
- _props.MethodInfo.AddLevelProp(level);
+ _props.MethodInfo.AddProp_Level(level);
}
else if (name == L"m")
{
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h
index 1391cdf4..c109992c 100644
--- a/CPP/7zip/Archive/Zip/ZipHeader.h
+++ b/CPP/7zip/Archive/Zip/ZipHeader.h
@@ -54,6 +54,8 @@ namespace NFileHeader
kLZMA = 14,
kTerse = 18,
kLz77 = 19,
+
+ kXz = 0x5F,
kJpeg = 0x60,
kWavPack = 0x61,
kPPMd = 0x62,
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 345fbf56..6f495305 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -348,7 +348,7 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim
return S_FALSE;
}
-HRESULT CInArchive::IncreaseRealPosition(UInt64 addValue)
+HRESULT CInArchive::IncreaseRealPosition(Int64 addValue)
{
return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
}
@@ -439,10 +439,9 @@ void CInArchive::ReadFileName(unsigned size, AString &s)
s.Empty();
return;
}
- char *p = s.GetBuffer(size);
+ char *p = s.GetBuf(size);
SafeReadBytes(p, size);
- p[size] = 0;
- s.ReleaseBuffer();
+ s.ReleaseBuf_CalcLen(size);
}
bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
@@ -556,7 +555,12 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
UInt32 diskStartNumber = 0;
if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize,
localHeaderOffset, diskStartNumber))
- return false;
+ {
+ /* Most of archives are OK for Extra. But there are some rare cases
+ that have error. And if error in first item, it can't open archive.
+ So we ignore that error */
+ // return false;
+ }
}
if (!CheckDosTime(item.Time))
{
@@ -650,6 +654,7 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
numBytesInBuffer += processedSize;
if (numBytesInBuffer < kDataDescriptorSize)
return S_FALSE;
+
UInt32 i;
for (i = 0; i <= numBytesInBuffer - kDataDescriptorSize; i++)
{
@@ -666,10 +671,11 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
item.Crc = Get32(buf + i + 4);
item.PackSize = descriptorPackSize;
item.Size = Get32(buf + i + 12);
- return IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - kDataDescriptorSize))));
+ return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize)));
}
}
}
+
packedSize += i;
unsigned j;
for (j = 0; i < numBytesInBuffer; i++, j++)
@@ -1262,7 +1268,10 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
(UInt32)ecd64.cdSize != (UInt32)cdSize ||
((UInt32)(ecd64.cdStartOffset) != (UInt32)cdRelatOffset &&
(!items.IsEmpty())))
- return S_FALSE;
+ {
+ // return S_FALSE;
+ HeadersError = true;
+ }
// printf("\nOpen OK");
return S_OK;
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
index f6b349b1..734d3bcb 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.h
+++ b/CPP/7zip/Archive/Zip/ZipIn.h
@@ -25,7 +25,7 @@ public:
UInt64 GetLocalFullSize() const
{ return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); }
UInt64 GetDataPosition() const
- { return LocalHeaderPos + LocalFullHeaderSize; };
+ { return LocalHeaderPos + LocalFullHeaderSize; }
};
struct CInArchiveInfo
@@ -107,7 +107,7 @@ class CInArchive
HRESULT Seek(UInt64 offset);
HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
- HRESULT IncreaseRealPosition(UInt64 addValue);
+ HRESULT IncreaseRealPosition(Int64 addValue);
HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
void SafeReadBytes(void *data, unsigned size);
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
index ae88944d..f2ccc814 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.cpp
+++ b/CPP/7zip/Archive/Zip/ZipItem.cpp
@@ -114,7 +114,7 @@ bool CItem::IsDir() const
case NHostOS::kMVS:
return false; // change it throw kUnknownAttributes;
case NHostOS::kUnix:
- return (highAttrib & NUnixAttrib::kIFDIR) != 0;
+ return ((highAttrib & NUnixAttrib::kIFMT) == NUnixAttrib::kIFDIR);
default:
return false;
}
@@ -130,6 +130,11 @@ UInt32 CItem::GetWinAttrib() const
if (FromCentral)
winAttrib = ExternalAttrib;
break;
+ case NHostOS::kUnix:
+ // do we need to clear 16 low bits in this case?
+ if (FromCentral)
+ winAttrib = ExternalAttrib & 0xFFFF0000;
+ break;
}
if (IsDir()) // test it;
winAttrib |= FILE_ATTRIBUTE_DIRECTORY;
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
index d50c3ae9..98afdf1d 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.h
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -179,9 +179,12 @@ struct CExtraBlock
void RemoveUnknownSubBlocks()
{
- for (int i = SubBlocks.Size() - 1; i >= 0; i--)
+ for (unsigned i = SubBlocks.Size(); i != 0;)
+ {
+ i--;
if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES)
SubBlocks.Delete(i);
+ }
}
};
@@ -204,8 +207,8 @@ public:
bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
- bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; };
- bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); };
+ bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }
+ bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
@@ -237,6 +240,7 @@ public:
void ClearFlags() { Flags = 0; }
void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
+ void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }
UINT GetCodePage() const { return CP_OEMCP; }
};
@@ -277,6 +281,7 @@ public:
void GetUnicodeString(const AString &s, UString &res, bool useSpecifiedCodePage, UINT codePage) const
{
bool isUtf8 = IsUtf8();
+ bool ignore_Utf8_Errors = true;
#ifdef _WIN32
if (!isUtf8)
@@ -287,14 +292,15 @@ public:
{
/* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header.
We try to get name as UTF-8.
- Do we need to do it in POSIX version also? */
+ Do we need to do it in POSIX version also? */
isUtf8 = true;
+ ignore_Utf8_Errors = false;
}
}
#endif
if (isUtf8)
- if (ConvertUTF8ToUnicode(s, res))
+ if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors)
return;
MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage());
}
diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h
index eaaa0320..056d0d09 100644
--- a/CPP/7zip/Archive/Zip/ZipOut.h
+++ b/CPP/7zip/Archive/Zip/ZipOut.h
@@ -63,7 +63,7 @@ public:
HRESULT Create(IOutStream *outStream);
void MoveCurPos(UInt64 distanceToMove);
- UInt64 GetCurPos() const { return m_CurPos; };
+ UInt64 GetCurPos() const { return m_CurPos; }
void SeekToCurPos();
diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp
index 545e76c6..2be783e6 100644
--- a/CPP/7zip/Archive/Zip/ZipRegister.cpp
+++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp
@@ -9,23 +9,18 @@
namespace NArchive {
namespace NZip {
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1,
- 3 + 4 + 4 + 6,
- {
+static const Byte k_Signature[] = {
4, 0x50, 0x4B, 0x03, 0x04,
4, 0x50, 0x4B, 0x05, 0x06,
- 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B,
- },
+ 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B };
+
+REGISTER_ARC_IO(
+ "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1,
+ k_Signature,
0,
NArcInfoFlags::kFindSignature |
NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kUseGlobalOffset,
- REF_CreateArc_Pair, IsArc_Zip };
-
-REGISTER_ARC(Zip)
-
+ IsArc_Zip)
+
}}
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index 97cce5ac..9a9526cc 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -65,6 +65,7 @@ static void SetFileHeader(
COutArchive &archive,
const CCompressionMethodMode &options,
const CUpdateItem &ui,
+ // bool isSeqMode,
CItemOut &item)
{
item.Size = ui.Size;
@@ -95,6 +96,8 @@ static void SetFileHeader(
item.InternalAttrib = 0; // test it
item.SetEncrypted(!isDir && options.PasswordIsDefined);
+ // item.SetDescriptorMode(isSeqMode);
+
if (isDir)
{
item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
@@ -156,12 +159,14 @@ struct CThreadInfo
bool IsFree;
UInt32 UpdateIndex;
+ UInt32 FileTime;
CThreadInfo(const CCompressionMethodMode &options):
ExitThread(false),
ProgressSpec(0),
OutStreamSpec(0),
- Coder(options)
+ Coder(options),
+ FileTime(0)
{}
HRESULT CreateEvents()
@@ -192,9 +197,11 @@ void CThreadInfo::WaitAndCode()
CompressEvent.Lock();
if (ExitThread)
return;
+
Result = Coder.Compress(
EXTERNAL_CODECS_LOC_VARS
- InStream, OutStream, Progress, CompressingResult);
+ InStream, OutStream, FileTime, Progress, CompressingResult);
+
if (Result == S_OK && Progress)
Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);
CompressionCompletedEvent.Set();
@@ -254,7 +261,7 @@ public:
MY_UNKNOWN_IMP
void Create(IProgress *progress, bool inSizeIsMain);
void SetProgressOffset(UInt64 progressOffset);
- HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize);
+ HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
@@ -274,16 +281,16 @@ void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)
CriticalSection.Leave();
}
-HRESULT CMtProgressMixer2::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize)
+HRESULT CMtProgressMixer2::SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize)
{
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
if (index == 0 && RatioProgress)
{
RINOK(RatioProgress->SetRatioInfo(inSize, outSize));
}
- if (inSize != 0)
+ if (inSize)
InSizes[index] = *inSize;
- if (outSize != 0)
+ if (outSize)
OutSizes[index] = *outSize;
UInt64 v = ProgressOffset + (_inSizeIsMain ?
(InSizes[0] + InSizes[1]) :
@@ -332,8 +339,16 @@ static HRESULT UpdateItemOldData(
CItemOut &item,
/* bool izZip64, */
ICompressProgressInfo *progress,
+ IArchiveUpdateCallbackFile *opCallback,
UInt64 &complexity)
{
+ if (opCallback)
+ {
+ RINOK(opCallback->ReportOperation(
+ NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc,
+ NUpdateNotifyOp::kReplicate))
+ }
+
if (ui.NewProps)
{
if (item.HasDescriptor())
@@ -396,7 +411,8 @@ static HRESULT Update2St(
const CObjectVector<CUpdateItem> &updateItems,
const CCompressionMethodMode *options,
const CByteBuffer *comment,
- IArchiveUpdateCallback *updateCallback)
+ IArchiveUpdateCallback *updateCallback,
+ IArchiveUpdateCallbackFile *opCallback)
{
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
@@ -445,15 +461,37 @@ static HRESULT Update2St(
if (!fileInStream)
return E_INVALIDARG;
+ // bool isSeqMode = false;
+ /*
+ {
+ CMyComPtr<IInStream> inStream2;
+ fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2);
+ isSeqMode = (inStream2 == NULL);
+ }
+ */
+
// file Size can be 64-bit !!!
SetFileHeader(archive, *options, ui, item);
archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode());
CCompressingResult compressingResult;
CMyComPtr<IOutStream> outStream;
archive.CreateStreamForCompressing(&outStream);
+
RINOK(compressor.Compress(
EXTERNAL_CODECS_LOC_VARS
- fileInStream, outStream, progress, compressingResult));
+ fileInStream, outStream,
+ ui.Time,
+ progress, compressingResult));
+
+ if (compressingResult.FileTimeWasUsed)
+ {
+ /*
+ if (!item.HasDescriptor())
+ return E_FAIL;
+ */
+ item.SetDescriptorMode(true);
+ }
+
SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);
archive.WriteLocalHeader_And_SeekToNextFile(item);
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
@@ -465,13 +503,14 @@ static HRESULT Update2St(
{
UInt64 complexity = 0;
lps->SendRatio = false;
- RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity));
+ RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity));
lps->SendRatio = true;
lps->ProgressOffset += complexity;
}
items.Add(item);
lps->ProgressOffset += kLocalHeaderSize;
}
+
lps->InSize = unpackSizeTotal;
lps->OutSize = packSizeTotal;
RINOK(lps->SetCur());
@@ -489,6 +528,9 @@ static HRESULT Update2(
const CByteBuffer *comment,
IArchiveUpdateCallback *updateCallback)
{
+ CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+
UInt64 complexity = 0;
UInt64 numFilesToCompress = 0;
UInt64 numBytesToCompress = 0;
@@ -542,6 +584,7 @@ static HRESULT Update2(
numThreads = MAXIMUM_WAIT_OBJECTS;
if (numThreads < 1)
numThreads = 1;
+
const size_t kMemPerThread = (1 << 25);
const size_t kBlockSize = 1 << 16;
@@ -558,7 +601,7 @@ static HRESULT Update2(
{
// fixed for 9.31. bzip2 default is just one thread.
if (options2.NumThreadsWasChanged || method == NFileHeader::NCompressionMethod::kBZip2)
- options2.MethodInfo.AddNumThreadsProp(numThreads);
+ options2.MethodInfo.AddProp_NumThreads(numThreads);
}
}
else
@@ -577,7 +620,7 @@ static HRESULT Update2(
numBZip2Threads = 32;
if (averageNumberOfBlocks < numBZip2Threads)
numBZip2Threads = (UInt32)averageNumberOfBlocks;
- options2.MethodInfo.AddNumThreadsProp(numBZip2Threads);
+ options2.MethodInfo.AddProp_NumThreads(numBZip2Threads);
}
numThreads /= numBZip2Threads;
}
@@ -599,7 +642,7 @@ static HRESULT Update2(
return Update2St(
EXTERNAL_CODECS_LOC_VARS
archive, inArchive,
- inputItems, updateItems, &options2, comment, updateCallback);
+ inputItems, updateItems, &options2, comment, updateCallback, opCallback);
#ifndef _7ZIP_ST
@@ -643,6 +686,7 @@ static HRESULT Update2(
threadInfo.ProgressSpec = new CMtCompressProgress();
threadInfo.Progress = threadInfo.ProgressSpec;
threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i);
+ threadInfo.FileTime = 0; // fix it !
RINOK(threadInfo.CreateThread());
}
}
@@ -784,7 +828,15 @@ static HRESULT Update2(
DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(),
&compressingCompletedEvents.Front(), FALSE, INFINITE);
- int t = (int)(result - WAIT_OBJECT_0);
+ if (result == WAIT_FAILED)
+ {
+ DWORD lastError = GetLastError();
+ return lastError != 0 ? lastError : E_FAIL;
+ }
+ unsigned t = (unsigned)(result - WAIT_OBJECT_0);
+ if (t >= compressingCompletedEvents.Size())
+ return E_FAIL;
+
CThreadInfo &threadInfo = threads.Threads[threadIndices[t]];
threadInfo.InStream.Release();
threadInfo.IsFree = true;
@@ -813,7 +865,7 @@ static HRESULT Update2(
}
else
{
- RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity));
+ RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity));
}
items.Add(item);
complexity += kLocalHeaderSize;
diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp
index 40f87879..cd7341c1 100644
--- a/CPP/7zip/Bundles/Alone/Alone.dsp
+++ b/CPP/7zip/Bundles/Alone/Alone.dsp
@@ -350,6 +350,10 @@ SOURCE=..\..\..\Common\NewHandler.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\Sha1Reg.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\Sha256Reg.cpp
# End Source File
# Begin Source File
@@ -1214,14 +1218,6 @@ SOURCE=..\..\Compress\BitmEncoder.h
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\BranchCoder.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\BranchCoder.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Compress\BranchMisc.cpp
# End Source File
# Begin Source File
@@ -1517,14 +1513,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Archive\Common\CoderMixer2MT.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Archive\Common\DummyOutStream.cpp
# End Source File
# Begin Source File
@@ -1650,6 +1638,10 @@ SOURCE=..\..\Archive\GzHandler.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Archive\IArchive.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\LzmaHandler.cpp
# End Source File
# Begin Source File
@@ -1944,32 +1936,6 @@ SOURCE=..\..\Crypto\RandGen.h
# End Source File
# Begin Source File
-SOURCE=..\..\Crypto\Sha1.cpp
-
-!IF "$(CFG)" == "Alone - Win32 Release"
-
-# ADD CPP /O2
-# SUBTRACT CPP /YX /Yc /Yu
-
-!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
-
-!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
-
-!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Crypto\Sha1.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Crypto\Sha1Reg.cpp
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Crypto\WzAes.cpp
# End Source File
# Begin Source File
@@ -2385,6 +2351,30 @@ SOURCE=..\..\..\..\C\Bcj2.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Bcj2Enc.c
+
+!IF "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Bra.c
!IF "$(CFG)" == "Alone - Win32 Release"
@@ -2918,6 +2908,34 @@ SOURCE=..\..\..\..\C\RotateDefs.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Sha1.c
+
+!IF "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sha1.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Sha256.c
!IF "$(CFG)" == "Alone - Win32 Release"
diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile
index 15139714..02a51398 100644
--- a/CPP/7zip/Bundles/Alone/makefile
+++ b/CPP/7zip/Bundles/Alone/makefile
@@ -23,6 +23,7 @@ COMMON_OBJS = \
$O\MyVector.obj \
$O\Wildcard.obj \
$O\XzCrc64Reg.obj \
+ $O\Sha1Reg.obj \
$O\Sha256Reg.obj \
WIN_OBJS = \
@@ -50,7 +51,6 @@ WIN_OBJS = \
$O\InBuffer.obj \
$O\InOutTempBuffer.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\MemBlocks.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
@@ -77,7 +77,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\DummyOutStream.obj \
$O\FindSignature.obj \
@@ -139,7 +138,6 @@ COMPRESS_OBJS = \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
$O\BitlDecoder.obj \
- $O\BranchCoder.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
@@ -181,8 +179,6 @@ CRYPTO_OBJS = \
$O\MyAesReg.obj \
$O\Pbkdf2HmacSha1.obj \
$O\RandGen.obj \
- $O\Sha1.obj \
- $O\Sha1Reg.obj \
$O\WzAes.obj \
$O\ZipCrypto.obj \
$O\ZipStrong.obj \
@@ -190,6 +186,8 @@ CRYPTO_OBJS = \
C_OBJS = \
$O\7zStream.obj \
$O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bcj2Enc.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
@@ -210,6 +208,7 @@ C_OBJS = \
$O\Ppmd8.obj \
$O\Ppmd8Dec.obj \
$O\Ppmd8Enc.obj \
+ $O\Sha1.obj \
$O\Sha256.obj \
$O\Sort.obj \
$O\Threads.obj \
diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp
index 2800ff88..089e4020 100644
--- a/CPP/7zip/Bundles/Alone7z/Alone.dsp
+++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp
@@ -44,7 +44,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /FAc /Yu"StdAfx.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
@@ -69,7 +69,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
@@ -94,7 +94,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c
-# ADD CPP /nologo /Gz /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
@@ -121,7 +121,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
-# ADD CPP /nologo /Gz /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
@@ -738,14 +738,6 @@ SOURCE=..\..\Compress\BcjRegister.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\BranchCoder.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\BranchCoder.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Compress\BranchMisc.cpp
# End Source File
# Begin Source File
@@ -961,14 +953,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Archive\Common\CoderMixer2MT.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Archive\Common\DummyOutStream.cpp
# End Source File
# Begin Source File
@@ -1026,6 +1010,10 @@ SOURCE=..\..\Archive\Common\ParseProperties.h
# End Group
# Begin Source File
+SOURCE=..\..\Archive\IArchive.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\LzmaHandler.cpp
# End Source File
# Begin Source File
@@ -1526,6 +1514,58 @@ SOURCE=..\..\..\..\C\Alloc.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Bcj2.c
+
+!IF "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bcj2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bcj2Enc.c
+
+!IF "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Bra.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile
index 84b235eb..7589bc30 100644
--- a/CPP/7zip/Bundles/Alone7z/makefile
+++ b/CPP/7zip/Bundles/Alone7z/makefile
@@ -48,7 +48,6 @@ WIN_OBJS = \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OffsetStream.obj \
@@ -68,7 +67,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\DummyOutStream.obj \
$O\HandlerOut.obj \
@@ -101,7 +99,6 @@ COMPRESS_OBJS = \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
- $O\BranchCoder.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
@@ -125,6 +122,8 @@ CRYPTO_OBJS = \
C_OBJS = \
$O\7zStream.obj \
$O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bcj2Enc.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp
index 1f214b33..dfb0bb47 100644
--- a/CPP/7zip/Bundles/Fm/FM.dsp
+++ b/CPP/7zip/Bundles/Fm/FM.dsp
@@ -45,7 +45,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS_2" /D "SUPPORT_DEVICE_FILE" /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"
@@ -72,7 +72,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS_2" /D "SUPPORT_DEVICE_FILE" /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"
@@ -99,7 +99,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c
-# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS_2" /D "SUPPORT_DEVICE_FILE" /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"
@@ -127,7 +127,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
-# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS_2" /D "SUPPORT_DEVICE_FILE" /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"
@@ -211,9 +211,188 @@ SOURCE=..\..\UI\FileManager\Test.bmp
# Begin Group "Archive"
# PROP Default_Filter ""
+# Begin Group "7z"
+
+# PROP Default_Filter ""
# Begin Source File
-SOURCE=..\..\Archive\IArchive.h
+SOURCE=..\..\Archive\7z\7zCompressionMode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zCompressionMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zDecode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zEncode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zEncode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zExtract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zFolderInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zFolderInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zFolderOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHandlerOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zOut.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zSpecStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zSpecStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zUpdate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zUpdate.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CoderMixer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CoderMixer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CoderMixer2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CoderMixer2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\DummyOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\DummyOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\FindSignature.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\FindSignature.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\HandlerOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\HandlerOut.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\InStreamWithCRC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\MultiStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\MultiStream.h
# End Source File
# Begin Source File
@@ -223,12 +402,33 @@ SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ParseProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ParseProperties.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\Archive\IArchive.h
+# End Source File
# End Group
# Begin Group "Folders"
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\UI\FileManager\AltStreamsFolder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\AltStreamsFolder.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\UI\FileManager\FSDrives.cpp
# End Source File
# Begin Source File
@@ -605,6 +805,22 @@ SOURCE=..\..\UI\FileManager\UpdateCallback100.h
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\Common\CreateCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\CreateCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\CWrappers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\CWrappers.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Common\FilePathAutoRename.cpp
# End Source File
# Begin Source File
@@ -621,6 +837,14 @@ SOURCE=..\..\Common\FileStreams.h
# End Source File
# Begin Source File
+SOURCE=..\..\Common\InOutTempBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InOutTempBuffer.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Common\MethodProps.cpp
# End Source File
# Begin Source File
@@ -629,6 +853,14 @@ SOURCE=..\..\Common\MethodProps.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
@@ -641,6 +873,14 @@ SOURCE=..\..\Common\PropId.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Common\StreamBinder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamBinder.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Common\StreamObjects.cpp
# End Source File
# Begin Source File
@@ -663,6 +903,14 @@ SOURCE=..\..\Common\UniqBlocks.cpp
SOURCE=..\..\Common\UniqBlocks.h
# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.h
+# End Source File
# End Group
# Begin Group "C"
@@ -745,6 +993,42 @@ SOURCE=..\..\..\..\C\CpuArch.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\LzFind.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzFindMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzFindMt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzmaDec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzmaDec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzmaEnc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzmaEnc.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Sha256.c
!IF "$(CFG)" == "FM - Win32 Release"
@@ -1302,14 +1586,6 @@ SOURCE=..\..\UI\Common\CompressCall2.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Common\CreateCoder.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Common\CreateCoder.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\UI\Common\DefaultName.cpp
# End Source File
# Begin Source File
@@ -1618,6 +1894,14 @@ SOURCE=..\..\UI\GUI\UpdateCallbackGUI.h
# End Source File
# Begin Source File
+SOURCE=..\..\UI\GUI\UpdateCallbackGUI2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\GUI\UpdateCallbackGUI2.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\UI\GUI\UpdateGUI.cpp
# End Source File
# Begin Source File
@@ -1637,37 +1921,49 @@ SOURCE=..\..\Compress\CopyCoder.cpp
SOURCE=..\..\Compress\CopyCoder.h
# End Source File
-# End Group
-# Begin Group "Interface"
+# Begin Source File
-# PROP Default_Filter ""
+SOURCE=..\..\Compress\CopyRegister.cpp
+# End Source File
# Begin Source File
-SOURCE=..\..\ICoder.h
+SOURCE=..\..\Compress\LzmaDecoder.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\IDecl.h
+SOURCE=..\..\Compress\LzmaDecoder.h
# End Source File
# Begin Source File
-SOURCE=..\..\IPassword.h
+SOURCE=..\..\Compress\LzmaEncoder.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\IProgress.h
+SOURCE=..\..\Compress\LzmaEncoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaRegister.cpp
# End Source File
# End Group
-# Begin Group "Crypto"
+# Begin Group "Interface"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=..\..\Crypto\Sha1.cpp
+SOURCE=..\..\ICoder.h
# End Source File
# Begin Source File
-SOURCE=..\..\Crypto\Sha1.h
+SOURCE=..\..\IDecl.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IPassword.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IProgress.h
# End Source File
# End Group
# Begin Source File
diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile
index fd211a1d..8ae5f4f6 100644
--- a/CPP/7zip/Bundles/Fm/makefile
+++ b/CPP/7zip/Bundles/Fm/makefile
@@ -2,7 +2,6 @@ PROG = 7zFM.exe
CFLAGS = $(CFLAGS) \
-DLANG \
-DNEW_FOLDER_INTERFACE \
- -DEXTERNAL_CODECS \
!IFDEF UNDER_CE
LIBS = $(LIBS) ceshell.lib Commctrl.lib
@@ -86,6 +85,7 @@ GUI_OBJS = \
$O\ExtractGUI.obj \
$O\HashGUI.obj \
$O\UpdateCallbackGUI.obj \
+ $O\UpdateCallbackGUI2.obj \
$O\UpdateGUI.obj \
diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile
index 01e63e67..992fc714 100644
--- a/CPP/7zip/Bundles/Format7z/makefile
+++ b/CPP/7zip/Bundles/Format7z/makefile
@@ -32,7 +32,6 @@ WIN_OBJS = \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
@@ -50,7 +49,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
@@ -84,7 +82,6 @@ COMPRESS_OBJS = \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
$O\BitlDecoder.obj \
- $O\BranchCoder.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
@@ -116,6 +113,8 @@ CRYPTO_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bcj2Enc.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile
index 86a76e3d..93240c80 100644
--- a/CPP/7zip/Bundles/Format7zExtract/makefile
+++ b/CPP/7zip/Bundles/Format7zExtract/makefile
@@ -26,7 +26,6 @@ WIN_OBJS = \
$O\InBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
@@ -43,7 +42,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
@@ -68,7 +66,6 @@ COMPRESS_OBJS = \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
$O\BitlDecoder.obj \
- $O\BranchCoder.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
@@ -96,6 +93,7 @@ CRYPTO_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
diff --git a/CPP/7zip/Bundles/Format7zExtractR/makefile b/CPP/7zip/Bundles/Format7zExtractR/makefile
index 7241b37c..3d49c46f 100644
--- a/CPP/7zip/Bundles/Format7zExtractR/makefile
+++ b/CPP/7zip/Bundles/Format7zExtractR/makefile
@@ -26,7 +26,6 @@ WIN_OBJS = \
$O\InBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
@@ -43,7 +42,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\HandlerOut.obj \
$O\ItemNameUtils.obj \
@@ -69,7 +67,6 @@ COMPRESS_OBJS = \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
- $O\BranchCoder.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
@@ -83,6 +80,7 @@ COMPRESS_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\Bcj2.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak
index c26a6d67..c2f415cf 100644
--- a/CPP/7zip/Bundles/Format7zF/Arc.mak
+++ b/CPP/7zip/Bundles/Format7zF/Arc.mak
@@ -8,6 +8,7 @@ COMMON_OBJS = \
$O\MyVector.obj \
$O\MyXml.obj \
$O\NewHandler.obj \
+ $O\Sha1Reg.obj \
$O\Sha256Reg.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
@@ -86,7 +87,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\DummyOutStream.obj \
$O\FindSignature.obj \
@@ -172,14 +172,11 @@ ZIP_OBJS = \
$O\ZipRegister.obj \
COMPRESS_OBJS = \
- $O\ArjDecoder1.obj \
- $O\ArjDecoder2.obj \
$O\Bcj2Coder.obj \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
$O\BitlDecoder.obj \
- $O\BranchCoder.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
@@ -231,8 +228,6 @@ CRYPTO_OBJS = \
$O\RandGen.obj \
$O\Rar20Crypto.obj \
$O\RarAes.obj \
- $O\Sha1.obj \
- $O\Sha1Reg.obj \
$O\WzAes.obj \
$O\ZipCrypto.obj \
$O\ZipStrong.obj \
@@ -242,6 +237,8 @@ C_OBJS = \
$O\7zBuf2.obj \
$O\7zStream.obj \
$O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bcj2Enc.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
@@ -262,6 +259,7 @@ C_OBJS = \
$O\Ppmd8.obj \
$O\Ppmd8Dec.obj \
$O\Ppmd8Enc.obj \
+ $O\Sha1.obj \
$O\Sha256.obj \
$O\Sort.obj \
$O\Threads.obj \
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
index 40f45455..82df284c 100644
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.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 "MY7Z_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /Gr /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /FAs /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gr /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "_7ZIP_ST_9" /FAcs /Yu"StdAfx.h" /FD /GF /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 "MY7Z_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\SDK" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\SDK" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_EXPORTS" /D "NO_REGISTRY" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "_7ZIP_ST_9" /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"
@@ -80,7 +80,8 @@ BSC32=bscmake.exe
# 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\7z.dll" /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\7z.dll" /pdbtype:sept /ignore:4033
+# SUBTRACT LINK32 /pdb:none
!ENDIF
@@ -334,6 +335,10 @@ SOURCE=..\..\..\Common\NewHandler.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\Sha1Reg.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\Sha256Reg.cpp
# End Source File
# Begin Source File
@@ -376,58 +381,6 @@ SOURCE=..\..\..\Common\XzCrc64Reg.cpp
# Begin Group "Compress"
# PROP Default_Filter ""
-# Begin Group "PPMD"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\..\Compress\PpmdDecoder.cpp
-
-!IF "$(CFG)" == "7z - Win32 Release"
-
-# ADD CPP /O2
-# SUBTRACT CPP /YX /Yc /Yu
-
-!ELSEIF "$(CFG)" == "7z - Win32 Debug"
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\PpmdDecoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\PpmdEncoder.cpp
-
-!IF "$(CFG)" == "7z - Win32 Release"
-
-# ADD CPP /O2
-# SUBTRACT CPP /YX /Yc /Yu
-
-!ELSEIF "$(CFG)" == "7z - Win32 Debug"
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\PpmdEncoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\PpmdRegister.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\PpmdSubAlloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\PpmdType.h
-# End Source File
-# End Group
# Begin Group "Bit Coder"
# PROP Default_Filter ""
@@ -628,6 +581,16 @@ SOURCE=..\..\Compress\ZlibEncoder.h
# Begin Source File
SOURCE=..\..\Compress\Bcj2Coder.cpp
+
+!IF "$(CFG)" == "7z - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+!ENDIF
+
# End Source File
# Begin Source File
@@ -651,14 +614,6 @@ SOURCE=..\..\Compress\BcjRegister.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\BranchCoder.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Compress\BranchCoder.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Compress\BranchMisc.cpp
# End Source File
# Begin Source File
@@ -687,6 +642,10 @@ SOURCE=..\..\Compress\CopyRegister.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Compress\DeltaFilter.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Compress\Lzma2Decoder.cpp
# End Source File
# Begin Source File
@@ -727,65 +686,77 @@ SOURCE=..\..\Compress\LzmaRegister.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\RangeCoder.h
-# End Source File
-# Begin Source File
+SOURCE=..\..\Compress\PpmdDecoder.cpp
-SOURCE=..\..\Compress\RangeCoderBit.h
-# End Source File
-# End Group
-# Begin Group "Cab Compress"
+!IF "$(CFG)" == "7z - Win32 Release"
-# PROP Default_Filter ""
-# Begin Source File
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+!ENDIF
-SOURCE=..\..\Compress\Lzx.h
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\Lzx86Converter.cpp
+SOURCE=..\..\Compress\PpmdDecoder.h
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\Lzx86Converter.h
+SOURCE=..\..\Compress\PpmdEncoder.cpp
+
+!IF "$(CFG)" == "7z - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+!ENDIF
+
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\LzxDecoder.cpp
+SOURCE=..\..\Compress\PpmdEncoder.h
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\LzxDecoder.h
+SOURCE=..\..\Compress\PpmdRegister.cpp
# End Source File
+# End Group
+# Begin Group "Cab Compress"
+
+# PROP Default_Filter ""
# Begin Source File
-SOURCE=..\..\Compress\QuantumDecoder.cpp
+SOURCE=..\..\Compress\Lzx.h
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\QuantumDecoder.h
+SOURCE=..\..\Compress\Lzx86Converter.cpp
# End Source File
-# End Group
# Begin Source File
-SOURCE=..\..\Compress\ArjDecoder1.cpp
+SOURCE=..\..\Compress\Lzx86Converter.h
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\ArjDecoder1.h
+SOURCE=..\..\Compress\LzxDecoder.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\ArjDecoder2.cpp
+SOURCE=..\..\Compress\LzxDecoder.h
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\ArjDecoder2.h
+SOURCE=..\..\Compress\QuantumDecoder.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\DeltaFilter.cpp
+SOURCE=..\..\Compress\QuantumDecoder.h
# End Source File
+# End Group
# Begin Source File
SOURCE=..\..\Compress\HuffmanDecoder.h
@@ -924,25 +895,7 @@ SOURCE=..\..\Crypto\RarAes.h
# End Source File
# Begin Source File
-SOURCE=..\..\Crypto\Sha1.cpp
-
-!IF "$(CFG)" == "7z - Win32 Release"
-
-# ADD CPP /O2
-# SUBTRACT CPP /YX /Yc /Yu
-
-!ELSEIF "$(CFG)" == "7z - Win32 Debug"
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Crypto\Sha1.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Crypto\Sha1Reg.cpp
+SOURCE=..\..\Crypto\Sha1Cls.h
# End Source File
# Begin Source File
@@ -1042,14 +995,6 @@ SOURCE=..\..\Common\LimitedStreams.h
# End Source File
# Begin Source File
-SOURCE=..\..\Common\LockedStream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Common\LockedStream.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Common\MemBlocks.cpp
# End Source File
# Begin Source File
@@ -1338,6 +1283,42 @@ SOURCE=..\..\..\..\C\Alloc.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Bcj2.c
+
+!IF "$(CFG)" == "7z - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bcj2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bcj2Enc.c
+
+!IF "$(CFG)" == "7z - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Bra.c
!IF "$(CFG)" == "7z - Win32 Release"
@@ -1701,6 +1682,26 @@ SOURCE=..\..\..\..\C\RotateDefs.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Sha1.c
+
+!IF "$(CFG)" == "7z - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sha1.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Sha256.c
!IF "$(CFG)" == "7z - Win32 Release"
@@ -1797,14 +1798,6 @@ SOURCE=..\..\Archive\7z\7zFolderInStream.h
# End Source File
# Begin Source File
-SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Archive\7z\7zFolderOutStream.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Archive\7z\7zHandler.cpp
# End Source File
# Begin Source File
@@ -1973,14 +1966,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Archive\Common\CoderMixer2MT.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Archive\Common\DummyOutStream.cpp
# End Source File
# Begin Source File
@@ -2440,6 +2425,10 @@ SOURCE=..\..\Archive\XzHandler.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Archive\XzHandler.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\ZHandler.cpp
# End Source File
# End Group
diff --git a/CPP/7zip/Bundles/Format7zR/makefile b/CPP/7zip/Bundles/Format7zR/makefile
index 555654bc..8d41ce89 100644
--- a/CPP/7zip/Bundles/Format7zR/makefile
+++ b/CPP/7zip/Bundles/Format7zR/makefile
@@ -30,7 +30,6 @@ WIN_OBJS = \
$O\InOutTempBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\MethodId.obj \
$O\MethodProps.obj \
$O\OutBuffer.obj \
@@ -48,7 +47,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
@@ -81,7 +79,6 @@ COMPRESS_OBJS = \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
- $O\BranchCoder.obj \
$O\BranchMisc.obj \
$O\BranchRegister.obj \
$O\ByteSwap.obj \
@@ -97,6 +94,8 @@ COMPRESS_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bcj2Enc.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index d321e454..5b64b524 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -25,6 +25,7 @@
#include "../../../Windows/System.h"
#endif
+#include "../../../Common/IntToString.h"
#include "../../../Common/CommandLineParser.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
@@ -36,14 +37,41 @@
#include "../../Compress/LzmaEncoder.h"
#include "../../UI/Console/BenchCon.h"
-
+#include "../../UI/Console/ConsoleClose.h"
using namespace NCommandLineParser;
+static const unsigned kDictSizeLog = 24;
+
+static const char *kCopyrightString = "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n\n";
+
+static const char *kHelpString =
+ "Usage: LZMA <command> [inputFile] [outputFile] [<switches>...]\n"
+ "\n"
+ "<command>\n"
+ " e : Encode file\n"
+ " d : Decode file\n"
+ " b : Benchmark\n"
+ "<switches>\n"
+ " -a{N} : set compression mode : [0, 1] : default = 1 (max)\n"
+ " -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n"
+ " -fb{N} : set number of fast bytes : [5, 273] : default = 128\n"
+ " -mc{N} : set number of cycles for match finder\n"
+ " -lc{N} : set number of literal context bits : [0, 8] : default = 3\n"
+ " -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n"
+ " -pb{N} : set number of pos bits : [0, 4] : default = 2\n"
+ " -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n"
+ " -mt{N} : set number of CPU threads\n"
+ " -eos : write end of stream marker\n"
+ " -si : read data from stdin\n"
+ " -so : write data to stdout\n";
+
+
static const char *kCantAllocate = "Can not allocate memory";
static const char *kReadError = "Read error";
static const char *kWriteError = "Write error";
+
namespace NKey {
enum Enum
{
@@ -88,75 +116,195 @@ static const CSwitchForm kSwitchForms[] =
{ "F86", NSwitchType::kChar, false, 0, "+" }
};
-static void PrintMessage(const char *s)
+
+static void PrintErr(const char *s)
{
fputs(s, stderr);
}
+static void PrintErr_LF(const char *s)
+{
+ PrintErr(s);
+ fputc('\n', stderr);
+}
+
+
+static void PrintError(const char *s)
+{
+ PrintErr("\nERROR: ");
+ PrintErr_LF(s);
+}
+
+static void PrintError2(const char *s1, const wchar_t *s2)
+{
+ PrintError(s1);
+ PrintErr_LF(GetOemString(s2));
+}
+
+static void PrintError_int(const char *s, int code)
+{
+ PrintError(s);
+ char temp[32];
+ ConvertInt64ToString(code, temp);
+ PrintErr("Error code = ");
+ PrintErr_LF(temp);
+}
+
+
+
+static void Print(const char *s)
+{
+ fputs(s, stdout);
+}
+
+static void Print_UInt64(UInt64 v)
+{
+ char temp[32];
+ ConvertUInt64ToString(v, temp);
+ Print(temp);
+}
+
+static void Print_MB(UInt64 v)
+{
+ Print_UInt64(v);
+ Print(" MiB");
+}
+
+static void Print_Size(const char *s, UInt64 v)
+{
+ Print(s);
+ Print_UInt64(v);
+ Print(" (");
+ Print_MB(v >> 20);
+ Print(")\n");
+}
+
+static void PrintTitle()
+{
+ Print(kCopyrightString);
+}
+
static void PrintHelp()
{
- PrintMessage("\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n"
- " e: encode file\n"
- " d: decode file\n"
- " b: Benchmark\n"
- "<Switches>\n"
- " -a{N}: set compression mode - [0, 1], default: 1 (max)\n"
- " -d{N}: set dictionary size - [12, 30], default: 23 (8MB)\n"
- " -fb{N}: set number of fast bytes - [5, 273], default: 128\n"
- " -mc{N}: set number of cycles for match finder\n"
- " -lc{N}: set number of literal context bits - [0, 8], default: 3\n"
- " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"
- " -pb{N}: set number of pos bits - [0, 4], default: 2\n"
- " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n"
- " -mt{N}: set number of CPU threads\n"
- " -eos: write End Of Stream marker\n"
- " -si: read data from stdin\n"
- " -so: write data to stdout\n"
- );
+ PrintTitle();
+ Print(kHelpString);
}
-static void PrintHelpAndExit(const char *s)
+class CProgressPrint:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+ UInt64 _size1;
+ UInt64 _size2;
+public:
+ CProgressPrint(): _size1(0), _size2(0) {}
+
+ void ClosePrint();
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+#define BACK_STR \
+"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
+static const char *kBackSpaces =
+BACK_STR
+" "
+BACK_STR;
+
+
+void CProgressPrint::ClosePrint()
{
- fprintf(stderr, "\nError: %s\n\n", s);
- PrintHelp();
- throw -1;
+ Print(kBackSpaces);
}
-static void IncorrectCommand()
+STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
- PrintHelpAndExit("Incorrect command");
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+ if (inSize)
+ {
+ UInt64 v1 = *inSize >> 20;
+ UInt64 v2 = _size2;
+ if (outSize)
+ v2 = *outSize >> 20;
+ if (v1 != _size1 || v2 != _size2)
+ {
+ _size1 = v1;
+ _size2 = v2;
+ ClosePrint();
+ Print_MB(_size1);
+ Print(" -> ");
+ Print_MB(_size2);
+ }
+ }
+ return S_OK;
}
-static void WriteArgumentsToStringList(int numArgs, const char *args[], UStringVector &strings)
+
+static void IncorrectCommand()
{
- for (int i = 1; i < numArgs; i++)
- strings.Add(MultiByteToUnicodeString(args[i]));
+ throw "Incorrect command";
}
-static bool GetNumber(const wchar_t *s, UInt32 &value)
+static UInt32 GetNumber(const wchar_t *s)
{
- value = 0;
- if (*s == 0)
- return false;
const wchar_t *end;
- value = ConvertStringToUInt32(s, &end);
- return *end == 0;
+ UInt32 v = ConvertStringToUInt32(s, &end);
+ if (*end != 0)
+ IncorrectCommand();
+ return v;
}
static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res)
{
if (parser[index].ThereIs)
- if (!GetNumber(parser[index].PostStrings[0], res))
- IncorrectCommand();
+ res = GetNumber(parser[index].PostStrings[0]);
}
-#define NT_CHECK_FAIL_ACTION PrintMessage("Unsupported Windows version"); return 1;
-int main2(int numArgs, const char *args[])
+static int Error_HRESULT(const char *s, HRESULT res)
{
- NT_CHECK
+ if (res == E_ABORT)
+ {
+ Print("\n\nBreak signaled\n");
+ return 255;
+ }
- PrintMessage("\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n");
+ PrintError(s);
+
+ if (res == E_OUTOFMEMORY)
+ {
+ PrintErr_LF(kCantAllocate);
+ return 8;
+ }
+ if (res == E_INVALIDARG)
+ {
+ PrintErr_LF("Ununsupported parameter");
+ }
+ else
+ {
+ char temp[32];
+ ConvertUInt32ToHex(res, temp);
+ PrintErr("Error code = 0x");
+ PrintErr_LF(temp);
+ }
+ return 1;
+}
+
+#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;
+
+static void AddProp(CObjectVector<CProperty> &props2, const char *name, const wchar_t *val)
+{
+ CProperty &prop = props2.AddNew();
+ prop.Name.SetFromAscii(name);
+ prop.Value = val;
+}
+
+static int main2(int numArgs, const char *args[])
+{
+ NT_CHECK
if (numArgs == 1)
{
@@ -164,20 +312,24 @@ int main2(int numArgs, const char *args[])
return 0;
}
- bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4);
+ /*
+ bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8);
if (unsupportedTypes)
- {
- PrintMessage("Unsupported base types. Edit Common/Types.h and recompile");
- return 1;
- }
+ throw "Unsupported base types. Edit Common/Types.h and recompile";
+ */
UStringVector commandStrings;
- WriteArgumentsToStringList(numArgs, args, commandStrings);
+ for (int i = 1; i < numArgs; i++)
+ commandStrings.Add(MultiByteToUnicodeString(args[i]));
CParser parser(ARRAY_SIZE(kSwitchForms));
try
{
- parser.ParseStrings(kSwitchForms, commandStrings);
+ if (!parser.ParseStrings(kSwitchForms, commandStrings))
+ {
+ PrintError2(parser.ErrorMessage, parser.ErrorLine);
+ return 1;
+ }
}
catch(...)
{
@@ -189,40 +341,41 @@ int main2(int numArgs, const char *args[])
PrintHelp();
return 0;
}
- const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
+
+ bool stdInMode = parser[NKey::kStdIn].ThereIs;
+ bool stdOutMode = parser[NKey::kStdOut].ThereIs;
+
+ if (!stdOutMode)
+ PrintTitle();
+
+ const UStringVector &params = parser.NonSwitchStrings;
unsigned paramIndex = 0;
- if (paramIndex >= nonSwitchStrings.Size())
+ if (paramIndex >= params.Size())
IncorrectCommand();
- const UString &command = nonSwitchStrings[paramIndex++];
+ const UString &command = params[paramIndex++];
- CObjectVector<CProperty> props;
+ CObjectVector<CProperty> props2;
bool dictDefined = false;
UInt32 dict = (UInt32)(Int32)-1;
+
if (parser[NKey::kDict].ThereIs)
{
- UInt32 dicLog;
+ UInt32 dictLog;
const UString &s = parser[NKey::kDict].PostStrings[0];
- if (!GetNumber(s, dicLog))
- IncorrectCommand();
- dict = 1 << dicLog;
+ dictLog = GetNumber(s);
+ dict = 1 << dictLog;
dictDefined = true;
- CProperty prop;
- prop.Name = L"d";
- prop.Value = s;
- props.Add(prop);
+ AddProp(props2, "d", s);
}
+
if (parser[NKey::kLevel].ThereIs)
{
- UInt32 level = 5;
const UString &s = parser[NKey::kLevel].PostStrings[0];
- if (!GetNumber(s, level))
- IncorrectCommand();
- CProperty prop;
- prop.Name = L"x";
- prop.Value = s;
- props.Add(prop);
+ /* UInt32 level = */ GetNumber(s);
+ AddProp(props2, "x", s);
}
+
UString mf = L"BT4";
if (parser[NKey::kMatchFinder].ThereIs)
mf = parser[NKey::kMatchFinder].PostStrings[0];
@@ -230,70 +383,64 @@ int main2(int numArgs, const char *args[])
UInt32 numThreads = (UInt32)(Int32)-1;
#ifndef _7ZIP_ST
+
if (parser[NKey::kMultiThread].ThereIs)
{
- UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
const UString &s = parser[NKey::kMultiThread].PostStrings[0];
if (s.IsEmpty())
- numThreads = numCPUs;
+ numThreads = NWindows::NSystem::GetNumberOfProcessors();
else
- if (!GetNumber(s, numThreads))
- IncorrectCommand();
- CProperty prop;
- prop.Name = L"mt";
- prop.Value = s;
- props.Add(prop);
+ numThreads = GetNumber(s);
+ AddProp(props2, "mt", s);
}
+
#endif
+
if (parser[NKey::kMethod].ThereIs)
{
- UString s = parser[NKey::kMethod].PostStrings[0];
+ const UString &s = parser[NKey::kMethod].PostStrings[0];
if (s.IsEmpty() || s[0] != '=')
IncorrectCommand();
- CProperty prop;
- prop.Name = L"m";
- prop.Value = s.Ptr(1);
- props.Add(prop);
+ AddProp(props2, "m", s.Ptr(1));
}
- if (MyStringCompareNoCase(command, L"b") == 0)
+ if (StringsAreEqualNoCase_Ascii(command, "b"))
{
- const UInt32 kNumDefaultItereations = 1;
- UInt32 numIterations = kNumDefaultItereations;
- {
- if (paramIndex < nonSwitchStrings.Size())
- if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
- numIterations = kNumDefaultItereations;
- }
- HRESULT res = BenchCon(props, numIterations, stderr);
- if (res != S_OK)
- {
- if (res != E_ABORT)
- {
- PrintMessage("Benchmark Error");
- return 1;
- }
- }
- return 0;
+ UInt32 numIterations = 1;
+ if (paramIndex < params.Size())
+ numIterations = GetNumber(params[paramIndex++]);
+ if (params.Size() != paramIndex)
+ IncorrectCommand();
+
+ HRESULT res = BenchCon(props2, numIterations, stdout);
+
+ if (res == S_OK)
+ return 0;
+ return Error_HRESULT("Benchmark error", res);
+ }
+
+ {
+ UInt32 needParams = 3;
+ if (stdInMode) needParams--;
+ if (stdOutMode) needParams--;
+ if (needParams != params.Size())
+ IncorrectCommand();
}
if (numThreads == (UInt32)(Int32)-1)
numThreads = 1;
bool encodeMode = false;
- if (MyStringCompareNoCase(command, L"e") == 0)
+
+ if (StringsAreEqualNoCase_Ascii(command, "e"))
encodeMode = true;
- else if (MyStringCompareNoCase(command, L"d") == 0)
- encodeMode = false;
- else
+ else if (!StringsAreEqualNoCase_Ascii(command, "d"))
IncorrectCommand();
- bool stdInMode = parser[NKey::kStdIn].ThereIs;
- bool stdOutMode = parser[NKey::kStdOut].ThereIs;
-
CMyComPtr<ISequentialInStream> inStream;
- CInFileStream *inStreamSpec = 0;
+ CInFileStream *inStreamSpec = NULL;
+
if (stdInMode)
{
inStream = new CStdInFileStream;
@@ -301,21 +448,19 @@ int main2(int numArgs, const char *args[])
}
else
{
- if (paramIndex >= nonSwitchStrings.Size())
- IncorrectCommand();
- const UString &inputName = nonSwitchStrings[paramIndex++];
+ const UString &inputName = params[paramIndex++];
inStreamSpec = new CInFileStream;
inStream = inStreamSpec;
if (!inStreamSpec->Open(us2fs(inputName)))
{
- fprintf(stderr, "\nError: can not open input file %s\n",
- (const char *)GetOemString(inputName));
+ PrintError2("can not open input file", inputName);
return 1;
}
}
CMyComPtr<ISequentialOutStream> outStream;
COutFileStream *outStreamSpec = NULL;
+
if (stdOutMode)
{
outStream = new CStdOutFileStream;
@@ -323,42 +468,70 @@ int main2(int numArgs, const char *args[])
}
else
{
- if (paramIndex >= nonSwitchStrings.Size())
- IncorrectCommand();
- const UString &outputName = nonSwitchStrings[paramIndex++];
+ const UString &outputName = params[paramIndex++];
outStreamSpec = new COutFileStream;
outStream = outStreamSpec;
if (!outStreamSpec->Create(us2fs(outputName), true))
{
- fprintf(stderr, "\nError: can not open output file %s\n",
- (const char *)GetOemString(outputName));
+ PrintError2("can not open output file", outputName);
return 1;
}
}
+ bool fileSizeDefined = false;
+ UInt64 fileSize = 0;
+
+ if (inStreamSpec)
+ {
+ if (!inStreamSpec->File.GetLength(fileSize))
+ throw "Can not get file length";
+ fileSizeDefined = true;
+ if (!stdOutMode)
+ Print_Size("Input size: ", fileSize);
+ }
+
+ if (encodeMode && !dictDefined)
+ {
+ dict = 1 << kDictSizeLog;
+ if (fileSizeDefined)
+ {
+ unsigned i;
+ for (i = 16; i < kDictSizeLog; i++)
+ if ((UInt32)((UInt32)1 << i) >= fileSize)
+ break;
+ dict = (UInt32)1 << i;
+ }
+ }
+
if (parser[NKey::kFilter86].ThereIs)
{
- // -f86 switch is for x86 filtered mode: BCJ + LZMA.
+ /* -f86 switch is for x86 filtered mode: BCJ + LZMA.
+ It uses modified header format.
+ It's not recommended to use -f86 mode now.
+ You can use xz format instead, if you want to use filters */
+
if (parser[NKey::kEOS].ThereIs || stdInMode)
throw "Can not use stdin in this mode";
- UInt64 fileSize;
- inStreamSpec->File.GetLength(fileSize);
+
if (fileSize > 0xF0000000)
throw "File is too big";
+
size_t inSize = (size_t)fileSize;
- Byte *inBuffer = 0;
+ Byte *inBuffer = NULL;
+
if (inSize != 0)
{
inBuffer = (Byte *)MyAlloc((size_t)inSize);
- if (inBuffer == 0)
+ if (!inBuffer)
throw kCantAllocate;
}
if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK)
throw "Can not read";
- Byte *outBuffer = 0;
+ Byte *outBuffer = NULL;
size_t outSize;
+
if (encodeMode)
{
// we allocate 105% of original size for output buffer
@@ -366,56 +539,70 @@ int main2(int numArgs, const char *args[])
if (outSize != 0)
{
outBuffer = (Byte *)MyAlloc((size_t)outSize);
- if (outBuffer == 0)
+ if (!outBuffer)
throw kCantAllocate;
}
- if (!dictDefined)
- dict = 1 << 23;
+
int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize,
5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);
+
if (res != 0)
{
- fprintf(stderr, "\nEncoder error = %d\n", (int)res);
+ PrintError_int("Encode error", (int)res);
return 1;
}
}
else
{
UInt64 outSize64;
+
if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0)
throw "data error";
+
outSize = (size_t)outSize64;
if (outSize != outSize64)
throw "too big";
if (outSize != 0)
{
outBuffer = (Byte *)MyAlloc(outSize);
- if (outBuffer == 0)
+ if (!outBuffer)
throw kCantAllocate;
}
+
int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize);
+
if (inSize != (size_t)fileSize)
throw "incorrect processed size";
if (res != 0)
- throw "LzmaDecoder error";
+ {
+ PrintError_int("Decode error", (int)res);
+ return 1;
+ }
}
+
if (WriteStream(outStream, outBuffer, outSize) != S_OK)
throw kWriteError;
+
MyFree(outBuffer);
MyFree(inBuffer);
- return 0;
}
+ else
+ {
+
+ CProgressPrint *progressSpec = NULL;
+ CMyComPtr<ICompressProgressInfo> progress;
+ if (!stdOutMode)
+ {
+ progressSpec = new CProgressPrint;
+ progress = progressSpec;
+ }
- UInt64 fileSize;
if (encodeMode)
{
NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder;
CMyComPtr<ICompressCoder> encoder = encoderSpec;
- if (!dictDefined)
- dict = 1 << 23;
-
UInt32 pb = 2;
UInt32 lc = 3; // = 0; for 32-bit data
UInt32 lp = 0; // = 2; for 32-bit data
@@ -434,8 +621,7 @@ int main2(int numArgs, const char *args[])
mcDefined = parser[NKey::kMc].ThereIs;
if (mcDefined)
- if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc))
- IncorrectCommand();
+ mc = GetNumber(parser[NKey::kMc].PostStrings[0]);
const PROPID propIDs[] =
{
@@ -450,6 +636,7 @@ int main2(int numArgs, const char *args[])
NCoderPropID::kNumThreads,
NCoderPropID::kMatchFinderCycles,
};
+
const unsigned kNumPropsMax = ARRAY_SIZE(propIDs);
PROPVARIANT props[kNumPropsMax];
@@ -480,92 +667,106 @@ int main2(int numArgs, const char *args[])
if (!mcDefined)
numProps--;
- if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK)
- IncorrectCommand();
- encoderSpec->WriteCoderProperties(outStream);
+ HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps);
+ if (res != S_OK)
+ return Error_HRESULT("incorrect encoder properties", res);
- if (eos || stdInMode)
- fileSize = (UInt64)(Int64)-1;
- else
- inStreamSpec->File.GetLength(fileSize);
+ if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
+ throw kWriteError;
- for (int i = 0; i < 8; i++)
- {
- Byte b = Byte(fileSize >> (8 * i));
- if (outStream->Write(&b, 1, 0) != S_OK)
- {
- PrintMessage(kWriteError);
- return 1;
- }
- }
- HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
- if (result == E_OUTOFMEMORY)
+ bool fileSizeWasUsed = true;
+ if (eos || stdInMode)
{
- PrintMessage("\nError: Can not allocate memory\n");
- return 1;
+ fileSize = (UInt64)(Int64)-1;
+ fileSizeWasUsed = false;
}
- else if (result != S_OK)
+
{
- fprintf(stderr, "\nEncoder error = %X\n", (unsigned)result);
- return 1;
+ Byte temp[8];
+ for (int i = 0; i < 8; i++)
+ temp[i]= (Byte)(fileSize >> (8 * i));
+ if (WriteStream(outStream, temp, 8) != S_OK)
+ throw kWriteError;
}
+
+ res = encoder->Code(inStream, outStream, NULL, NULL, progress);
+ if (progressSpec)
+ progressSpec->ClosePrint();
+
+ if (res != S_OK)
+ return Error_HRESULT("Encoding error", res);
+
+ UInt64 processedSize = encoderSpec->GetInputProcessedSize();
+
+ if (fileSizeWasUsed && processedSize != fileSize)
+ throw "Incorrect size of processed data";
}
else
{
NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder;
CMyComPtr<ICompressCoder> decoder = decoderSpec;
+
decoderSpec->FinishStream = true;
- const UInt32 kPropertiesSize = 5;
+
+ const unsigned kPropertiesSize = 5;
Byte header[kPropertiesSize + 8];
+
if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)
- {
- PrintMessage(kReadError);
- return 1;
- }
+ throw kReadError;
+
if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)
- {
- PrintMessage("SetDecoderProperties error");
- return 1;
- }
- fileSize = 0;
+ throw "SetDecoderProperties error";
+
+ UInt64 unpackSize = 0;
for (int i = 0; i < 8; i++)
- fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);
+ unpackSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i);
+
+ bool unpackSizeDefined = (unpackSize != (UInt64)(Int64)-1);
+
+ HRESULT res = decoder->Code(inStream, outStream, NULL, unpackSizeDefined ? &unpackSize : NULL, progress);
+ if (progressSpec)
+ progressSpec->ClosePrint();
- bool isSizeDefined = (fileSize != (UInt64)(Int64)-1);
- HRESULT res = decoder->Code(inStream, outStream, 0, isSizeDefined ? &fileSize : NULL, 0) != S_OK;
if (res != S_OK)
{
- PrintMessage("Decoder error");
- return 1;
- }
- if (isSizeDefined && decoderSpec->GetOutputProcessedSize() != fileSize)
- {
- PrintMessage("Error: incorrect uncompressed size in header");
- return 1;
+ if (res == S_FALSE)
+ {
+ PrintError("Decoding error");
+ return 1;
+ }
+ return Error_HRESULT("Decoding error", res);
}
+
+ if (unpackSizeDefined && unpackSize != decoderSpec->GetOutputProcessedSize())
+ throw "incorrect uncompressed size in header";
+ }
}
- if (outStreamSpec != NULL)
+
+ if (!stdOutMode)
+ Print_Size("Output size: ", outStreamSpec->ProcessedSize);
+
+ if (outStreamSpec)
{
if (outStreamSpec->Close() != S_OK)
- {
- PrintMessage("File closing error");
- return 1;
- }
+ throw "File closing error";
}
+
return 0;
}
int MY_CDECL main(int numArgs, const char *args[])
{
+ NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
+
try { return main2(numArgs, args); }
catch (const char *s)
{
- fprintf(stderr, "\nError: %s\n", s);
+ PrintError(s);
return 1;
}
catch(...)
{
- PrintMessage("\nError\n");
+ PrintError("Unknown Error");
return 1;
}
}
diff --git a/CPP/7zip/Bundles/LzmaCon/resource.rc b/CPP/7zip/Bundles/LzmaCon/resource.rc
index c68fdcc0..43b50738 100644
--- a/CPP/7zip/Bundles/LzmaCon/resource.rc
+++ b/CPP/7zip/Bundles/LzmaCon/resource.rc
@@ -1,3 +1,3 @@
-#include "../../../../C/7zVersion.rc"
+#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_APP("LZMA", "lzma")
diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
index 092fedcd..0cacd60c 100644
--- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
+++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
@@ -117,14 +117,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Archive\Common\CoderMixer2MT.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
@@ -197,6 +189,14 @@ SOURCE=..\..\UI\Console\OpenCallbackConsole.h
# End Source File
# Begin Source File
+SOURCE=..\..\UI\Console\PercentPrinter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\PercentPrinter.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\UI\Console\UserInputUtils.cpp
# End Source File
# Begin Source File
@@ -281,7 +281,15 @@ SOURCE=..\..\Compress\BcjRegister.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\BranchCoder.cpp
+SOURCE=..\..\Compress\BranchMisc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BranchMisc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BranchRegister.cpp
# End Source File
# Begin Source File
@@ -293,6 +301,10 @@ SOURCE=..\..\Compress\CopyRegister.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Compress\DeltaFilter.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Compress\Lzma2Decoder.cpp
# End Source File
# Begin Source File
@@ -605,6 +617,14 @@ SOURCE=..\..\Common\PropId.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Common\RegisterArc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\RegisterCodec.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Common\StreamBinder.cpp
# End Source File
# Begin Source File
@@ -758,6 +778,20 @@ SOURCE=..\..\..\..\C\Alloc.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Bcj2.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bcj2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bra.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Bra.h
# End Source File
# Begin Source File
@@ -767,11 +801,25 @@ SOURCE=..\..\..\..\C\Bra86.c
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\BraIA64.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\CpuArch.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Delta.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Delta.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Lzma2Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
index c8837f9d..01089c5e 100644
--- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
+++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
@@ -104,7 +104,7 @@ static const char *kHelpString =
"\nUsage: 7zSFX [<command>] [<switches>...]\n"
"\n"
"<Commands>\n"
- " l: List contents of archive\n"
+ // " l: List contents of archive\n"
" t: Test integrity of archive\n"
" x: eXtract files with full pathname (default)\n"
"<Switches>\n"
@@ -369,22 +369,22 @@ int Main2(
{
CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
- ecs->OutStream = g_StdStream;
+ ecs->Init(g_StdStream, &g_StdErr, g_StdStream);
#ifndef _NO_CRYPTO
ecs->PasswordIsDefined = passwordEnabled;
ecs->Password = password;
#endif
- ecs->Init();
-
+ /*
COpenCallbackConsole openCallback;
- openCallback.OutStream = g_StdStream;
+ openCallback.Init(g_StdStream, g_StdStream);
#ifndef _NO_CRYPTO
openCallback.PasswordIsDefined = passwordEnabled;
openCallback.Password = password;
#endif
+ */
CExtractOptions eo;
eo.StdOutMode = false;
@@ -402,7 +402,7 @@ int Main2(
codecs, CObjectVector<COpenType>(), CIntVector(),
v1, v2,
wildcardCensorHead,
- eo, &openCallback, ecs,
+ eo, ecs, ecs,
// NULL, // hash
errorMessage, stat);
if (!errorMessage.IsEmpty())
@@ -425,6 +425,9 @@ int Main2(
}
else
{
+ throw CSystemException(E_NOTIMPL);
+
+ /*
UInt64 numErrors = 0;
UInt64 numWarnings = 0;
HRESULT result = ListArchives(
@@ -447,6 +450,7 @@ int Main2(
}
if (result != S_OK)
throw CSystemException(result);
+ */
}
}
return 0;
diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile
index dd795b0b..d3d61372 100644
--- a/CPP/7zip/Bundles/SFXCon/makefile
+++ b/CPP/7zip/Bundles/SFXCon/makefile
@@ -14,6 +14,7 @@ CONSOLE_OBJS = \
$O\List.obj \
$O\MainAr.obj \
$O\OpenCallbackConsole.obj \
+ $O\PercentPrinter.obj \
$O\UserInputUtils.obj \
COMMON_OBJS = \
@@ -48,7 +49,6 @@ WIN_OBJS = \
$O\InBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
@@ -72,7 +72,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\ItemNameUtils.obj \
$O\MultiStream.obj \
@@ -88,13 +87,15 @@ AR_COMMON_OBJS = \
$O\7zRegister.obj \
COMPRESS_OBJS = \
- $O\BranchCoder.obj \
$O\Bcj2Coder.obj \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
+ $O\BranchMisc.obj \
+ $O\BranchRegister.obj \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
+ $O\DeltaFilter.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Register.obj \
$O\LzmaDecoder.obj \
@@ -109,8 +110,12 @@ CRYPTO_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bra.obj \
$O\Bra86.obj \
+ $O\BraIA64.obj \
$O\CpuArch.obj \
+ $O\Delta.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
$O\Ppmd7.obj \
diff --git a/CPP/7zip/Bundles/SFXCon/resource.rc b/CPP/7zip/Bundles/SFXCon/resource.rc
index a83581c2..58331b81 100644
--- a/CPP/7zip/Bundles/SFXCon/resource.rc
+++ b/CPP/7zip/Bundles/SFXCon/resource.rc
@@ -1,4 +1,4 @@
-#include "../../../../C/7zVersion.rc"
+#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx")
diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
index 9fe98fc0..ac7df6b2 100644
--- a/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
@@ -58,6 +58,11 @@ HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, co
#endif
}
+HRESULT CExtractCallbackImp::Open_Finished()
+{
+ return S_OK;
+}
+
STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)
{
#ifndef _NO_PROGRESS
@@ -83,7 +88,7 @@ void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathPar
{
fullPath += us2fs(dirPathParts[i]);
CreateDir(fullPath);
- fullPath += FCHAR_PATH_SEPARATOR;
+ fullPath.Add_PathSepar();
}
}
@@ -95,18 +100,21 @@ STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
return E_ABORT;
#endif
_outFileStream.Release();
- NCOM::CPropVariant propVariantName;
- RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariantName));
+
UString fullPath;
- if (propVariantName.vt == VT_EMPTY)
- fullPath = _itemDefaultName;
- else
{
- if (propVariantName.vt != VT_BSTR)
- return E_FAIL;
- fullPath = propVariantName.bstrVal;
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));
+ if (prop.vt == VT_EMPTY)
+ fullPath = _itemDefaultName;
+ else
+ {
+ if (prop.vt != VT_BSTR)
+ return E_FAIL;
+ fullPath.SetFromBstr(prop.bstrVal);
+ }
+ _filePath = fullPath;
}
- _filePath = fullPath;
if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)
{
diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
index 3a8ae36b..1f076f7d 100644
--- a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
+++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
@@ -205,14 +205,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Archive\Common\CoderMixer2MT.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
@@ -257,7 +249,15 @@ SOURCE=..\..\Compress\BcjRegister.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\BranchCoder.cpp
+SOURCE=..\..\Compress\BranchMisc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BranchMisc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BranchRegister.cpp
# End Source File
# Begin Source File
@@ -269,6 +269,10 @@ SOURCE=..\..\Compress\CopyRegister.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Compress\DeltaFilter.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Compress\Lzma2Decoder.cpp
# End Source File
# Begin Source File
@@ -513,14 +517,6 @@ SOURCE=..\..\Common\LimitedStreams.h
# End Source File
# Begin Source File
-SOURCE=..\..\Common\LockedStream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Common\LockedStream.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Common\OutBuffer.cpp
# End Source File
# Begin Source File
@@ -680,6 +676,20 @@ SOURCE=..\..\..\..\C\Alloc.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Bcj2.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bcj2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bra.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Bra.h
# End Source File
# Begin Source File
@@ -689,6 +699,11 @@ SOURCE=..\..\..\..\C\Bra86.c
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\BraIA64.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\CpuArch.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
@@ -698,6 +713,15 @@ SOURCE=..\..\..\..\C\CpuArch.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Delta.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Delta.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Lzma2Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
index 20bde9e9..611ef651 100644
--- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -94,12 +94,11 @@ static bool ReadDataString(CFSTR fileName, LPCSTR startID,
}
}
-static char kStartID[] = ",!@Install@!UTF-8!";
-static char kEndID[] = ",!@InstallEnd@!";
+static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 };
+static char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 };
-class CInstallIDInit
+struct CInstallIDInit
{
-public:
CInstallIDInit()
{
kStartID[0] = ';';
@@ -147,7 +146,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
switches.Trim();
bool assumeYes = false;
- if (MyStringCompareNoCase_N(switches, L"-y", 2) == 0)
+ if (switches.IsPrefixedBy_Ascii_NoCase("-y"))
{
assumeYes = true;
switches = switches.Ptr(2);
@@ -177,7 +176,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
UString friendlyName = GetTextConfigValue(pairs, L"Title");
UString installPrompt = GetTextConfigValue(pairs, L"BeginPrompt");
UString progress = GetTextConfigValue(pairs, L"Progress");
- if (progress.IsEqualToNoCase(L"no"))
+ if (progress.IsEqualTo_Ascii_NoCase("no"))
showProgress = false;
int index = FindTextConfigItem(pairs, L"Directory");
if (index >= 0)
@@ -265,8 +264,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
if (!switches.IsEmpty())
{
- if (!executeParameters.IsEmpty())
- executeParameters += L' ';
+ executeParameters.Add_Space_if_NotEmpty();
executeParameters += switches;
}
@@ -315,7 +313,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
if (!switches.IsEmpty())
{
- appLaunched += L' ';
+ appLaunched.Add_Space();
appLaunched += switches;
}
STARTUPINFO startupInfo;
diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile
index ac5c6aa4..ae631988 100644
--- a/CPP/7zip/Bundles/SFXSetup/makefile
+++ b/CPP/7zip/Bundles/SFXSetup/makefile
@@ -44,7 +44,6 @@ WIN_CTRL_OBJS = \
$O\InBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
@@ -68,7 +67,6 @@ FM_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
@@ -82,13 +80,15 @@ AR_COMMON_OBJS = \
$O\7zRegister.obj \
COMPRESS_OBJS = \
- $O\BranchCoder.obj \
$O\Bcj2Coder.obj \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
+ $O\BranchMisc.obj \
+ $O\BranchRegister.obj \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
+ $O\DeltaFilter.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Register.obj \
$O\LzmaDecoder.obj \
@@ -96,8 +96,12 @@ COMPRESS_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bra.obj \
$O\Bra86.obj \
+ $O\BraIA64.obj \
$O\CpuArch.obj \
+ $O\Delta.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
$O\Threads.obj \
diff --git a/CPP/7zip/Bundles/SFXSetup/resource.rc b/CPP/7zip/Bundles/SFXSetup/resource.rc
index 8819a2c8..47e1b762 100644
--- a/CPP/7zip/Bundles/SFXSetup/resource.rc
+++ b/CPP/7zip/Bundles/SFXSetup/resource.rc
@@ -1,4 +1,4 @@
-#include "../../../../C/7zVersion.rc"
+#include "../../MyVersionInfo.rc"
#include "resource.h"
MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx")
diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
index 55dbe377..3e11881b 100644
--- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
+++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
@@ -197,14 +197,6 @@ SOURCE=..\..\Archive\Common\CoderMixer2.h
# End Source File
# Begin Source File
-SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Archive\Common\CoderMixer2MT.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
@@ -257,7 +249,15 @@ SOURCE=..\..\Compress\BcjRegister.cpp
# End Source File
# Begin Source File
-SOURCE=..\..\Compress\BranchCoder.cpp
+SOURCE=..\..\Compress\BranchMisc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BranchMisc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BranchRegister.cpp
# End Source File
# Begin Source File
@@ -269,6 +269,10 @@ SOURCE=..\..\Compress\CopyRegister.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\Compress\DeltaFilter.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Compress\Lzma2Decoder.cpp
# End Source File
# Begin Source File
@@ -509,6 +513,14 @@ SOURCE=..\..\UI\FileManager\FormatUtils.h
# End Source File
# Begin Source File
+SOURCE=..\..\UI\FileManager\PropertyName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\PropertyName.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\UI\FileManager\SysIconUtils.cpp
# End Source File
# Begin Source File
@@ -858,6 +870,20 @@ SOURCE=..\..\..\..\C\Alloc.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Bcj2.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bcj2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bra.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Bra.h
# End Source File
# Begin Source File
@@ -867,11 +893,25 @@ SOURCE=..\..\..\..\C\Bra86.c
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\BraIA64.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\CpuArch.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Delta.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Delta.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Lzma2Dec.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile
index d6e1de78..7f2a78c1 100644
--- a/CPP/7zip/Bundles/SFXWin/makefile
+++ b/CPP/7zip/Bundles/SFXWin/makefile
@@ -56,7 +56,6 @@ WIN_CTRL_OBJS = \
$O\InBuffer.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
- $O\LockedStream.obj \
$O\OutBuffer.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
@@ -85,6 +84,7 @@ FM_OBJS = \
$O\OverwriteDialog.obj \
$O\PasswordDialog.obj \
$O\ProgressDialog2.obj \
+ $O\PropertyName.obj \
$O\SysIconUtils.obj \
AR_OBJS = \
@@ -92,7 +92,6 @@ AR_OBJS = \
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\ItemNameUtils.obj \
$O\MultiStream.obj \
@@ -107,13 +106,15 @@ AR_COMMON_OBJS = \
$O\7zRegister.obj \
COMPRESS_OBJS = \
- $O\BranchCoder.obj \
$O\Bcj2Coder.obj \
$O\Bcj2Register.obj \
$O\BcjCoder.obj \
$O\BcjRegister.obj \
+ $O\BranchMisc.obj \
+ $O\BranchRegister.obj \
$O\CopyCoder.obj \
$O\CopyRegister.obj \
+ $O\DeltaFilter.obj \
$O\Lzma2Decoder.obj \
$O\Lzma2Register.obj \
$O\LzmaDecoder.obj \
@@ -128,7 +129,11 @@ CRYPTO_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bra.obj \
$O\Bra86.obj \
+ $O\BraIA64.obj \
+ $O\Delta.obj \
$O\CpuArch.obj \
$O\Lzma2Dec.obj \
$O\LzmaDec.obj \
diff --git a/CPP/7zip/Bundles/SFXWin/resource.rc b/CPP/7zip/Bundles/SFXWin/resource.rc
index ccde0cb2..91292b2f 100644
--- a/CPP/7zip/Bundles/SFXWin/resource.rc
+++ b/CPP/7zip/Bundles/SFXWin/resource.rc
@@ -1,4 +1,4 @@
-#include "../../../../C/7zVersion.rc"
+#include "../../MyVersionInfo.rc"
#include "../../GuiCommon.rc"
#include "../../UI/GUI/ExtractDialogRes.h"
#include "../../UI/FileManager/PropertyNameRes.h"
diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp
index e5e09327..75074ad8 100644
--- a/CPP/7zip/Common/CreateCoder.cpp
+++ b/CPP/7zip/Common/CreateCoder.cpp
@@ -10,25 +10,40 @@
#include "FilterCoder.h"
#include "RegisterCodec.h"
-static const unsigned int kNumCodecsMax = 64;
-unsigned int g_NumCodecs = 0;
+static const unsigned kNumCodecsMax = 64;
+unsigned g_NumCodecs = 0;
const CCodecInfo *g_Codecs[kNumCodecsMax];
+
+// We use g_ExternalCodecs in other stages.
+/*
+#ifdef EXTERNAL_CODECS
+extern CExternalCodecs g_ExternalCodecs;
+#define CHECK_GLOBAL_CODECS \
+ if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs;
+#endif
+*/
+
+#define CHECK_GLOBAL_CODECS
+
void RegisterCodec(const CCodecInfo *codecInfo) throw()
{
if (g_NumCodecs < kNumCodecsMax)
g_Codecs[g_NumCodecs++] = codecInfo;
}
-static const unsigned int kNumHashersMax = 16;
-unsigned int g_NumHashers = 0;
+static const unsigned kNumHashersMax = 16;
+unsigned g_NumHashers = 0;
const CHasherInfo *g_Hashers[kNumHashersMax];
+
void RegisterHasher(const CHasherInfo *hashInfo) throw()
{
if (g_NumHashers < kNumHashersMax)
g_Hashers[g_NumHashers++] = hashInfo;
}
+
#ifdef EXTERNAL_CODECS
+
static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
{
NWindows::NCOM::CPropVariant prop;
@@ -55,102 +70,130 @@ static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index,
return S_OK;
}
-HRESULT CExternalCodecs::LoadCodecs()
+HRESULT CExternalCodecs::Load()
{
+ Codecs.Clear();
+ Hashers.Clear();
+
if (GetCodecs)
{
+ CCodecInfoEx info;
+
+ UString s;
UInt32 num;
- RINOK(GetCodecs->GetNumberOfMethods(&num));
+ RINOK(GetCodecs->GetNumMethods(&num));
+
for (UInt32 i = 0; i < num; i++)
{
- CCodecInfoEx info;
NWindows::NCOM::CPropVariant prop;
+
RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop));
- // if (prop.vt != VT_BSTR)
- // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);
- // memcpy(info.Id.ID, prop.bstrVal, info.Id.IDSize);
if (prop.vt != VT_UI8)
continue; // old Interface
info.Id = prop.uhVal.QuadPart;
+
prop.Clear();
+ info.Name.Empty();
RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop));
if (prop.vt == VT_BSTR)
- info.Name = prop.bstrVal;
+ info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
else if (prop.vt != VT_EMPTY)
- return E_INVALIDARG;
+ continue;
- RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kInStreams, info.NumInStreams));
- RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kOutStreams, info.NumOutStreams));
+ RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams));
+ {
+ UInt32 numUnpackStreams = 1;
+ RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams));
+ if (numUnpackStreams != 1)
+ continue;
+ }
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));
Codecs.Add(info);
}
}
+
if (GetHashers)
{
UInt32 num = GetHashers->GetNumHashers();
+ CHasherInfoEx info;
+
for (UInt32 i = 0; i < num; i++)
{
- CHasherInfoEx info;
NWindows::NCOM::CPropVariant prop;
+
RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop));
if (prop.vt != VT_UI8)
continue;
info.Id = prop.uhVal.QuadPart;
+
prop.Clear();
+ info.Name.Empty();
RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop));
if (prop.vt == VT_BSTR)
- info.Name = prop.bstrVal;
+ info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
else if (prop.vt != VT_EMPTY)
- return E_INVALIDARG;
+ continue;
Hashers.Add(info);
}
}
+
return S_OK;
}
#endif
-bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS
- const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)
+
+bool FindMethod(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const AString &name,
+ CMethodId &methodId, UInt32 &numStreams)
{
- UInt32 i;
+ unsigned i;
for (i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &codec = *g_Codecs[i];
- if (name.IsEqualToNoCase(codec.Name))
+ if (StringsAreEqualNoCase_Ascii(name, codec.Name))
{
methodId = codec.Id;
- numInStreams = codec.NumInStreams;
- numOutStreams = 1;
+ numStreams = codec.NumStreams;
return true;
}
}
+
#ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
if (__externalCodecs)
- for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)
+ for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
{
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
- if (codec.Name.IsEqualToNoCase(name))
+ if (StringsAreEqualNoCase_Ascii(name, codec.Name))
{
methodId = codec.Id;
- numInStreams = codec.NumInStreams;
- numOutStreams = codec.NumOutStreams;
+ numStreams = codec.NumStreams;
return true;
}
}
+
#endif
+
return false;
}
-bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId, UString &name)
+bool FindMethod(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ AString &name)
{
- UInt32 i;
+ name.Empty();
+
+ unsigned i;
for (i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &codec = *g_Codecs[i];
@@ -160,9 +203,13 @@ bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS
return true;
}
}
+
#ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
if (__externalCodecs)
- for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)
+ for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
{
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
if (methodId == codec.Id)
@@ -171,62 +218,79 @@ bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS
return true;
}
}
+
#endif
+
return false;
}
-bool FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS
- const UString &name,
- CMethodId &methodId)
+bool FindHashMethod(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const AString &name,
+ CMethodId &methodId)
{
- UInt32 i;
+ unsigned i;
for (i = 0; i < g_NumHashers; i++)
{
const CHasherInfo &codec = *g_Hashers[i];
- if (name.IsEqualToNoCase(codec.Name))
+ if (StringsAreEqualNoCase_Ascii(name, codec.Name))
{
methodId = codec.Id;
return true;
}
}
+
#ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
if (__externalCodecs)
- for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)
+ for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
{
const CHasherInfoEx &codec = __externalCodecs->Hashers[i];
- if (codec.Name.IsEqualToNoCase(name))
+ if (StringsAreEqualNoCase_Ascii(name, codec.Name))
{
methodId = codec.Id;
return true;
}
}
+
#endif
+
return false;
}
-void GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS
+void GetHashMethods(
+ DECL_EXTERNAL_CODECS_LOC_VARS
CRecordVector<CMethodId> &methods)
{
methods.ClearAndSetSize(g_NumHashers);
- UInt32 i;
+ unsigned i;
for (i = 0; i < g_NumHashers; i++)
methods[i] = (*g_Hashers[i]).Id;
+
#ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
if (__externalCodecs)
- for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)
+ for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
methods.Add(__externalCodecs->Hashers[i].Id);
+
#endif
}
HRESULT CreateCoder(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- CMyComPtr<ICompressFilter> &filter,
- CMyComPtr<ICompressCoder> &coder,
- CMyComPtr<ICompressCoder2> &coder2,
- bool encode, bool onlyCoder)
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter,
+ CCreatedCoder &cod)
{
- UInt32 i;
+ cod.IsExternal = false;
+ cod.IsFilter = false;
+ cod.NumStreams = 1;
+
+ unsigned i;
for (i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &codec = *g_Codecs[i];
@@ -238,9 +302,9 @@ HRESULT CreateCoder(
{
void *p = codec.CreateEncoder();
if (codec.IsFilter) filter = (ICompressFilter *)p;
- else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
- else coder2 = (ICompressCoder2 *)p;
- break;
+ else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
+ else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
+ return S_OK;
}
}
else
@@ -248,16 +312,21 @@ HRESULT CreateCoder(
{
void *p = codec.CreateDecoder();
if (codec.IsFilter) filter = (ICompressFilter *)p;
- else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
- else coder2 = (ICompressCoder2 *)p;
- break;
+ else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
+ else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
+ return S_OK;
}
}
}
#ifdef EXTERNAL_CODECS
- if (!filter && !coder && !coder2 && __externalCodecs)
- for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++)
+
+ CHECK_GLOBAL_CODECS
+
+ if (__externalCodecs)
+ {
+ cod.IsExternal = true;
+ for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
{
const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
if (codec.Id == methodId)
@@ -266,125 +335,126 @@ HRESULT CreateCoder(
{
if (codec.EncoderIsAssigned)
{
- if (codec.IsSimpleCodec())
- {
- HRESULT result = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);
- if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)
- return result;
- if (!coder)
- {
- RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));
- }
- }
- else
+ if (codec.NumStreams == 1)
{
- RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));
+ HRESULT res = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
+ if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
+ return res;
+ if (cod.Coder)
+ return res;
+ return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter);
}
- break;
+ cod.NumStreams = codec.NumStreams;
+ return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
}
}
else
if (codec.DecoderIsAssigned)
{
- if (codec.IsSimpleCodec())
+ if (codec.NumStreams == 1)
{
- HRESULT result = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);
- if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE)
- return result;
- if (!coder)
- {
- RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));
- }
+ HRESULT res = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
+ if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
+ return res;
+ if (cod.Coder)
+ return res;
+ return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter);
}
- else
- {
- RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));
- }
- break;
+ cod.NumStreams = codec.NumStreams;
+ return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
}
}
}
+ }
#endif
- if (onlyCoder && filter)
- {
- CFilterCoder *coderSpec = new CFilterCoder;
- coder = coderSpec;
- coderSpec->Filter = filter;
- }
return S_OK;
}
HRESULT CreateCoder(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- CMyComPtr<ICompressCoder> &coder,
- CMyComPtr<ICompressCoder2> &coder2,
- bool encode)
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CCreatedCoder &cod)
{
CMyComPtr<ICompressFilter> filter;
- return CreateCoder(
- EXTERNAL_CODECS_LOC_VARS
- methodId,
- filter, coder, coder2, encode, true);
+ HRESULT res = CreateCoder(
+ EXTERNAL_CODECS_LOC_VARS
+ methodId, encode,
+ filter, cod);
+
+ if (filter)
+ {
+ cod.IsFilter = true;
+ CFilterCoder *coderSpec = new CFilterCoder(encode);
+ cod.Coder = coderSpec;
+ coderSpec->Filter = filter;
+ }
+
+ return res;
}
HRESULT CreateCoder(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- CMyComPtr<ICompressCoder> &coder, bool encode)
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressCoder> &coder)
{
- CMyComPtr<ICompressFilter> filter;
- CMyComPtr<ICompressCoder2> coder2;
- return CreateCoder(
- EXTERNAL_CODECS_LOC_VARS
- methodId,
- coder, coder2, encode);
+ CCreatedCoder cod;
+ HRESULT res = CreateCoder(
+ EXTERNAL_CODECS_LOC_VARS
+ methodId, encode,
+ cod);
+ coder = cod.Coder;
+ return res;
}
HRESULT CreateFilter(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- CMyComPtr<ICompressFilter> &filter,
- bool encode)
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter)
{
- CMyComPtr<ICompressCoder> coder;
- CMyComPtr<ICompressCoder2> coder2;
+ CCreatedCoder cod;
return CreateCoder(
- EXTERNAL_CODECS_LOC_VARS
- methodId,
- filter, coder, coder2, encode, false);
+ EXTERNAL_CODECS_LOC_VARS
+ methodId, encode,
+ filter, cod);
}
+
HRESULT CreateHasher(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- UString &name,
- CMyComPtr<IHasher> &hasher)
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ AString &name,
+ CMyComPtr<IHasher> &hasher)
{
- UInt32 i;
+ name.Empty();
+
+ unsigned i;
for (i = 0; i < g_NumHashers; i++)
{
const CHasherInfo &codec = *g_Hashers[i];
if (codec.Id == methodId)
{
- hasher = (IHasher *)codec.CreateHasher();
+ hasher = codec.CreateHasher();
name = codec.Name;
break;
}
}
#ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
if (!hasher && __externalCodecs)
- for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++)
+ for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
{
const CHasherInfoEx &codec = __externalCodecs->Hashers[i];
if (codec.Id == methodId)
{
name = codec.Name;
- return __externalCodecs->GetHashers->CreateHasher(i, &hasher);
+ return __externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher);
}
}
+
#endif
return S_OK;
diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h
index 50a68ce1..f06064b6 100644
--- a/CPP/7zip/Common/CreateCoder.h
+++ b/CPP/7zip/Common/CreateCoder.h
@@ -5,29 +5,44 @@
#include "../../Common/MyCom.h"
#include "../../Common/MyString.h"
+
#include "../ICoder.h"
#include "MethodId.h"
+/*
+ if EXTERNAL_CODECS is not defined, the code supports only codecs that
+ are statically linked at compile-time and link-time.
+
+ if EXTERNAL_CODECS is defined, the code supports also codecs from another
+ executable modules, that can be linked dynamically at run-time:
+ - EXE module can use codecs from external DLL files.
+ - DLL module can use codecs from external EXE and DLL files.
+
+ CExternalCodecs contains information about codecs and interfaces to create them.
+
+ The order of codecs:
+ 1) Internal codecs
+ 2) External codecs
+*/
+
#ifdef EXTERNAL_CODECS
struct CCodecInfoEx
{
- UString Name;
CMethodId Id;
- UInt32 NumInStreams;
- UInt32 NumOutStreams;
+ AString Name;
+ UInt32 NumStreams;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
- bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; }
CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}
};
struct CHasherInfoEx
{
- UString Name;
CMethodId Id;
+ AString Name;
};
#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,
@@ -35,7 +50,7 @@ struct CHasherInfoEx
#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);
#define IMPL_ISetCompressCodecsInfo2(x) \
STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \
- COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.LoadCodecs(); COM_TRY_END }
+ COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.Load(); COM_TRY_END }
#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)
struct CExternalCodecs
@@ -46,13 +61,36 @@ struct CExternalCodecs
CObjectVector<CCodecInfoEx> Codecs;
CObjectVector<CHasherInfoEx> Hashers;
- HRESULT LoadCodecs();
+ bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; }
+
+ HRESULT Load();
+
+ void ClearAndRelease()
+ {
+ Hashers.Clear();
+ Codecs.Clear();
+ GetHashers.Release();
+ GetCodecs.Release();
+ }
+
+ ~CExternalCodecs()
+ {
+ GetHashers.Release();
+ GetCodecs.Release();
+ }
};
-#define EXTERNAL_CODECS_VARS2 &__externalCodecs
+extern CExternalCodecs g_ExternalCodecs;
+
+#define EXTERNAL_CODECS_VARS2 (__externalCodecs.IsSet() ? &__externalCodecs : &g_ExternalCodecs)
+#define EXTERNAL_CODECS_VARS2_L (&__externalCodecs)
+#define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs)
#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs;
-#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,
+
+#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,
+#define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L,
+#define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G,
#define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs
#define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs
@@ -68,7 +106,9 @@ struct CExternalCodecs
#define IMPL_ISetCompressCodecsInfo
#define EXTERNAL_CODECS_VARS2
#define DECL_EXTERNAL_CODECS_VARS
-#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2
+#define EXTERNAL_CODECS_VARS
+#define EXTERNAL_CODECS_VARS_L
+#define EXTERNAL_CODECS_VARS_G
#define DECL_EXTERNAL_CODECS_LOC_VARS2
#define EXTERNAL_CODECS_LOC_VARS2
#define DECL_EXTERNAL_CODECS_LOC_VARS
@@ -76,52 +116,67 @@ struct CExternalCodecs
#endif
+
+
+
bool FindMethod(
- DECL_EXTERNAL_CODECS_LOC_VARS
- const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const AString &name,
+ CMethodId &methodId, UInt32 &numStreams);
bool FindMethod(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId, UString &name);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ AString &name);
bool FindHashMethod(
- DECL_EXTERNAL_CODECS_LOC_VARS
- const UString &name, CMethodId &methodId);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const AString &name,
+ CMethodId &methodId);
void GetHashMethods(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CRecordVector<CMethodId> &methods);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CRecordVector<CMethodId> &methods);
+
+
+struct CCreatedCoder
+{
+ CMyComPtr<ICompressCoder> Coder;
+ CMyComPtr<ICompressCoder2> Coder2;
+
+ bool IsExternal;
+ bool IsFilter; // = true, if Coder was created from filter
+ UInt32 NumStreams;
+
+ // CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {}
+};
+
HRESULT CreateCoder(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- CMyComPtr<ICompressFilter> &filter,
- CMyComPtr<ICompressCoder> &coder,
- CMyComPtr<ICompressCoder2> &coder2,
- bool encode, bool onlyCoder);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter,
+ CCreatedCoder &cod);
HRESULT CreateCoder(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- CMyComPtr<ICompressCoder> &coder,
- CMyComPtr<ICompressCoder2> &coder2,
- bool encode);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CCreatedCoder &cod);
HRESULT CreateCoder(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- CMyComPtr<ICompressCoder> &coder, bool encode);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressCoder> &coder);
HRESULT CreateFilter(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- CMyComPtr<ICompressFilter> &filter,
- bool encode);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter);
HRESULT CreateHasher(
- DECL_EXTERNAL_CODECS_LOC_VARS
- CMethodId methodId,
- UString &name,
- CMyComPtr<IHasher> &hacher);
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ AString &name,
+ CMyComPtr<IHasher> &hasher);
#endif
diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp
index 958360fa..d186e599 100644
--- a/CPP/7zip/Common/FilePathAutoRename.cpp
+++ b/CPP/7zip/Common/FilePathAutoRename.cpp
@@ -12,44 +12,40 @@
using namespace NWindows;
static bool MakeAutoName(const FString &name,
- const FString &extension, unsigned value, FString &path)
+ const FString &extension, UInt32 value, FString &path)
{
- FChar number[16];
- ConvertUInt32ToString(value, number);
+ char temp[16];
+ ConvertUInt32ToString(value, temp);
path = name;
- path += number;
+ path.AddAscii(temp);
path += extension;
return NFile::NFind::DoesFileOrDirExist(path);
}
-bool AutoRenamePath(FString &fullProcessedPath)
+bool AutoRenamePath(FString &path)
{
- FString path;
- int dotPos = fullProcessedPath.ReverseFind(FTEXT('.'));
+ int dotPos = path.ReverseFind_Dot();
+ int slashPos = path.ReverseFind_PathSepar();
- int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));
- #ifdef _WIN32
- int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
-
- FString name, extension;
- if (dotPos > slashPos && dotPos > 0)
+ FString name = path;
+ FString extension;
+ if (dotPos > slashPos + 1)
{
- name.SetFrom(fullProcessedPath, dotPos);
- extension = fullProcessedPath.Ptr(dotPos);
+ name.DeleteFrom(dotPos);
+ extension = path.Ptr(dotPos);
}
- else
- name = fullProcessedPath;
- name += L'_';
- unsigned left = 1, right = (1 << 30);
+ name += FTEXT('_');
+
+ FString temp;
+
+ UInt32 left = 1, right = ((UInt32)1 << 30);
while (left != right)
{
- unsigned mid = (left + right) / 2;
- if (MakeAutoName(name, extension, mid, path))
+ UInt32 mid = (left + right) / 2;
+ if (MakeAutoName(name, extension, mid, temp))
left = mid + 1;
else
right = mid;
}
- return !MakeAutoName(name, extension, right, fullProcessedPath);
+ return !MakeAutoName(name, extension, right, path);
}
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp
index 1523fad1..f3a322fc 100644
--- a/CPP/7zip/Common/FileStreams.cpp
+++ b/CPP/7zip/Common/FileStreams.cpp
@@ -29,25 +29,29 @@ static inline HRESULT ConvertBoolToHRESULT(bool result)
#endif
}
-#ifdef SUPPORT_DEVICE_FILE
static const UInt32 kClusterSize = 1 << 18;
CInFileStream::CInFileStream():
+ #ifdef SUPPORT_DEVICE_FILE
VirtPos(0),
PhyPos(0),
Buf(0),
BufSize(0),
- SupportHardLinks(false)
+ #endif
+ SupportHardLinks(false),
+ Callback(NULL),
+ CallbackRef(0)
{
}
-#endif
-
CInFileStream::~CInFileStream()
{
#ifdef SUPPORT_DEVICE_FILE
MidFree(Buf);
#endif
+
+ if (Callback)
+ Callback->InFileStream_On_Destroy(CallbackRef);
}
STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
@@ -148,19 +152,37 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
bool result = File.ReadPart(data, size, realProcessedSize);
if (processedSize)
*processedSize = realProcessedSize;
+
#ifdef SUPPORT_DEVICE_FILE
VirtPos += realProcessedSize;
PhyPos += realProcessedSize;
#endif
- return ConvertBoolToHRESULT(result);
-
+
+ if (result)
+ return S_OK;
+
+ {
+ DWORD error = ::GetLastError();
+
+ if (Callback)
+ return Callback->InFileStream_On_Error(CallbackRef, error);
+ if (error == 0)
+ return E_FAIL;
+
+ return HRESULT_FROM_WIN32(error);
+ }
+
#else
if (processedSize)
*processedSize = 0;
ssize_t res = File.Read(data, (size_t)size);
if (res == -1)
+ {
+ if (Callback)
+ return Callback->InFileStream_On_Error(CallbackRef, E_FAIL);
return E_FAIL;
+ }
if (processedSize)
*processedSize = (UInt32)res;
return S_OK;
@@ -321,7 +343,7 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces
#ifdef USE_WIN_FILE
UInt32 realProcessedSize;
- bool result = File.WritePart(data, size, realProcessedSize);
+ bool result = File.Write(data, size, realProcessedSize);
ProcessedSize += realProcessedSize;
if (processedSize)
*processedSize = realProcessedSize;
@@ -346,6 +368,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
{
if (seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
+
#ifdef USE_WIN_FILE
UInt64 realNewPosition;
@@ -369,6 +392,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
{
#ifdef USE_WIN_FILE
+
UInt64 currentPos;
if (!File.Seek(0, FILE_CURRENT, currentPos))
return E_FAIL;
@@ -376,12 +400,21 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
UInt64 currentPos2;
result = result && File.Seek(currentPos, currentPos2);
return result ? S_OK : E_FAIL;
+
#else
+
return E_FAIL;
+
#endif
}
+HRESULT COutFileStream::GetSize(UInt64 *size)
+{
+ return ConvertBoolToHRESULT(File.GetLength(*size));
+}
+
#ifdef UNDER_CE
+
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
size_t s2 = fwrite(data, 1, size, stdout);
@@ -389,13 +422,16 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro
*processedSize = s2;
return (s2 == size) ? S_OK : E_FAIL;
}
+
#else
+
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
*processedSize = 0;
#ifdef _WIN32
+
UInt32 realProcessedSize;
BOOL res = TRUE;
if (size > 0)
@@ -407,6 +443,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro
sizeTemp = size;
res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
+ _size += realProcessedSize;
size -= realProcessedSize;
data = (const void *)((const Byte *)data + realProcessedSize);
if (processedSize)
@@ -417,18 +454,21 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro
#else
ssize_t res;
+
do
{
res = write(1, data, (size_t)size);
}
while (res < 0 && (errno == EINTR));
+
if (res == -1)
return E_FAIL;
+
+ _size += (size_t)res;
if (processedSize)
*processedSize = (UInt32)res;
return S_OK;
- return S_OK;
#endif
}
diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h
index 971366e9..ef2986fd 100644
--- a/CPP/7zip/Common/FileStreams.h
+++ b/CPP/7zip/Common/FileStreams.h
@@ -19,6 +19,18 @@
#include "../IStream.h"
+#ifdef _WIN32
+typedef UINT_PTR My_UINT_PTR;
+#else
+typedef UINT My_UINT_PTR;
+#endif
+
+struct IInFileStream_Callback
+{
+ virtual HRESULT InFileStream_On_Error(My_UINT_PTR val, DWORD error) = 0;
+ virtual void InFileStream_On_Destroy(My_UINT_PTR val) = 0;
+};
+
class CInFileStream:
public IInStream,
public IStreamGetSize,
@@ -45,12 +57,13 @@ public:
#endif
bool SupportHardLinks;
-
+
+ IInFileStream_Callback *Callback;
+ My_UINT_PTR CallbackRef;
+
virtual ~CInFileStream();
- #ifdef SUPPORT_DEVICE_FILE
CInFileStream();
- #endif
bool Open(CFSTR fileName)
{
@@ -132,15 +145,20 @@ public:
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(UInt64 newSize);
+
+ HRESULT GetSize(UInt64 *size);
};
class CStdOutFileStream:
public ISequentialOutStream,
public CMyUnknownImp
{
+ UInt64 _size;
public:
MY_UNKNOWN_IMP
+ UInt64 GetSize() const { return _size; }
+ CStdOutFileStream(): _size(0) {}
virtual ~CStdOutFileStream() {}
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp
index 578a3193..4f3ae4e7 100644
--- a/CPP/7zip/Common/FilterCoder.cpp
+++ b/CPP/7zip/Common/FilterCoder.cpp
@@ -2,90 +2,144 @@
#include "StdAfx.h"
-#include "../../../C/Alloc.h"
-
#include "../../Common/Defs.h"
#include "FilterCoder.h"
#include "StreamUtils.h"
-static const UInt32 kBufferSize = 1 << 17;
+/*
+ AES filters need 16-bytes alignment for HARDWARE-AES instructions.
+ So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block.
+
+ AES-CBC filters need data size aligned for 16-bytes.
+ So the encoder can add zeros to the end of original stream.
+
+ Some filters (BCJ and others) don't process data at the end of stream in some cases.
+ So the encoder and decoder write such last bytes without change.
+*/
+
+
+static const UInt32 kBufSize = 1 << 20;
-CFilterCoder::CFilterCoder()
+STDMETHODIMP CFilterCoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
+STDMETHODIMP CFilterCoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
+
+HRESULT CFilterCoder::Alloc()
{
- _buffer = (Byte *)::MidAlloc(kBufferSize);
- if (_buffer == 0)
- throw 1;
+ UInt32 size = MyMin(_inBufSize, _outBufSize);
+ /* minimal bufSize is 16 bytes for AES and IA64 filter.
+ bufSize for AES must be aligned for 16 bytes.
+ We use (1 << 12) min size to support future aligned filters. */
+ const UInt32 kMinSize = 1 << 12;
+ size &= ~(UInt32)(kMinSize - 1);
+ if (size < kMinSize)
+ size = kMinSize;
+ if (!_buf || _bufSize != size)
+ {
+ AllocAlignedMask(size, 16 - 1);
+ if (!_buf)
+ return E_OUTOFMEMORY;
+ _bufSize = size;
+ }
+ return S_OK;
}
-CFilterCoder::~CFilterCoder()
+HRESULT CFilterCoder::Init_and_Alloc()
{
- ::MidFree(_buffer);
+ RINOK(Filter->Init());
+ return Alloc();
}
-HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
+CFilterCoder::CFilterCoder(bool encodeMode):
+ _bufSize(0),
+ _inBufSize(kBufSize),
+ _outBufSize(kBufSize),
+ _encodeMode(encodeMode),
+ _outSizeIsDefined(false),
+ _outSize(0),
+ _nowPos64(0)
+ {}
+
+CFilterCoder::~CFilterCoder()
{
- if (_outSizeIsDefined)
- {
- UInt64 remSize = _outSize - _nowPos64;
- if (size > remSize)
- size = (UInt32)remSize;
- }
- RINOK(WriteStream(outStream, _buffer, size));
- _nowPos64 += size;
- return S_OK;
}
STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{
- RINOK(Init());
- UInt32 bufferPos = 0;
- _outSizeIsDefined = (outSize != 0);
- if (_outSizeIsDefined)
- _outSize = *outSize;
+ RINOK(Init_and_Alloc());
+
+ UInt64 nowPos64 = 0;
+ bool inputFinished = false;
+ UInt32 pos = 0;
- while (!_outSizeIsDefined || _nowPos64 < _outSize)
+ while (!outSize || nowPos64 < *outSize)
{
- size_t processedSize = kBufferSize - bufferPos;
-
- // Change it: It can be optimized using ReadPart
- RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize));
+ UInt32 endPos = pos;
- UInt32 endPos = bufferPos + (UInt32)processedSize;
-
- bufferPos = Filter->Filter(_buffer, endPos);
- if (bufferPos > endPos)
+ if (!inputFinished)
{
- for (; endPos < bufferPos; endPos++)
- _buffer[endPos] = 0;
- bufferPos = Filter->Filter(_buffer, endPos);
+ size_t processedSize = _bufSize - pos;
+ RINOK(ReadStream(inStream, _buf + pos, &processedSize));
+ endPos = pos + (UInt32)processedSize;
+ inputFinished = (endPos != _bufSize);
}
- if (bufferPos == 0)
+ pos = Filter->Filter(_buf, endPos);
+
+ if (pos > endPos)
{
- if (endPos == 0)
- return S_OK;
- return WriteWithLimit(outStream, endPos);
+ // AES
+ if (!inputFinished || pos > _bufSize)
+ return E_FAIL;
+ if (!_encodeMode)
+ return S_FALSE;
+
+ do
+ _buf[endPos] = 0;
+ while (++endPos != pos);
+
+ if (pos != Filter->Filter(_buf, pos))
+ return E_FAIL;
}
- RINOK(WriteWithLimit(outStream, bufferPos));
- if (progress != NULL)
+
+ if (endPos == 0)
+ return S_OK;
+
+ UInt32 size = (pos != 0 ? pos : endPos);
+ if (outSize)
{
- RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
+ UInt64 remSize = *outSize - nowPos64;
+ if (size > remSize)
+ size = (UInt32)remSize;
}
+
+ RINOK(WriteStream(outStream, _buf, size));
+ nowPos64 += size;
+
+ if (pos == 0)
+ return S_OK;
+
+ if (progress)
+ RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
+
UInt32 i = 0;
- while (bufferPos < endPos)
- _buffer[i++] = _buffer[bufferPos++];
- bufferPos = i;
+ while (pos < endPos)
+ _buf[i++] = _buf[pos++];
+ pos = i;
}
+
return S_OK;
}
+
+
+// ---------- Write to Filter ----------
+
STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
{
- _bufferPos = 0;
_outStream = outStream;
- return Init();
+ return S_OK;
}
STDMETHODIMP CFilterCoder::ReleaseOutStream()
@@ -94,76 +148,154 @@ STDMETHODIMP CFilterCoder::ReleaseOutStream()
return S_OK;
}
+HRESULT CFilterCoder::Flush2()
+{
+ while (_convSize != 0)
+ {
+ UInt32 num = _convSize;
+ if (_outSizeIsDefined)
+ {
+ UInt64 rem = _outSize - _nowPos64;
+ if (num > rem)
+ num = (UInt32)rem;
+ if (num == 0)
+ return k_My_HRESULT_WritingWasCut;
+ }
+
+ UInt32 processed = 0;
+ HRESULT res = _outStream->Write(_buf + _convPos, num, &processed);
+ if (processed == 0)
+ return res != S_OK ? res : E_FAIL;
+
+ _convPos += processed;
+ _convSize -= processed;
+ _nowPos64 += processed;
+ RINOK(res);
+ }
+
+ if (_convPos != 0)
+ {
+ UInt32 num = _bufPos - _convPos;
+ for (UInt32 i = 0; i < num; i++)
+ _buf[i] = _buf[_convPos + i];
+ _bufPos = num;
+ _convPos = 0;
+ }
+
+ return S_OK;
+}
STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
- while (size > 0)
+
+ while (size != 0)
{
- UInt32 sizeTemp = MyMin(size, kBufferSize - _bufferPos);
- memcpy(_buffer + _bufferPos, data, sizeTemp);
- size -= sizeTemp;
- if (processedSize != NULL)
- *processedSize += sizeTemp;
- data = (const Byte *)data + sizeTemp;
- UInt32 endPos = _bufferPos + sizeTemp;
- _bufferPos = Filter->Filter(_buffer, endPos);
- if (_bufferPos == 0)
+ RINOK(Flush2());
+
+ // _convSize is 0
+ // _convPos is 0
+ // _bufPos is small
+
+ if (_bufPos != _bufSize)
{
- _bufferPos = endPos;
- break;
+ UInt32 num = MyMin(size, _bufSize - _bufPos);
+ memcpy(_buf + _bufPos, data, num);
+ size -= num;
+ data = (const Byte *)data + num;
+ if (processedSize)
+ *processedSize += num;
+ _bufPos += num;
+ if (_bufPos != _bufSize)
+ continue;
}
- if (_bufferPos > endPos)
- {
- if (size != 0)
- return E_FAIL;
+
+ // _bufPos == _bufSize
+ _convSize = Filter->Filter(_buf, _bufPos);
+
+ if (_convSize == 0)
break;
+ if (_convSize > _bufPos)
+ {
+ // that case is not possible.
+ _convSize = 0;
+ return E_FAIL;
}
- RINOK(WriteWithLimit(_outStream, _bufferPos));
- UInt32 i = 0;
- while (_bufferPos < endPos)
- _buffer[i++] = _buffer[_bufferPos++];
- _bufferPos = i;
}
+
return S_OK;
}
-STDMETHODIMP CFilterCoder::Flush()
+STDMETHODIMP CFilterCoder::OutStreamFinish()
{
- if (_bufferPos != 0)
+ for (;;)
{
- // _buffer contains only data refused by previous Filter->Filter call.
- UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
- if (endPos > _bufferPos)
+ RINOK(Flush2());
+ if (_bufPos == 0)
+ break;
+ _convSize = Filter->Filter(_buf, _bufPos);
+ if (_convSize == 0)
+ _convSize = _bufPos;
+ else if (_convSize > _bufPos)
{
- for (; _bufferPos < endPos; _bufferPos++)
- _buffer[_bufferPos] = 0;
- if (Filter->Filter(_buffer, endPos) != endPos)
+ // AES
+ if (_convSize > _bufSize)
+ {
+ _convSize = 0;
+ return E_FAIL;
+ }
+ if (!_encodeMode)
+ {
+ _convSize = 0;
+ return S_FALSE;
+ }
+ for (; _bufPos < _convSize; _bufPos++)
+ _buf[_bufPos] = 0;
+ _convSize = Filter->Filter(_buf, _bufPos);
+ if (_convSize != _bufPos)
return E_FAIL;
}
- RINOK(WriteWithLimit(_outStream, _bufferPos));
- _bufferPos = 0;
}
- CMyComPtr<IOutStreamFlush> flush;
- _outStream.QueryInterface(IID_IOutStreamFlush, &flush);
- if (flush)
- return flush->Flush();
+
+ CMyComPtr<IOutStreamFinish> finish;
+ _outStream.QueryInterface(IID_IOutStreamFinish, &finish);
+ if (finish)
+ return finish->OutStreamFinish();
return S_OK;
}
+// ---------- Init functions ----------
-void CFilterCoder::SetInStream_NoSubFilterInit(ISequentialInStream *inStream)
+STDMETHODIMP CFilterCoder::InitEncoder()
{
- _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
- _inStream = inStream;
- Init2();
+ InitSpecVars();
+ return Init_and_Alloc();
+}
+
+HRESULT CFilterCoder::Init_NoSubFilterInit()
+{
+ InitSpecVars();
+ return Alloc();
+}
+
+STDMETHODIMP CFilterCoder::SetOutStreamSize(const UInt64 *outSize)
+{
+ InitSpecVars();
+ if (outSize)
+ {
+ _outSize = *outSize;
+ _outSizeIsDefined = true;
+ }
+ return Init_and_Alloc();
}
+// ---------- Read from Filter ----------
+
STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
{
- SetInStream_NoSubFilterInit(inStream);
- return Init();
+ _inStream = inStream;
+ return S_OK;
}
STDMETHODIMP CFilterCoder::ReleaseInStream()
@@ -172,94 +304,115 @@ STDMETHODIMP CFilterCoder::ReleaseInStream()
return S_OK;
}
+
STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
- while (size > 0)
+
+ while (size != 0)
{
- if (_convertedPosBegin != _convertedPosEnd)
+ if (_convSize != 0)
{
- UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
- memcpy(data, _buffer + _convertedPosBegin, sizeTemp);
- _convertedPosBegin += sizeTemp;
- data = (void *)((Byte *)data + sizeTemp);
- size -= sizeTemp;
- if (processedSize != NULL)
- *processedSize += sizeTemp;
+ if (size > _convSize)
+ size = _convSize;
+ if (_outSizeIsDefined)
+ {
+ UInt64 rem = _outSize - _nowPos64;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ memcpy(data, _buf + _convPos, size);
+ _convPos += size;
+ _convSize -= size;
+ _nowPos64 += size;
+ if (processedSize)
+ *processedSize = size;
break;
}
- UInt32 i;
- for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
- _buffer[i] = _buffer[_convertedPosEnd + i];
- _bufferPos = i;
- _convertedPosBegin = _convertedPosEnd = 0;
- size_t processedSizeTemp = kBufferSize - _bufferPos;
- RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp));
- _bufferPos += (UInt32)processedSizeTemp;
- _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
- if (_convertedPosEnd == 0)
+
+ if (_convPos != 0)
+ {
+ UInt32 num = _bufPos - _convPos;
+ for (UInt32 i = 0; i < num; i++)
+ _buf[i] = _buf[_convPos + i];
+ _bufPos = num;
+ _convPos = 0;
+ }
+
+ {
+ size_t readSize = _bufSize - _bufPos;
+ HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize);
+ _bufPos += (UInt32)readSize;
+ RINOK(res);
+ }
+
+ _convSize = Filter->Filter(_buf, _bufPos);
+
+ if (_convSize == 0)
{
- if (_bufferPos == 0)
+ if (_bufPos == 0)
break;
- _convertedPosEnd = _bufferPos; // check it
+ // BCJ
+ _convSize = _bufPos;
continue;
}
- if (_convertedPosEnd > _bufferPos)
+
+ if (_convSize > _bufPos)
{
- for (; _bufferPos < _convertedPosEnd; _bufferPos++)
- _buffer[_bufferPos] = 0;
- _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
+ // AES
+ if (_convSize > _bufSize)
+ return E_FAIL;
+ if (!_encodeMode)
+ return S_FALSE;
+
+ do
+ _buf[_bufPos] = 0;
+ while (++_bufPos != _convSize);
+
+ _convSize = Filter->Filter(_buf, _convSize);
+ if (_convSize != _bufPos)
+ return E_FAIL;
}
}
+
return S_OK;
}
+
#ifndef _NO_CRYPTO
STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
-{
- return _setPassword->CryptoSetPassword(data, size);
-}
+ { return _SetPassword->CryptoSetPassword(data, size); }
STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size)
-{
- return _cryptoProperties->SetKey(data, size);
-}
+ { return _CryptoProperties->SetKey(data, size); }
STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size)
-{
- return _cryptoProperties->SetInitVector(data, size);
-}
+ { return _CryptoProperties->SetInitVector(data, size); }
#endif
+
#ifndef EXTRACT_ONLY
+
STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
- const PROPVARIANT *properties, UInt32 numProperties)
-{
- return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
-}
+ const PROPVARIANT *properties, UInt32 numProperties)
+ { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); }
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
-{
- return _writeCoderProperties->WriteCoderProperties(outStream);
-}
+ { return _WriteCoderProperties->WriteCoderProperties(outStream); }
/*
STDMETHODIMP CFilterCoder::ResetSalt()
-{
- return _CryptoResetSalt->ResetSalt();
-}
+ { return _CryptoResetSalt->ResetSalt(); }
*/
STDMETHODIMP CFilterCoder::ResetInitVector()
-{
- return _CryptoResetInitVector->ResetInitVector();
-}
+ { return _CryptoResetInitVector->ResetInitVector(); }
+
#endif
+
STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
-{
- return _setDecoderProperties->SetDecoderProperties2(data, size);
-}
+ { return _SetDecoderProperties2->SetDecoderProperties2(data, size); }
diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
index 2b8f142f..cde33c88 100644
--- a/CPP/7zip/Common/FilterCoder.h
+++ b/CPP/7zip/Common/FilterCoder.h
@@ -3,106 +3,204 @@
#ifndef __FILTER_CODER_H
#define __FILTER_CODER_H
+#include "../../../C/Alloc.h"
+
#include "../../Common/MyCom.h"
#include "../ICoder.h"
+
+#ifndef _NO_CRYPTO
#include "../IPassword.h"
+#endif
#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \
{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
*outObject = (void *)(i *)this; }
+
+struct CAlignedMidBuffer
+{
+ #ifndef _WIN32
+
+ Byte *_buf;
+
+ CAlignedMidBuffer(): _buf(NULL) {}
+ ~CAlignedMidBuffer() { ::MidFree(_buf); }
+
+ void AllocAlignedMask(size_t size, size_t)
+ {
+ ::MidFree(_buf);
+ _buf = (Byte *)::MidAlloc(size);
+ }
+
+ #else
+
+ Byte *_bufBase;
+ Byte *_buf;
+
+ CAlignedMidBuffer(): _bufBase(NULL), _buf(NULL) {}
+ ~CAlignedMidBuffer() { ::MidFree(_bufBase); }
+
+ void AllocAlignedMask(size_t size, size_t alignMask)
+ {
+ ::MidFree(_bufBase);
+ _buf = NULL;
+ _bufBase = (Byte *)::MidAlloc(size + alignMask);
+
+ if (_bufBase)
+ {
+ // _buf = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask);
+ _buf = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask);
+ }
+ }
+
+ #endif
+};
+
class CFilterCoder:
public ICompressCoder,
+
+ public ICompressSetOutStreamSize,
+ public ICompressInitEncoder,
+
public ICompressSetInStream,
public ISequentialInStream,
+
public ICompressSetOutStream,
public ISequentialOutStream,
- public IOutStreamFlush,
+ public IOutStreamFinish,
+
+ public ICompressSetBufSize,
#ifndef _NO_CRYPTO
public ICryptoSetPassword,
public ICryptoProperties,
#endif
+
#ifndef EXTRACT_ONLY
public ICompressSetCoderProperties,
public ICompressWriteCoderProperties,
// public ICryptoResetSalt,
public ICryptoResetInitVector,
#endif
+
public ICompressSetDecoderProperties2,
- public CMyUnknownImp
+ public CMyUnknownImp,
+ public CAlignedMidBuffer
{
-protected:
- Byte *_buffer;
- CMyComPtr<ISequentialInStream> _inStream;
- CMyComPtr<ISequentialOutStream> _outStream;
- UInt32 _bufferPos;
- UInt32 _convertedPosBegin;
- UInt32 _convertedPosEnd;
+ UInt32 _bufSize;
+ UInt32 _inBufSize;
+ UInt32 _outBufSize;
+
+ bool _encodeMode;
bool _outSizeIsDefined;
UInt64 _outSize;
UInt64 _nowPos64;
- void Init2()
+ CMyComPtr<ISequentialInStream> _inStream;
+ CMyComPtr<ISequentialOutStream> _outStream;
+ UInt32 _bufPos;
+ UInt32 _convPos; // current pos in buffer for converted data
+ UInt32 _convSize; // size of converted data starting from _convPos
+
+ void InitSpecVars()
{
- _nowPos64 = 0;
+ _bufPos = 0;
+ _convPos = 0;
+ _convSize = 0;
+
_outSizeIsDefined = false;
+ _outSize = 0;
+ _nowPos64 = 0;
}
- HRESULT Init()
- {
- Init2();
- return Filter->Init();
- }
+ HRESULT Alloc();
+ HRESULT Init_and_Alloc();
+ HRESULT Flush2();
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoSetPassword> _SetPassword;
+ CMyComPtr<ICryptoProperties> _CryptoProperties;
+ #endif
- CMyComPtr<ICryptoSetPassword> _setPassword;
- CMyComPtr<ICryptoProperties> _cryptoProperties;
#ifndef EXTRACT_ONLY
CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
- CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
+ CMyComPtr<ICompressWriteCoderProperties> _WriteCoderProperties;
// CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
#endif
- CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;
+
+ CMyComPtr<ICompressSetDecoderProperties2> _SetDecoderProperties2;
+
public:
CMyComPtr<ICompressFilter> Filter;
- CFilterCoder();
+ CFilterCoder(bool encodeMode);
~CFilterCoder();
- HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);
-public:
+ class C_InStream_Releaser
+ {
+ public:
+ CFilterCoder *FilterCoder;
+ C_InStream_Releaser(): FilterCoder(NULL) {}
+ ~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
+ };
+
+ class C_OutStream_Releaser
+ {
+ public:
+ CFilterCoder *FilterCoder;
+ C_OutStream_Releaser(): FilterCoder(NULL) {}
+ ~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
+ };
+
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
+
+ MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
+ MY_QUERYINTERFACE_ENTRY(ICompressInitEncoder)
+
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
+
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
- MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)
+ MY_QUERYINTERFACE_ENTRY(IOutStreamFinish)
+
+ MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
#ifndef _NO_CRYPTO
- MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)
- MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties)
+ MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _SetPassword)
+ MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _CryptoProperties)
#endif
#ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)
- MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
+ MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _WriteCoderProperties)
// MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
#endif
- MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)
+ MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _SetDecoderProperties2)
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
+
+
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
- STDMETHOD(ReleaseInStream)();
+
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+ STDMETHOD(InitEncoder)();
+
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \
+ STDMETHOD(ReleaseInStream)();
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
STDMETHOD(ReleaseOutStream)();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
- STDMETHOD(Flush)();
+ STDMETHOD(OutStreamFinish)();
+
+ STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
+ STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
#ifndef _NO_CRYPTO
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
@@ -110,6 +208,7 @@ public:
STDMETHOD(SetKey)(const Byte *data, UInt32 size);
STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);
#endif
+
#ifndef EXTRACT_ONLY
STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
const PROPVARIANT *properties, UInt32 numProperties);
@@ -117,26 +216,11 @@ public:
// STDMETHOD(ResetSalt)();
STDMETHOD(ResetInitVector)();
#endif
+
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
- void SetInStream_NoSubFilterInit(ISequentialInStream *inStream);
-
-};
-
-class CInStreamReleaser
-{
-public:
- CFilterCoder *FilterCoder;
- CInStreamReleaser(): FilterCoder(0) {}
- ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
-};
-
-class COutStreamReleaser
-{
-public:
- CFilterCoder *FilterCoder;
- COutStreamReleaser(): FilterCoder(0) {}
- ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
+
+ HRESULT Init_NoSubFilterInit();
};
#endif
diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp
index be65ba32..85d6a1aa 100644
--- a/CPP/7zip/Common/InOutTempBuffer.cpp
+++ b/CPP/7zip/Common/InOutTempBuffer.cpp
@@ -13,7 +13,7 @@ using namespace NWindows;
using namespace NFile;
using namespace NDir;
-static const UInt32 kTempBufSize = (1 << 20);
+static const size_t kTempBufSize = (1 << 20);
static CFSTR kTempFilePrefixString = FTEXT("7zt");
@@ -58,15 +58,19 @@ bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
bool CInOutTempBuffer::Write(const void *data, UInt32 size)
{
- if (_bufPos < kTempBufSize)
+ if (size == 0)
+ return true;
+ size_t cur = kTempBufSize - _bufPos;
+ if (cur != 0)
{
- UInt32 cur = MyMin(kTempBufSize - _bufPos, size);
+ if (cur > size)
+ cur = size;
memcpy(_buf + _bufPos, data, cur);
_crc = CrcUpdate(_crc, data, cur);
_bufPos += cur;
- size -= cur;
- data = ((const Byte *)data) + cur;
_size += cur;
+ size -= (UInt32)cur;
+ data = ((const Byte *)data) + cur;
}
return WriteToFile(data, size);
}
@@ -79,12 +83,13 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
UInt64 size = 0;
UInt32 crc = CRC_INIT_VAL;
- if (_bufPos > 0)
+ if (_bufPos != 0)
{
RINOK(WriteStream(stream, _buf, _bufPos));
crc = CrcUpdate(crc, _buf, _bufPos);
size += _bufPos;
}
+
if (_tempFileCreated)
{
NIO::CInFile inFile;
@@ -102,18 +107,21 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
size += processed;
}
}
+
return (_crc == crc && size == _size) ? S_OK : E_FAIL;
}
+/*
STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed)
{
if (!_buf->Write(data, size))
{
- if (processed != NULL)
+ if (processed)
*processed = 0;
return E_FAIL;
}
- if (processed != NULL)
+ if (processed)
*processed = size;
return S_OK;
}
+*/
diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h
index 256d7242..204a105f 100644
--- a/CPP/7zip/Common/InOutTempBuffer.h
+++ b/CPP/7zip/Common/InOutTempBuffer.h
@@ -13,10 +13,10 @@ class CInOutTempBuffer
NWindows::NFile::NDir::CTempFile _tempFile;
NWindows::NFile::NIO::COutFile _outFile;
Byte *_buf;
- UInt32 _bufPos;
- bool _tempFileCreated;
+ size_t _bufPos;
UInt64 _size;
UInt32 _crc;
+ bool _tempFileCreated;
bool WriteToFile(const void *data, UInt32 size);
public:
@@ -31,6 +31,7 @@ public:
UInt64 GetDataSize() const { return _size; }
};
+/*
class CSequentialOutTempBufferImp:
public ISequentialOutStream,
public CMyUnknownImp
@@ -42,5 +43,6 @@ public:
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
+*/
#endif
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
index de236040..2ea718e7 100644
--- a/CPP/7zip/Common/LimitedStreams.cpp
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -279,7 +279,10 @@ STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *proce
if (newPos >= _cachePhyPos &&
offsetInCache <= _cacheSize &&
size <= _cacheSize - (size_t)offsetInCache)
- memcpy(data, _cache + (size_t)offsetInCache, size);
+ {
+ if (size != 0)
+ memcpy(data, _cache + (size_t)offsetInCache, size);
+ }
else
{
if (newPos != _physPos)
diff --git a/CPP/7zip/Common/LockedStream.cpp b/CPP/7zip/Common/LockedStream.cpp
index f05601cb..ca39fb45 100644
--- a/CPP/7zip/Common/LockedStream.cpp
+++ b/CPP/7zip/Common/LockedStream.cpp
@@ -1,23 +1,3 @@
// LockedStream.cpp
#include "StdAfx.h"
-
-#include "LockedStream.h"
-
-HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size,
- UInt32 *processedSize)
-{
- NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
- RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL));
- return _stream->Read(data, size, processedSize);
-}
-
-STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize)
-{
- UInt32 realProcessedSize = 0;
- HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize);
- _pos += realProcessedSize;
- if (processedSize != NULL)
- *processedSize = realProcessedSize;
- return result;
-}
diff --git a/CPP/7zip/Common/LockedStream.h b/CPP/7zip/Common/LockedStream.h
index 486e4220..efebf197 100644
--- a/CPP/7zip/Common/LockedStream.h
+++ b/CPP/7zip/Common/LockedStream.h
@@ -1,38 +1,6 @@
// LockedStream.h
-#ifndef __LOCKEDSTREAM_H
-#define __LOCKEDSTREAM_H
-
-#include "../../Windows/Synchronization.h"
-#include "../../Common/MyCom.h"
-#include "../IStream.h"
-
-class CLockedInStream
-{
- CMyComPtr<IInStream> _stream;
- NWindows::NSynchronization::CCriticalSection _criticalSection;
-public:
- void Init(IInStream *stream)
- { _stream = stream; }
- HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize);
-};
-
-class CLockedSequentialInStreamImp:
- public ISequentialInStream,
- public CMyUnknownImp
-{
- CLockedInStream *_lockedInStream;
- UInt64 _pos;
-public:
- void Init(CLockedInStream *lockedInStream, UInt64 startPos)
- {
- _lockedInStream = lockedInStream;
- _pos = startPos;
- }
-
- MY_UNKNOWN_IMP
-
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
-};
+#ifndef __LOCKED_STREAM_H
+#define __LOCKED_STREAM_H
#endif
diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
index f1c34ada..7c1e9979 100644
--- a/CPP/7zip/Common/MethodProps.cpp
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -10,12 +10,12 @@ using namespace NWindows;
bool StringToBool(const UString &s, bool &res)
{
- if (s.IsEmpty() || s == L"+" || StringsAreEqualNoCase_Ascii(s, "ON"))
+ if (s.IsEmpty() || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON"))
{
res = true;
return true;
}
- if (s == L"-" || StringsAreEqualNoCase_Ascii(s, "OFF"))
+ if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF"))
{
res = false;
return true;
@@ -137,11 +137,10 @@ static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, UInt32 &resValue
void CProps::AddProp32(PROPID propid, UInt32 level)
{
- CProp prop;
+ CProp &prop = Props.AddNew();
prop.IsOptional = true;
prop.Id = propid;
prop.Value = (UInt32)level;
- Props.Add(prop);
}
class CCoderProps
@@ -331,7 +330,7 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
int index = FindPropIdExact(name);
if (index < 0)
return E_INVALIDARG;
- const CNameToPropID &nameToPropID = g_NameToPropID[index];
+ const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
CProp prop;
prop.Id = index;
@@ -401,7 +400,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const
int index = FindPropIdExact(realName);
if (index < 0)
return E_INVALIDARG;
- const CNameToPropID &nameToPropID = g_NameToPropID[index];
+ const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
CProp prop;
prop.Id = index;
@@ -422,12 +421,20 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const
HRESULT COneMethodInfo::ParseMethodFromString(const UString &s)
{
- int splitPos = s.Find(':');
- MethodName = s;
+ MethodName.Empty();
+ int splitPos = s.Find(L':');
+ {
+ UString temp = s;
+ if (splitPos >= 0)
+ temp.DeleteFrom(splitPos);
+ if (!temp.IsAscii())
+ return E_INVALIDARG;
+ MethodName.SetFromWStr_if_Ascii(temp);
+ }
if (splitPos < 0)
return S_OK;
- MethodName.DeleteFrom(splitPos);
- return ParseParamsFromString(s.Ptr(splitPos + 1));
+ PropsString = s.Ptr(splitPos + 1);
+ return ParseParamsFromString(PropsString);
}
HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h
index 18672bde..765e425d 100644
--- a/CPP/7zip/Common/MethodProps.h
+++ b/CPP/7zip/Common/MethodProps.h
@@ -40,13 +40,12 @@ struct CProps
void AddProp32(PROPID propid, UInt32 level);
- void AddPropString(PROPID propid, const wchar_t *s)
+ void AddProp_Ascii(PROPID propid, const char *s)
{
- CProp prop;
+ CProp &prop = Props.AddNew();
prop.IsOptional = true;
prop.Id = propid;
prop.Value = s;
- Props.Add(prop);
}
HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const;
@@ -100,6 +99,14 @@ public:
return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26));
}
+ bool Are_Lzma_Model_Props_Defined() const
+ {
+ if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true;
+ if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true;
+ if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true;
+ return false;
+ }
+
UInt32 Get_Lzma_NumThreads(bool &fixedNumber) const
{
fixedNumber = false;
@@ -153,12 +160,12 @@ public:
return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19));
}
- void AddLevelProp(UInt32 level)
+ void AddProp_Level(UInt32 level)
{
AddProp32(NCoderPropID::kLevel, level);
}
- void AddNumThreadsProp(UInt32 numThreads)
+ void AddProp_NumThreads(UInt32 numThreads)
{
AddProp32(NCoderPropID::kNumThreads, numThreads);
}
@@ -170,12 +177,14 @@ public:
class COneMethodInfo: public CMethodProps
{
public:
- UString MethodName;
+ AString MethodName;
+ UString PropsString;
void Clear()
{
CMethodProps::Clear();
MethodName.Empty();
+ PropsString.Empty();
}
bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); }
HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
diff --git a/CPP/7zip/Common/ProgressUtils.cpp b/CPP/7zip/Common/ProgressUtils.cpp
index bac45c1c..41385ccb 100644
--- a/CPP/7zip/Common/ProgressUtils.cpp
+++ b/CPP/7zip/Common/ProgressUtils.cpp
@@ -4,11 +4,13 @@
#include "ProgressUtils.h"
-CLocalProgress::CLocalProgress()
-{
- ProgressOffset = InSize = OutSize = 0;
- SendRatio = SendProgress = true;
-}
+CLocalProgress::CLocalProgress():
+ ProgressOffset(0),
+ InSize(0),
+ OutSize(0),
+ SendRatio(true),
+ SendProgress(true)
+ {}
void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
{
@@ -20,19 +22,26 @@ void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
- UInt64 inSizeNew = InSize, outSizeNew = OutSize;
+ UInt64 inSize2 = InSize;
+ UInt64 outSize2 = OutSize;
+
if (inSize)
- inSizeNew += (*inSize);
+ inSize2 += (*inSize);
if (outSize)
- outSizeNew += (*outSize);
+ outSize2 += (*outSize);
+
if (SendRatio && _ratioProgress)
{
- RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew));
+ RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2));
}
- inSizeNew += ProgressOffset;
- outSizeNew += ProgressOffset;
+
if (SendProgress)
- return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew);
+ {
+ inSize2 += ProgressOffset;
+ outSize2 += ProgressOffset;
+ return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2);
+ }
+
return S_OK;
}
diff --git a/CPP/7zip/Common/ProgressUtils.h b/CPP/7zip/Common/ProgressUtils.h
index bae5395c..e94265ba 100644
--- a/CPP/7zip/Common/ProgressUtils.h
+++ b/CPP/7zip/Common/ProgressUtils.h
@@ -1,7 +1,7 @@
// ProgressUtils.h
-#ifndef __PROGRESSUTILS_H
-#define __PROGRESSUTILS_H
+#ifndef __PROGRESS_UTILS_H
+#define __PROGRESS_UTILS_H
#include "../../Common/MyCom.h"
@@ -23,10 +23,11 @@ public:
bool SendProgress;
CLocalProgress();
+
void Init(IProgress *progress, bool inSizeIsMain);
HRESULT SetCur();
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp
index 10daef71..2ce6fd85 100644
--- a/CPP/7zip/Common/PropId.cpp
+++ b/CPP/7zip/Common/PropId.cpp
@@ -5,7 +5,7 @@
#include "../PropID.h"
// VARTYPE
-Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
+const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
{
VT_EMPTY,
VT_UI4,
@@ -95,5 +95,11 @@ Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
VT_BOOL,
VT_BOOL,
VT_UI8,
- VT_UI8
+ VT_UI8,
+ VT_BSTR, // kpidNtReparse
+ VT_BSTR,
+ VT_UI8,
+ VT_UI8,
+ VT_BOOL,
+ VT_BSTR // kpidOutName
};
diff --git a/CPP/7zip/Common/RegisterArc.h b/CPP/7zip/Common/RegisterArc.h
index edc3abdd..3421ba1b 100644
--- a/CPP/7zip/Common/RegisterArc.h
+++ b/CPP/7zip/Common/RegisterArc.h
@@ -7,18 +7,16 @@
struct CArcInfo
{
+ UInt16 Flags;
+ Byte Id;
+ Byte SignatureSize;
+ UInt16 SignatureOffset;
+
+ const Byte *Signature;
const char *Name;
const char *Ext;
const char *AddExt;
- Byte ClassId;
-
- Byte SignatureSize;
- Byte Signature[20];
- UInt16 SignatureOffset;
-
- UInt16 Flags;
-
Func_CreateInArchive CreateInArchive;
Func_CreateOutArchive CreateOutArchive;
Func_IsArc IsArc;
@@ -28,28 +26,53 @@ struct CArcInfo
void RegisterArc(const CArcInfo *arcInfo) throw();
-#define REGISTER_ARC_NAME(x) CRegister ## x
-
-#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \
- REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \
- static REGISTER_ARC_NAME(x) g_RegisterArc;
-
-#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \
- REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \
- static REGISTER_ARC_NAME(x) g_RegisterArc;
-
#define IMP_CreateArcIn_2(c) \
static IInArchive *CreateArc() { return new c; }
-#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler)
+#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler())
#ifdef EXTRACT_ONLY
#define IMP_CreateArcOut
- #define REF_CreateArc_Pair CreateArc, NULL
+ #define CreateArcOut NULL
#else
- #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler; }
- #define REF_CreateArc_Pair CreateArc, CreateArcOut
+ #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); }
#endif
+#define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
+ static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, crIn, crOut, isArc } ; \
+
+#define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
+ REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \
+ struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \
+ static CRegisterArc g_RegisterArc;
+
+
+#define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \
+ IMP_CreateArcIn_2(cls) \
+ REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, NULL, isArc)
+
+#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \
+ IMP_CreateArcIn_2(cls) \
+ REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, CreateArc, NULL, isArc)
+
+#define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \
+ REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc)
+
+#define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \
+ REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc)
+
+
+#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, isArc) \
+ IMP_CreateArcIn \
+ IMP_CreateArcOut \
+ REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc)
+
+#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, isArc) \
+ IMP_CreateArcIn \
+ IMP_CreateArcOut \
+ REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) \
+ struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \
+ static CRegisterArcDecSig g_RegisterArc;
+
#endif
diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h
index 4222a305..7ddb7604 100644
--- a/CPP/7zip/Common/RegisterCodec.h
+++ b/CPP/7zip/Common/RegisterCodec.h
@@ -4,48 +4,103 @@
#define __REGISTER_CODEC_H
#include "../Common/MethodId.h"
+
#include "../ICoder.h"
typedef void * (*CreateCodecP)();
+
struct CCodecInfo
{
CreateCodecP CreateDecoder;
CreateCodecP CreateEncoder;
CMethodId Id;
- const wchar_t *Name;
- UInt32 NumInStreams;
+ const char *Name;
+ UInt32 NumStreams;
bool IsFilter;
};
void RegisterCodec(const CCodecInfo *codecInfo) throw();
+
+#define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); }
+#define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder)
+
#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x
+#define REGISTER_CODEC_VAR static const CCodecInfo g_CodecInfo =
#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \
REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \
static REGISTER_CODEC_NAME(x) g_RegisterCodec;
+
#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x
+#define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] =
+
#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \
REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \
RegisterCodec(&g_CodecsInfo[i]); }}; \
static REGISTER_CODECS_NAME(x) g_RegisterCodecs;
+#define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \
+ REGISTER_CODEC_VAR \
+ { crDec, crEnc, id, name, 1, false }; \
+ REGISTER_CODEC(x)
+
+
+#ifdef EXTRACT_ONLY
+ #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \
+ REGISTER_CODEC_CREATE(CreateDec, clsDec) \
+ REGISTER_CODEC_2(x, CreateDec, NULL, id, name)
+#else
+ #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \
+ REGISTER_CODEC_CREATE(CreateDec, clsDec) \
+ REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \
+ REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name)
+#endif
+
+
+
+#define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter)
+
+#define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \
+ { crDec, crEnc, id, name, 1, true }
+
+#define REGISTER_FILTER(x, crDec, crEnc, id, name) \
+ REGISTER_CODEC_VAR \
+ REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \
+ REGISTER_CODEC(x)
+
+#ifdef EXTRACT_ONLY
+ #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \
+ REGISTER_FILTER_CREATE(CreateDec, clsDec) \
+ REGISTER_FILTER(x, CreateDec, NULL, id, name)
+#else
+ #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \
+ REGISTER_FILTER_CREATE(CreateDec, clsDec) \
+ REGISTER_FILTER_CREATE(CreateEnc, clsEnc) \
+ REGISTER_FILTER(x, CreateDec, CreateEnc, id, name)
+#endif
+
+
+
struct CHasherInfo
{
IHasher * (*CreateHasher)();
CMethodId Id;
- const wchar_t *Name;
+ const char *Name;
UInt32 DigestSize;
};
void RegisterHasher(const CHasherInfo *hasher) throw();
-#define REGISTER_HASHER_NAME(x) CRegisterHasher ## x
+#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x
-#define REGISTER_HASHER(x) struct REGISTER_HASHER_NAME(x) { \
- REGISTER_HASHER_NAME(x)() { RegisterHasher(&g_HasherInfo); }}; \
- static REGISTER_HASHER_NAME(x) g_RegisterHasher;
+#define REGISTER_HASHER(cls, id, name, size) \
+ STDMETHODIMP_(UInt32) cls::GetDigestSize() throw() { return size; } \
+ static IHasher *CreateHasherSpec() { return new cls(); } \
+ static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \
+ struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \
+ static REGISTER_HASHER_NAME(cls) g_RegisterHasher;
#endif
diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp
index 7a4c0ed2..435440c6 100644
--- a/CPP/7zip/Common/StreamBinder.cpp
+++ b/CPP/7zip/Common/StreamBinder.cpp
@@ -12,7 +12,7 @@ class CBinderInStream:
{
CStreamBinder *_binder;
public:
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(ISequentialInStream)
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
~CBinderInStream() { _binder->CloseRead(); }
CBinderInStream(CStreamBinder *binder): _binder(binder) {}
@@ -27,7 +27,7 @@ class CBinderOutStream:
{
CStreamBinder *_binder;
public:
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
~CBinderOutStream() { _binder->CloseWrite(); }
CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
@@ -40,26 +40,38 @@ STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
WRes CStreamBinder::CreateEvents()
{
- RINOK(_canWrite_Event.Create(true));
+ RINOK(_canWrite_Event.Create());
RINOK(_canRead_Event.Create());
return _readingWasClosed_Event.Create();
}
void CStreamBinder::ReInit()
{
- _waitWrite = true;
+ _canWrite_Event.Reset();
_canRead_Event.Reset();
_readingWasClosed_Event.Reset();
+
+ // _readingWasClosed = false;
+ _readingWasClosed2 = false;
+
+ _waitWrite = true;
+ _bufSize = 0;
+ _buf = NULL;
ProcessedSize = 0;
+ // WritingWasCut = false;
}
void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream)
{
+ // _readingWasClosed = false;
+ _readingWasClosed2 = false;
+
_waitWrite = true;
_bufSize = 0;
_buf = NULL;
ProcessedSize = 0;
+ // WritingWasCut = false;
CBinderInStream *inStreamSpec = new CBinderInStream(this);
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
@@ -108,19 +120,37 @@ HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSiz
{
if (processedSize)
*processedSize = 0;
- if (size != 0)
+ if (size == 0)
+ return S_OK;
+
+ if (!_readingWasClosed2)
{
_buf = data;
_bufSize = size;
- _canWrite_Event.Reset();
_canRead_Event.Set();
+
+ /*
+ _canWrite_Event.Lock();
+ if (_readingWasClosed)
+ _readingWasClosed2 = true;
+ */
HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event };
DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
- if (waitResult != WAIT_OBJECT_0 + 0)
- return S_FALSE;
- if (processedSize)
- *processedSize = size;
+ if (waitResult >= WAIT_OBJECT_0 + 2)
+ return E_FAIL;
+
+ size -= _bufSize;
+ if (size != 0)
+ {
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ }
+ // if (waitResult == WAIT_OBJECT_0 + 1)
+ _readingWasClosed2 = true;
}
- return S_OK;
+
+ // WritingWasCut = true;
+ return k_My_HRESULT_WritingWasCut;
}
diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h
index f3fb5322..12088a94 100644
--- a/CPP/7zip/Common/StreamBinder.h
+++ b/CPP/7zip/Common/StreamBinder.h
@@ -7,11 +7,27 @@
#include "../IStream.h"
+/*
+We don't use probably UNSAFE version:
+reader thread:
+ _canWrite_Event.Set();
+ _readingWasClosed = true
+ _canWrite_Event.Set();
+writer thread:
+ _canWrite_Event.Wait()
+ if (_readingWasClosed)
+Can second call of _canWrite_Event.Set() be executed without memory barrier, if event is already set?
+*/
+
class CStreamBinder
{
- NWindows::NSynchronization::CManualResetEvent _canWrite_Event;
+ NWindows::NSynchronization::CAutoResetEvent _canWrite_Event;
NWindows::NSynchronization::CManualResetEvent _canRead_Event;
NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event;
+
+ // bool _readingWasClosed;
+ bool _readingWasClosed2;
+ // bool WritingWasCut;
bool _waitWrite;
UInt32 _bufSize;
const void *_buf;
@@ -20,13 +36,23 @@ public:
WRes CreateEvents();
void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream);
+
void ReInit();
+
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);
- void CloseRead() { _readingWasClosed_Event.Set(); }
+
+ void CloseRead()
+ {
+ _readingWasClosed_Event.Set();
+ // _readingWasClosed = true;
+ // _canWrite_Event.Set();
+ }
+
void CloseWrite()
{
- // _bufSize must be = 0
+ _buf = NULL;
+ _bufSize = 0;
_canRead_Event.Set();
}
};
diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp
index 817017ab..8136716d 100644
--- a/CPP/7zip/Common/StreamObjects.cpp
+++ b/CPP/7zip/Common/StreamObjects.cpp
@@ -8,6 +8,41 @@
#include "StreamObjects.h"
+STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ if (_pos >= Buf.Size())
+ return S_OK;
+ size_t rem = Buf.Size() - (size_t)_pos;
+ if (rem > size)
+ rem = (size_t)size;
+ memcpy(data, (const Byte *)Buf + (size_t)_pos, rem);
+ _pos += rem;
+ if (processedSize)
+ *processedSize = (UInt32)rem;
+ return S_OK;
+}
+
+STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ switch (seekOrigin)
+ {
+ case STREAM_SEEK_SET: break;
+ case STREAM_SEEK_CUR: offset += _pos; break;
+ case STREAM_SEEK_END: offset += Buf.Size(); break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _pos = offset;
+ if (newPosition)
+ *newPosition = offset;
+ return S_OK;
+}
+
STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
@@ -43,25 +78,22 @@ STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi
return S_OK;
}
-/*
-void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream)
+void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream)
{
+ *stream = NULL;
CBufInStream *inStreamSpec = new CBufInStream;
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
- inStreamSpec->Init((const Byte *)data, size);
+ inStreamSpec->Init((const Byte *)data, size, ref);
*stream = streamTemp.Detach();
}
-*/
-void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream)
+void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream)
{
- CReferenceBuf *referenceBuf = new CReferenceBuf;
- CMyComPtr<IUnknown> ref = referenceBuf;
- referenceBuf->Buf.CopyFrom((const Byte *)data, size);
-
- CBufInStream *inStreamSpec = new CBufInStream;
+ *stream = NULL;
+ CBufferInStream *inStreamSpec = new CBufferInStream;
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
- inStreamSpec->Init(referenceBuf);
+ inStreamSpec->Buf.CopyFrom((const Byte *)data, size);
+ inStreamSpec->Init();
*stream = streamTemp.Detach();
}
@@ -128,8 +160,11 @@ STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *p
size_t rem = _size - _pos;
if (rem > size)
rem = (size_t)size;
- memcpy(_buffer + _pos, data, rem);
- _pos += rem;
+ if (rem != 0)
+ {
+ memcpy(_buffer + _pos, data, rem);
+ _pos += rem;
+ }
if (processedSize)
*processedSize = (UInt32)rem;
return (rem != 0 || size == 0) ? S_OK : E_FAIL;
diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h
index d0c86b56..e20e9bd8 100644
--- a/CPP/7zip/Common/StreamObjects.h
+++ b/CPP/7zip/Common/StreamObjects.h
@@ -9,6 +9,21 @@
#include "../IStream.h"
+class CBufferInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ UInt64 _pos;
+public:
+ CByteBuffer Buf;
+ void Init() { _pos = 0; }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
struct CReferenceBuf:
public IUnknown,
public CMyUnknownImp
@@ -40,8 +55,10 @@ public:
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};
-// void Create_BufInStream_WithReference(const void *data, size_t size, ISequentialInStream **stream);
-void Create_BufInStream_WithNewBuf(const void *data, size_t size, ISequentialInStream **stream);
+void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream);
+void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream);
+inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream)
+ { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); }
class CByteDynBuffer
{
@@ -53,8 +70,8 @@ public:
~CByteDynBuffer() { Free(); }
void Free() throw();
size_t GetCapacity() const { return _capacity; }
- operator Byte*() const { return _buf; };
- operator const Byte*() const { return _buf; };
+ operator Byte*() const { return _buf; }
+ operator const Byte*() const { return _buf; }
bool EnsureCapacity(size_t capacity) throw();
};
diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp
index 7fcc88f5..a2cacdde 100644
--- a/CPP/7zip/Common/UniqBlocks.cpp
+++ b/CPP/7zip/Common/UniqBlocks.cpp
@@ -4,13 +4,13 @@
#include "UniqBlocks.h"
-int CUniqBlocks::AddUniq(const Byte *data, size_t size)
+unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
{
unsigned left = 0, right = Sorted.Size();
while (left != right)
{
unsigned mid = (left + right) / 2;
- int index = Sorted[mid];
+ unsigned index = Sorted[mid];
const CByteBuffer &buf = Bufs[index];
size_t sizeMid = buf.Size();
if (size < sizeMid)
@@ -19,6 +19,8 @@ int CUniqBlocks::AddUniq(const Byte *data, size_t size)
left = mid + 1;
else
{
+ if (size == 0)
+ return index;
int cmp = memcmp(data, buf, size);
if (cmp == 0)
return index;
@@ -28,10 +30,9 @@ int CUniqBlocks::AddUniq(const Byte *data, size_t size)
left = mid + 1;
}
}
- int index = Bufs.Size();
+ unsigned index = Bufs.Size();
Sorted.Insert(left, index);
- CByteBuffer &buf = Bufs.AddNew();
- buf.CopyFrom(data, size);
+ Bufs.AddNew().CopyFrom(data, size);
return index;
}
@@ -47,10 +48,8 @@ void CUniqBlocks::GetReverseMap()
{
unsigned num = Sorted.Size();
BufIndexToSortedIndex.ClearAndSetSize(num);
- int *p = &BufIndexToSortedIndex[0];
- unsigned i;
- for (i = 0; i < num; i++)
- p[i] = 0;
- for (i = 0; i < num; i++)
- p[Sorted[i]] = i;
+ unsigned *p = &BufIndexToSortedIndex[0];
+ const unsigned *sorted = &Sorted[0];
+ for (unsigned i = 0; i < num; i++)
+ p[sorted[i]] = i;
}
diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h
index 9c08b09f..a376024e 100644
--- a/CPP/7zip/Common/UniqBlocks.h
+++ b/CPP/7zip/Common/UniqBlocks.h
@@ -10,20 +10,16 @@
struct CUniqBlocks
{
CObjectVector<CByteBuffer> Bufs;
- CIntVector Sorted;
- CIntVector BufIndexToSortedIndex;
+ CUIntVector Sorted;
+ CUIntVector BufIndexToSortedIndex;
- int AddUniq(const Byte *data, size_t size);
+ unsigned AddUniq(const Byte *data, size_t size);
UInt64 GetTotalSizeInBytes() const;
void GetReverseMap();
bool IsOnlyEmpty() const
{
- if (Bufs.Size() == 0)
- return true;
- if (Bufs.Size() > 1)
- return false;
- return Bufs[0].Size() == 0;
+ return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0);
}
};
diff --git a/CPP/7zip/Compress/ArjDecoder1.cpp b/CPP/7zip/Compress/ArjDecoder1.cpp
deleted file mode 100644
index 2eaa591c..00000000
--- a/CPP/7zip/Compress/ArjDecoder1.cpp
+++ /dev/null
@@ -1,309 +0,0 @@
-// ArjDecoder1.cpp
-
-#include "StdAfx.h"
-
-#include "ArjDecoder1.h"
-
-namespace NCompress{
-namespace NArj {
-namespace NDecoder1 {
-
-static const UInt32 kHistorySize = 26624;
-static const UInt32 kMatchMinLen = 3;
-static const UInt32 kMatchMaxLen = 256;
-
-// static const UInt32 kNC = 255 + kMatchMaxLen + 2 - kMatchMinLen;
-
-void CCoder::MakeTable(int nchar, Byte *bitlen, int tablebits,
- UInt32 *table, int tablesize)
-{
- UInt32 count[17], weight[17], start[18], *p;
- UInt32 i, k, len, ch, jutbits, avail, nextcode, mask;
-
- for (i = 1; i <= 16; i++)
- count[i] = 0;
- for (i = 0; (int)i < nchar; i++)
- count[bitlen[i]]++;
-
- start[1] = 0;
- for (i = 1; i <= 16; i++)
- start[i + 1] = start[i] + (count[i] << (16 - i));
- if (start[17] != (UInt32) (1 << 16))
- throw "Data error";
-
- jutbits = 16 - tablebits;
- for (i = 1; (int)i <= tablebits; i++)
- {
- start[i] >>= jutbits;
- weight[i] = 1 << (tablebits - i);
- }
- while (i <= 16)
- {
- weight[i] = 1 << (16 - i);
- i++;
- }
-
- i = start[tablebits + 1] >> jutbits;
- if (i != (UInt32) (1 << 16))
- {
- k = 1 << tablebits;
- while (i != k)
- table[i++] = 0;
- }
-
- avail = nchar;
- mask = 1 << (15 - tablebits);
- for (ch = 0; (int)ch < nchar; ch++)
- {
- if ((len = bitlen[ch]) == 0)
- continue;
- k = start[len];
- nextcode = k + weight[len];
- if ((int)len <= tablebits)
- {
- if (nextcode > (UInt32)tablesize)
- throw "Data error";
- for (i = start[len]; i < nextcode; i++)
- table[i] = ch;
- }
- else
- {
- p = &table[k >> jutbits];
- i = len - tablebits;
- while (i != 0)
- {
- if (*p == 0)
- {
- right[avail] = left[avail] = 0;
- *p = avail++;
- }
- if (k & mask)
- p = &right[*p];
- else
- p = &left[*p];
- k <<= 1;
- i--;
- }
- *p = ch;
- }
- start[len] = nextcode;
- }
-}
-
-void CCoder::read_pt_len(int nn, int nbit, int i_special)
-{
- UInt32 n = m_InBitStream.ReadBits(nbit);
- if (n == 0)
- {
- UInt32 c = m_InBitStream.ReadBits(nbit);
- int i;
- for (i = 0; i < nn; i++)
- pt_len[i] = 0;
- for (i = 0; i < 256; i++)
- pt_table[i] = c;
- }
- else
- {
- UInt32 i = 0;
- while (i < n)
- {
- UInt32 bitBuf = m_InBitStream.GetValue(16);
- int c = bitBuf >> 13;
- if (c == 7)
- {
- UInt32 mask = 1 << (12);
- while (mask & bitBuf)
- {
- mask >>= 1;
- c++;
- }
- }
- m_InBitStream.MovePos((c < 7) ? 3 : (int)(c - 3));
- pt_len[i++] = (Byte)c;
- if (i == (UInt32)i_special)
- {
- c = m_InBitStream.ReadBits(2);
- while (--c >= 0)
- pt_len[i++] = 0;
- }
- }
- while (i < (UInt32)nn)
- pt_len[i++] = 0;
- MakeTable(nn, pt_len, 8, pt_table, PTABLESIZE);
- }
-}
-
-void CCoder::read_c_len()
-{
- int i, c, n;
- UInt32 mask;
-
- n = m_InBitStream.ReadBits(CBIT);
- if (n == 0)
- {
- c = m_InBitStream.ReadBits(CBIT);
- for (i = 0; i < NC; i++)
- c_len[i] = 0;
- for (i = 0; i < CTABLESIZE; i++)
- c_table[i] = c;
- }
- else
- {
- i = 0;
- while (i < n)
- {
- UInt32 bitBuf = m_InBitStream.GetValue(16);
- c = pt_table[bitBuf >> (8)];
- if (c >= NT)
- {
- mask = 1 << (7);
- do
- {
- if (bitBuf & mask)
- c = right[c];
- else
- c = left[c];
- mask >>= 1;
- } while (c >= NT);
- }
- m_InBitStream.MovePos((int)(pt_len[c]));
- if (c <= 2)
- {
- if (c == 0)
- c = 1;
- else if (c == 1)
- c = m_InBitStream.ReadBits(4) + 3;
- else
- c = m_InBitStream.ReadBits(CBIT) + 20;
- while (--c >= 0)
- c_len[i++] = 0;
- }
- else
- c_len[i++] = (Byte)(c - 2);
- }
- while (i < NC)
- c_len[i++] = 0;
- MakeTable(NC, c_len, 12, c_table, CTABLESIZE);
- }
-}
-
-UInt32 CCoder::decode_c()
-{
- UInt32 j, mask;
- UInt32 bitbuf = m_InBitStream.GetValue(16);
- j = c_table[bitbuf >> 4];
- if (j >= NC)
- {
- mask = 1 << (3);
- do
- {
- if (bitbuf & mask)
- j = right[j];
- else
- j = left[j];
- mask >>= 1;
- } while (j >= NC);
- }
- m_InBitStream.MovePos((int)(c_len[j]));
- return j;
-}
-
-UInt32 CCoder::decode_p()
-{
- UInt32 j, mask;
- UInt32 bitbuf = m_InBitStream.GetValue(16);
- j = pt_table[bitbuf >> (8)];
- if (j >= NP)
- {
- mask = 1 << (7);
- do
- {
- if (bitbuf & mask)
- j = right[j];
- else
- j = left[j];
- mask >>= 1;
- } while (j >= NP);
- }
- m_InBitStream.MovePos((int)(pt_len[j]));
- if (j != 0)
- {
- j--;
- j = (1 << j) + m_InBitStream.ReadBits((int)j);
- }
- return j;
-}
-
-
-HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
-{
- if (outSize == NULL)
- return E_INVALIDARG;
-
- if (!m_OutWindowStream.Create(kHistorySize))
- return E_OUTOFMEMORY;
- if (!m_InBitStream.Create(1 << 20))
- return E_OUTOFMEMORY;
-
- // check it
- for (int i = 0; i < CTABLESIZE; i++)
- c_table[i] = 0;
-
- UInt64 pos = 0;
- m_OutWindowStream.SetStream(outStream);
- m_OutWindowStream.Init(false);
- m_InBitStream.SetStream(inStream);
- m_InBitStream.Init();
-
- CCoderReleaser coderReleaser(this);
-
- UInt32 blockSize = 0;
-
- while (pos < *outSize)
- {
- if (blockSize == 0)
- {
- if (progress != NULL)
- {
- UInt64 packSize = m_InBitStream.GetProcessedSize();
- RINOK(progress->SetRatioInfo(&packSize, &pos));
- }
- blockSize = m_InBitStream.ReadBits(16);
- read_pt_len(NT, TBIT, 3);
- read_c_len();
- read_pt_len(NP, PBIT, -1);
- }
- blockSize--;
-
- UInt32 number = decode_c();
- if (number < 256)
- {
- m_OutWindowStream.PutByte((Byte)number);
- pos++;
- continue;
- }
- else
- {
- UInt32 len = number - 256 + kMatchMinLen;
- UInt32 distance = decode_p();
- if (distance >= pos)
- return S_FALSE;
- m_OutWindowStream.CopyBlock(distance, len);
- pos += len;
- }
- }
- coderReleaser.NeedFlush = false;
- return m_OutWindowStream.Flush();
-}
-
-STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
-{
- try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
- catch(const CInBufferException &e) { return e.ErrorCode; }
- catch(const CLzOutWindowException &e) { return e.ErrorCode; }
- catch(...) { return S_FALSE; }
-}
-
-}}}
diff --git a/CPP/7zip/Compress/ArjDecoder1.h b/CPP/7zip/Compress/ArjDecoder1.h
deleted file mode 100644
index dd12e445..00000000
--- a/CPP/7zip/Compress/ArjDecoder1.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// ArjDecoder1.h
-
-#ifndef __COMPRESS_ARJ_DECODER1_H
-#define __COMPRESS_ARJ_DECODER1_H
-
-#include "../../Common/MyCom.h"
-
-#include "../ICoder.h"
-
-#include "../Common/InBuffer.h"
-
-#include "BitmDecoder.h"
-#include "LzOutWindow.h"
-
-namespace NCompress {
-namespace NArj {
-namespace NDecoder1 {
-
-#define CODE_BIT 16
-
-#define THRESHOLD 3
-#define DDICSIZ 26624
-#define MAXDICBIT 16
-#define MATCHBIT 8
-#define MAXMATCH 256
-#define NC (0xFF + MAXMATCH + 2 - THRESHOLD)
-#define NP (MAXDICBIT + 1)
-#define CBIT 9
-#define NT (CODE_BIT + 3)
-#define PBIT 5
-#define TBIT 5
-
-#if NT > NP
-#define NPT NT
-#else
-#define NPT NP
-#endif
-
-#define CTABLESIZE 4096
-#define PTABLESIZE 256
-
-
-class CCoder :
- public ICompressCoder,
- public CMyUnknownImp
-{
- CLzOutWindow m_OutWindowStream;
- NBitm::CDecoder<CInBuffer> m_InBitStream;
-
- UInt32 left[2 * NC - 1];
- UInt32 right[2 * NC - 1];
- Byte c_len[NC];
- Byte pt_len[NPT];
-
- UInt32 c_table[CTABLESIZE];
- UInt32 pt_table[PTABLESIZE];
-
- class CCoderReleaser
- {
- CCoder *m_Coder;
- public:
- bool NeedFlush;
- CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
- ~CCoderReleaser()
- {
- if (NeedFlush)
- m_Coder->m_OutWindowStream.Flush();
- }
- };
- friend class CCoderReleaser;
-
- void MakeTable(int nchar, Byte *bitlen, int tablebits, UInt32 *table, int tablesize);
-
- void read_c_len();
- void read_pt_len(int nn, int nbit, int i_special);
- UInt32 decode_c();
- UInt32 decode_p();
-
- HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
-public:
- MY_UNKNOWN_IMP
-
- STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
-
-};
-
-}}}
-
-#endif
diff --git a/CPP/7zip/Compress/ArjDecoder2.cpp b/CPP/7zip/Compress/ArjDecoder2.cpp
deleted file mode 100644
index 4903605c..00000000
--- a/CPP/7zip/Compress/ArjDecoder2.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-// ArjDecoder2.cpp
-
-#include "StdAfx.h"
-
-#include "ArjDecoder2.h"
-
-namespace NCompress{
-namespace NArj {
-namespace NDecoder2 {
-
-static const UInt32 kHistorySize = 26624;
-static const UInt32 kMatchMinLen = 3;
-
-HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo * /* progress */)
-{
- if (outSize == NULL)
- return E_INVALIDARG;
-
- if (!m_OutWindowStream.Create(kHistorySize))
- return E_OUTOFMEMORY;
- if (!m_InBitStream.Create(1 << 20))
- return E_OUTOFMEMORY;
-
- UInt64 pos = 0;
- m_OutWindowStream.SetStream(outStream);
- m_OutWindowStream.Init(false);
- m_InBitStream.SetStream(inStream);
- m_InBitStream.Init();
-
- CCoderReleaser coderReleaser(this);
-
- while (pos < *outSize)
- {
- const UInt32 kStartWidth = 0;
- const UInt32 kStopWidth = 7;
- UInt32 power = 1 << kStartWidth;
- UInt32 width;
- UInt32 len = 0;
- for (width = kStartWidth; width < kStopWidth; width++)
- {
- if (m_InBitStream.ReadBits(1) == 0)
- break;
- len += power;
- power <<= 1;
- }
- if (width != 0)
- len += m_InBitStream.ReadBits(width);
- if (len == 0)
- {
- m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8));
- pos++;
- continue;
- }
- else
- {
- len = len - 1 + kMatchMinLen;
- const UInt32 kStartWidth = 9;
- const UInt32 kStopWidth = 13;
- UInt32 power = 1 << kStartWidth;
- UInt32 width;
- UInt32 distance = 0;
- for (width = kStartWidth; width < kStopWidth; width++)
- {
- if (m_InBitStream.ReadBits(1) == 0)
- break;
- distance += power;
- power <<= 1;
- }
- if (width != 0)
- distance += m_InBitStream.ReadBits(width);
- if (distance >= pos)
- return S_FALSE;
- m_OutWindowStream.CopyBlock(distance, len);
- pos += len;
- }
- }
- coderReleaser.NeedFlush = false;
- return m_OutWindowStream.Flush();
-}
-
-STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
-{
- try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
- catch(const CInBufferException &e) { return e.ErrorCode; }
- catch(const CLzOutWindowException &e) { return e.ErrorCode; }
- catch(...) { return S_FALSE; }
-}
-
-}}}
diff --git a/CPP/7zip/Compress/ArjDecoder2.h b/CPP/7zip/Compress/ArjDecoder2.h
deleted file mode 100644
index cf544d9e..00000000
--- a/CPP/7zip/Compress/ArjDecoder2.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// ArjDecoder2.h
-
-#ifndef __COMPRESS_ARJ_DECODER2_H
-#define __COMPRESS_ARJ_DECODER2_H
-
-#include "../../Common/MyCom.h"
-
-#include "../ICoder.h"
-
-#include "../Common/InBuffer.h"
-
-#include "BitmDecoder.h"
-#include "LzOutWindow.h"
-
-namespace NCompress {
-namespace NArj {
-namespace NDecoder2 {
-
-class CCoder :
- public ICompressCoder,
- public CMyUnknownImp
-{
- CLzOutWindow m_OutWindowStream;
- NBitm::CDecoder<CInBuffer> m_InBitStream;
-
- class CCoderReleaser
- {
- CCoder *m_Coder;
- public:
- bool NeedFlush;
- CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
- ~CCoderReleaser()
- {
- if (NeedFlush)
- m_Coder->m_OutWindowStream.Flush();
- }
- };
- friend class CCoderReleaser;
-
- HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
-public:
- MY_UNKNOWN_IMP
-
- STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
-
-};
-
-}}}
-
-#endif
diff --git a/CPP/7zip/Compress/BZip2Const.h b/CPP/7zip/Compress/BZip2Const.h
index 62427aa6..588f5ae0 100644
--- a/CPP/7zip/Compress/BZip2Const.h
+++ b/CPP/7zip/Compress/BZip2Const.h
@@ -25,29 +25,30 @@ const Byte kBlockSig3 = 0x26;
const Byte kBlockSig4 = 0x53;
const Byte kBlockSig5 = 0x59;
-const int kNumOrigBits = 24;
+const unsigned kNumOrigBits = 24;
-const int kNumTablesBits = 3;
-const int kNumTablesMin = 2;
-const int kNumTablesMax = 6;
+const unsigned kNumTablesBits = 3;
+const unsigned kNumTablesMin = 2;
+const unsigned kNumTablesMax = 6;
-const int kNumLevelsBits = 5;
+const unsigned kNumLevelsBits = 5;
-const int kMaxHuffmanLen = 20; // Check it
+const unsigned kMaxHuffmanLen = 20; // Check it
-const int kMaxAlphaSize = 258;
+const unsigned kMaxAlphaSize = 258;
-const int kGroupSize = 50;
+const unsigned kGroupSize = 50;
+
+const unsigned kBlockSizeMultMin = 1;
+const unsigned kBlockSizeMultMax = 9;
-const int kBlockSizeMultMin = 1;
-const int kBlockSizeMultMax = 9;
const UInt32 kBlockSizeStep = 100000;
const UInt32 kBlockSizeMax = kBlockSizeMultMax * kBlockSizeStep;
-const int kNumSelectorsBits = 15;
+const unsigned kNumSelectorsBits = 15;
const UInt32 kNumSelectorsMax = (2 + (kBlockSizeMax / kGroupSize));
-const int kRleModeRepSize = 4;
+const unsigned kRleModeRepSize = 4;
}}
diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp
index 3798421e..db4d0933 100644
--- a/CPP/7zip/Compress/BZip2Decoder.cpp
+++ b/CPP/7zip/Compress/BZip2Decoder.cpp
@@ -105,10 +105,10 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps
CMtf8Decoder mtf;
mtf.StartInit();
- int numInUse = 0;
+ unsigned numInUse = 0;
{
Byte inUse16[16];
- int i;
+ unsigned i;
for (i = 0; i < 16; i++)
inUse16[i] = (Byte)ReadBit();
for (i = 0; i < 256; i++)
@@ -121,9 +121,9 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps
return S_FALSE;
// mtf.Init(numInUse);
}
- int alphaSize = numInUse + 2;
+ unsigned alphaSize = numInUse + 2;
- int numTables = ReadBits(kNumTablesBits);
+ unsigned numTables = ReadBits(kNumTablesBits);
if (numTables < kNumTablesMin || numTables > kNumTablesMax)
return S_FALSE;
@@ -133,14 +133,14 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps
{
Byte mtfPos[kNumTablesMax];
- int t = 0;
+ unsigned t = 0;
do
mtfPos[t] = (Byte)t;
while (++t < numTables);
UInt32 i = 0;
do
{
- int j = 0;
+ unsigned j = 0;
while (ReadBit())
if (++j >= numTables)
return S_FALSE;
@@ -152,12 +152,12 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps
while (++i < numSelectors);
}
- int t = 0;
+ unsigned t = 0;
do
{
Byte lens[kMaxAlphaSize];
- int len = (int)ReadBits(kNumLevelsBits);
- int i;
+ unsigned len = (unsigned)ReadBits(kNumLevelsBits);
+ unsigned i;
for (i = 0; i < alphaSize; i++)
{
for (;;)
@@ -166,7 +166,8 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps
return S_FALSE;
if (!ReadBit())
break;
- len += 1 - (int)(ReadBit() << 1);
+ len++;
+ len -= (ReadBit() << 1);
}
lens[i] = (Byte)len;
}
@@ -178,7 +179,7 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps
while (++t < numTables);
{
- for (int i = 0; i < 256; i++)
+ for (unsigned i = 0; i < 256; i++)
charCounters[i] = 0;
}
@@ -187,7 +188,7 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps
UInt32 groupIndex = 0;
UInt32 groupSize = 0;
CHuffmanDecoder *huffmanDecoder = 0;
- int runPower = 0;
+ unsigned runPower = 0;
UInt32 runCounter = 0;
for (;;)
@@ -224,7 +225,7 @@ HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps
}
if (nextSym <= (UInt32)numInUse)
{
- UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1);
+ UInt32 b = (UInt32)mtf.GetAndMove((unsigned)nextSym - 1);
if (blockSize >= blockSizeMax)
return S_FALSE;
charCounters[b]++;
@@ -510,7 +511,7 @@ HRESULT CDecoder::ReadSignature(UInt32 &crc)
crc = 0;
Byte s[10];
- int i;
+ unsigned i;
for (i = 0; i < 10; i++)
s[i] = ReadByte();
@@ -576,7 +577,7 @@ HRESULT CDecoder::DecodeFile(ICompressProgressInfo *progress)
*/
Byte s[4];
- int i;
+ unsigned i;
for (i = 0; i < 4; i++)
s[i] = ReadByte();
if (Base.BitDecoder.ExtraBitsWereRead())
diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h
index 2c28c5a1..8703d572 100644
--- a/CPP/7zip/Compress/BZip2Decoder.h
+++ b/CPP/7zip/Compress/BZip2Decoder.h
@@ -154,10 +154,6 @@ public:
UInt32 BlockSizeMax;
- bool IsBz;
- bool BzWasFinished; // bzip stream was finished with end signature
- bool CrcError; // it can CRC error of block or CRC error of whole stream.
-
~CDecoder();
HRESULT Create();
void Free();
@@ -166,6 +162,10 @@ public:
CState m_States[1];
#endif
+ bool IsBz;
+ bool BzWasFinished; // bzip stream was finished with end signature
+ bool CrcError; // it can CRC error of block or CRC error of whole stream.
+
CDecoder();
HRESULT SetRatioProgress(UInt64 packSize);
diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp
index 2bdbe989..bd985dfe 100644
--- a/CPP/7zip/Compress/BZip2Encoder.cpp
+++ b/CPP/7zip/Compress/BZip2Encoder.cpp
@@ -13,10 +13,10 @@
namespace NCompress {
namespace NBZip2 {
-const int kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20
+const unsigned kMaxHuffmanLenForEncoding = 16; // it must be < kMaxHuffmanLen = 20
static const UInt32 kBufferSize = (1 << 17);
-static const int kNumHuffPasses = 4;
+static const unsigned kNumHuffPasses = 4;
bool CThreadInfo::Alloc()
{
@@ -126,14 +126,16 @@ void CEncProps::Normalize(int level)
{
if (level < 0) level = 5;
if (level > 9) level = 9;
+
if (NumPasses == (UInt32)(Int32)-1)
NumPasses = (level >= 9 ? 7 : (level >= 7 ? 2 : 1));
- if (NumPasses < kBlockSizeMultMin) NumPasses = kBlockSizeMultMin;
- if (NumPasses > kBlockSizeMultMax) NumPasses = kBlockSizeMultMax;
+ if (NumPasses < 1) NumPasses = 1;
+ if (NumPasses > kNumPassesMax) NumPasses = kNumPassesMax;
+
if (BlockSizeMult == (UInt32)(Int32)-1)
BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));
- if (BlockSizeMult == 0) BlockSizeMult = 1;
- if (BlockSizeMult > kNumPassesMax) BlockSizeMult = kNumPassesMax;
+ if (BlockSizeMult < kBlockSizeMultMin) BlockSizeMult = kBlockSizeMultMin;
+ if (BlockSizeMult > kBlockSizeMultMax) BlockSizeMult = kBlockSizeMultMax;
}
CEncoder::CEncoder()
@@ -212,7 +214,7 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer)
if (m_InStream.ReadByte(prevByte))
{
UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1;
- int numReps = 1;
+ unsigned numReps = 1;
buffer[i++] = prevByte;
while (i < blockSize) // "- 1" to support RLE
{
@@ -246,19 +248,19 @@ UInt32 CEncoder::ReadRleBlock(Byte *buffer)
void CThreadInfo::WriteBits2(UInt32 value, unsigned numBits) { m_OutStreamCurrent->WriteBits(value, numBits); }
void CThreadInfo::WriteByte2(Byte b) { WriteBits2(b, 8); }
-void CThreadInfo::WriteBit2(bool v) { WriteBits2((v ? 1 : 0), 1); }
+void CThreadInfo::WriteBit2(Byte v) { WriteBits2(v, 1); }
void CThreadInfo::WriteCrc2(UInt32 v)
{
- for (int i = 0; i < 4; i++)
+ for (unsigned i = 0; i < 4; i++)
WriteByte2(((Byte)(v >> (24 - i * 8))));
}
void CEncoder::WriteBits(UInt32 value, unsigned numBits) { m_OutStream.WriteBits(value, numBits); }
void CEncoder::WriteByte(Byte b) { WriteBits(b, 8); }
-void CEncoder::WriteBit(bool v) { WriteBits((v ? 1 : 0), 1); }
+// void CEncoder::WriteBit(Byte v) { WriteBits(v, 1); }
void CEncoder::WriteCrc(UInt32 v)
{
- for (int i = 0; i < 4; i++)
+ for (unsigned i = 0; i < 4; i++)
WriteByte(((Byte)(v >> (24 - i * 8))));
}
@@ -266,7 +268,7 @@ void CEncoder::WriteCrc(UInt32 v)
// blockSize > 0
void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
{
- WriteBit2(false); // Randomised = false
+ WriteBit2(0); // Randomised = false
{
UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize);
@@ -276,21 +278,21 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
}
CMtf8Encoder mtf;
- int numInUse = 0;
+ unsigned numInUse = 0;
{
- bool inUse[256];
- bool inUse16[16];
+ Byte inUse[256];
+ Byte inUse16[16];
UInt32 i;
for (i = 0; i < 256; i++)
- inUse[i] = false;
+ inUse[i] = 0;
for (i = 0; i < 16; i++)
- inUse16[i] = false;
+ inUse16[i] = 0;
for (i = 0; i < blockSize; i++)
- inUse[block[i]] = true;
+ inUse[block[i]] = 1;
for (i = 0; i < 256; i++)
if (inUse[i])
{
- inUse16[i >> 4] = true;
+ inUse16[i >> 4] = 1;
mtf.Buf[numInUse++] = (Byte)i;
}
for (i = 0; i < 16; i++)
@@ -299,13 +301,13 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
if (inUse16[i >> 4])
WriteBit2(inUse[i]);
}
- int alphaSize = numInUse + 2;
+ unsigned alphaSize = numInUse + 2;
Byte *mtfs = m_MtfArray;
UInt32 mtfArraySize = 0;
UInt32 symbolCounts[kMaxAlphaSize];
{
- for (int i = 0; i < kMaxAlphaSize; i++)
+ for (unsigned i = 0; i < kMaxAlphaSize; i++)
symbolCounts[i] = 0;
}
@@ -360,17 +362,17 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
UInt32 numSymbols = 0;
{
- for (int i = 0; i < kMaxAlphaSize; i++)
+ for (unsigned i = 0; i < kMaxAlphaSize; i++)
numSymbols += symbolCounts[i];
}
- int bestNumTables = kNumTablesMin;
+ unsigned bestNumTables = kNumTablesMin;
UInt32 bestPrice = 0xFFFFFFFF;
UInt32 startPos = m_OutStreamCurrent->GetPos();
Byte startCurByte = m_OutStreamCurrent->GetCurByte();
- for (int nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++)
+ for (unsigned nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++)
{
- int numTables;
+ unsigned numTables;
if (m_OptimizeNumTables)
{
@@ -397,21 +399,21 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
{
UInt32 remFreq = numSymbols;
- int gs = 0;
- int t = numTables;
+ unsigned gs = 0;
+ unsigned t = numTables;
do
{
UInt32 tFreq = remFreq / t;
- int ge = gs;
+ unsigned ge = gs;
UInt32 aFreq = 0;
while (aFreq < tFreq) // && ge < alphaSize)
aFreq += symbolCounts[ge++];
- if (ge - 1 > gs && t != numTables && t != 1 && (((numTables - t) & 1) == 1))
+ if (ge > gs + 1 && t != numTables && t != 1 && (((numTables - t) & 1) == 1))
aFreq -= symbolCounts[--ge];
Byte *lens = Lens[t - 1];
- int i = 0;
+ unsigned i = 0;
do
lens[i] = (Byte)((i >= gs && i < ge) ? 0 : 1);
while (++i < alphaSize);
@@ -422,10 +424,10 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
}
- for (int pass = 0; pass < kNumHuffPasses; pass++)
+ for (unsigned pass = 0; pass < kNumHuffPasses; pass++)
{
{
- int t = 0;
+ unsigned t = 0;
do
memset(Freqs[t], 0, sizeof(Freqs[t]));
while (++t < numTables);
@@ -437,7 +439,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
do
{
UInt32 symbols[kGroupSize];
- int i = 0;
+ unsigned i = 0;
do
{
UInt32 symbol = mtfs[mtfPos++];
@@ -448,12 +450,12 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
while (++i < kGroupSize && mtfPos < mtfArraySize);
UInt32 bestPrice = 0xFFFFFFFF;
- int t = 0;
+ unsigned t = 0;
do
{
const Byte *lens = Lens[t];
UInt32 price = 0;
- int j = 0;
+ unsigned j = 0;
do
price += lens[symbols[j]];
while (++j < i);
@@ -465,7 +467,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
}
while (++t < numTables);
UInt32 *freqs = Freqs[m_Selectors[g++]];
- int j = 0;
+ unsigned j = 0;
do
freqs[symbols[j]]++;
while (++j < i);
@@ -473,11 +475,11 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
while (mtfPos < mtfArraySize);
}
- int t = 0;
+ unsigned t = 0;
do
{
UInt32 *freqs = Freqs[t];
- int i = 0;
+ unsigned i = 0;
do
if (freqs[i] == 0)
freqs[i] = 1;
@@ -490,7 +492,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
{
Byte mtfSel[kNumTablesMax];
{
- int t = 0;
+ unsigned t = 0;
do
mtfSel[t] = (Byte)t;
while (++t < numTables);
@@ -500,10 +502,10 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
do
{
Byte sel = m_Selectors[i];
- int pos;
+ unsigned pos;
for (pos = 0; mtfSel[pos] != sel; pos++)
- WriteBit2(true);
- WriteBit2(false);
+ WriteBit2(1);
+ WriteBit2(0);
for (; pos > 0; pos--)
mtfSel[pos] = mtfSel[pos - 1];
mtfSel[0] = sel;
@@ -512,31 +514,31 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
}
{
- int t = 0;
+ unsigned t = 0;
do
{
const Byte *lens = Lens[t];
UInt32 len = lens[0];
WriteBits2(len, kNumLevelsBits);
- int i = 0;
+ unsigned i = 0;
do
{
UInt32 level = lens[i];
while (len != level)
{
- WriteBit2(true);
+ WriteBit2(1);
if (len < level)
{
- WriteBit2(false);
+ WriteBit2(0);
len++;
}
else
{
- WriteBit2(true);
+ WriteBit2(1);
len--;
}
}
- WriteBit2(false);
+ WriteBit2(0);
}
while (++i < alphaSize);
}
@@ -557,7 +559,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
if (groupSize == 0)
{
groupSize = kGroupSize;
- int t = m_Selectors[groupIndex++];
+ unsigned t = m_Selectors[groupIndex++];
lens = Lens[t];
codes = Codes[t];
}
@@ -591,7 +593,7 @@ UInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize)
WriteByte2(kBlockSig5);
CBZip2Crc crc;
- int numReps = 0;
+ unsigned numReps = 0;
Byte prevByte = block[0];
UInt32 i = 0;
do
diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h
index 6b04eca1..bf05f59f 100644
--- a/CPP/7zip/Compress/BZip2Encoder.h
+++ b/CPP/7zip/Compress/BZip2Encoder.h
@@ -85,7 +85,7 @@ public:
class CEncoder;
-const int kNumPassesMax = 10;
+const unsigned kNumPassesMax = 10;
class CThreadInfo
{
@@ -111,7 +111,7 @@ private:
void WriteBits2(UInt32 value, unsigned numBits);
void WriteByte2(Byte b);
- void WriteBit2(bool v);
+ void WriteBit2(Byte v);
void WriteCrc2(UInt32 v);
void EncodeBlock(const Byte *block, UInt32 blockSize);
@@ -198,7 +198,7 @@ public:
void WriteBits(UInt32 value, unsigned numBits);
void WriteByte(Byte b);
- void WriteBit(bool v);
+ // void WriteBit(Byte v);
void WriteCrc(UInt32 v);
#ifndef _7ZIP_ST
diff --git a/CPP/7zip/Compress/BZip2Register.cpp b/CPP/7zip/Compress/BZip2Register.cpp
index ef14204b..0dd6ec9a 100644
--- a/CPP/7zip/Compress/BZip2Register.cpp
+++ b/CPP/7zip/Compress/BZip2Register.cpp
@@ -6,15 +6,13 @@
#include "BZip2Decoder.h"
-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NBZip2::CDecoder); }
+REGISTER_CODEC_CREATE(CreateDec, NCompress::NBZip2::CDecoder)
+
#if !defined(EXTRACT_ONLY) && !defined(BZIP2_EXTRACT_ONLY)
#include "BZip2Encoder.h"
-static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NBZip2::CEncoder); }
+REGISTER_CODEC_CREATE(CreateEnc, NCompress::NBZip2::CEncoder)
#else
-#define CreateCodecOut 0
+#define CreateEnc NULL
#endif
-static CCodecInfo g_CodecInfo =
- { CreateCodec, CreateCodecOut, 0x040202, L"BZip2", 1, false };
-
-REGISTER_CODEC(BZip2)
+REGISTER_CODEC_2(BZip2, CreateDec, CreateEnc, 0x40202, "BZip2")
diff --git a/CPP/7zip/Compress/Bcj2Coder.cpp b/CPP/7zip/Compress/Bcj2Coder.cpp
index 2d737e8a..fd7ce7ef 100644
--- a/CPP/7zip/Compress/Bcj2Coder.cpp
+++ b/CPP/7zip/Compress/Bcj2Coder.cpp
@@ -4,363 +4,655 @@
#include "../../../C/Alloc.h"
+#include "../Common/StreamUtils.h"
+
#include "Bcj2Coder.h"
namespace NCompress {
namespace NBcj2 {
-inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); }
-inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); }
-inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); }
-
-#ifndef EXTRACT_ONLY
-
-static const unsigned kBufSize = 1 << 17;
-
-#define NUM_BITS 2
-#define SIGN_BIT (1 << NUM_BITS)
-#define MASK_HIGH (0x100 - (1 << (NUM_BITS + 1)))
-
-static const UInt32 kDefaultLimit = (1 << (24 + NUM_BITS));
+CBaseCoder::CBaseCoder()
+{
+ for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++)
+ {
+ _bufs[i] = NULL;
+ _bufsCurSizes[i] = 0;
+ _bufsNewSizes[i] = (1 << 18);
+ }
+}
-static bool inline Test86MSByte(Byte b)
+CBaseCoder::~CBaseCoder()
{
- return (((b) + SIGN_BIT) & MASK_HIGH) == 0;
+ for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++)
+ ::MidFree(_bufs[i]);
}
-CEncoder::~CEncoder()
+HRESULT CBaseCoder::Alloc(bool allocForOrig)
{
- ::MidFree(_buf);
+ unsigned num = allocForOrig ? BCJ2_NUM_STREAMS + 1 : BCJ2_NUM_STREAMS;
+ for (unsigned i = 0; i < num; i++)
+ {
+ UInt32 newSize = _bufsNewSizes[i];
+ const UInt32 kMinBufSize = 1;
+ if (newSize < kMinBufSize)
+ newSize = kMinBufSize;
+ if (!_bufs[i] || newSize != _bufsCurSizes[i])
+ {
+ if (_bufs[i])
+ {
+ ::MidFree(_bufs[i]);
+ _bufs[i] = 0;
+ }
+ _bufsCurSizes[i] = 0;
+ Byte *buf = (Byte *)::MidAlloc(newSize);
+ _bufs[i] = buf;
+ if (!buf)
+ return E_OUTOFMEMORY;
+ _bufsCurSizes[i] = newSize;
+ }
+ }
+ return S_OK;
}
-HRESULT CEncoder::Flush()
+
+
+#ifndef EXTRACT_ONLY
+
+CEncoder::CEncoder(): _relatLim(BCJ2_RELAT_LIMIT) {}
+CEncoder::~CEncoder() {}
+
+STDMETHODIMP CEncoder::SetInBufSize(UInt32, UInt32 size) { _bufsNewSizes[BCJ2_NUM_STREAMS] = size; return S_OK; }
+STDMETHODIMP CEncoder::SetOutBufSize(UInt32 streamIndex, UInt32 size) { _bufsNewSizes[streamIndex] = size; return S_OK; }
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
- RINOK(_mainStream.Flush());
- RINOK(_callStream.Flush());
- RINOK(_jumpStream.Flush());
- _rc.FlushData();
- return _rc.FlushStream();
+ UInt32 relatLim = BCJ2_RELAT_LIMIT;
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = props[i];
+ PROPID propID = propIDs[i];
+ if (propID >= NCoderPropID::kReduceSize)
+ continue;
+ switch (propID)
+ {
+ /*
+ case NCoderPropID::kDefaultProp:
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 v = prop.ulVal;
+ if (v > 31)
+ return E_INVALIDARG;
+ relatLim = (UInt32)1 << v;
+ break;
+ }
+ */
+ case NCoderPropID::kDictionarySize:
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ relatLim = prop.ulVal;
+ if (relatLim > ((UInt32)1 << 31))
+ return E_INVALIDARG;
+ break;
+ }
+
+ case NCoderPropID::kNumThreads:
+ continue;
+ case NCoderPropID::kLevel:
+ continue;
+
+ default: return E_INVALIDARG;
+ }
+ }
+
+ _relatLim = relatLim;
+
+ return S_OK;
}
-HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,
+
+HRESULT CEncoder::CodeReal(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
+ ISequentialOutStream * const *outStreams, const UInt64 * const * /* outSizes */, UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
- if (numInStreams != 1 || numOutStreams != 4)
+ if (numInStreams != 1 || numOutStreams != BCJ2_NUM_STREAMS)
return E_INVALIDARG;
- if (!_mainStream.Create(1 << 18)) return E_OUTOFMEMORY;
- if (!_callStream.Create(1 << 18)) return E_OUTOFMEMORY;
- if (!_jumpStream.Create(1 << 18)) return E_OUTOFMEMORY;
- if (!_rc.Create(1 << 20)) return E_OUTOFMEMORY;
- if (_buf == 0)
+ RINOK(Alloc());
+
+ UInt32 fileSize_for_Conv = 0;
+ if (inSizes && inSizes[0])
{
- _buf = (Byte *)MidAlloc(kBufSize);
- if (_buf == 0)
- return E_OUTOFMEMORY;
+ UInt64 inSize = *inSizes[0];
+ if (inSize <= BCJ2_FileSize_MAX)
+ fileSize_for_Conv = (UInt32)inSize;
}
- bool sizeIsDefined = false;
- UInt64 inSize = 0;
- if (inSizes)
- if (inSizes[0])
+ CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
+ inStreams[0]->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
+
+ CBcj2Enc enc;
+
+ enc.src = _bufs[BCJ2_NUM_STREAMS];
+ enc.srcLim = enc.src;
+
+ {
+ for (int i = 0; i < BCJ2_NUM_STREAMS; i++)
{
- inSize = *inSizes[0];
- if (inSize <= kDefaultLimit)
- sizeIsDefined = true;
+ enc.bufs[i] = _bufs[i];
+ enc.lims[i] = _bufs[i] + _bufsCurSizes[i];
}
+ }
- ISequentialInStream *inStream = inStreams[0];
+ size_t numBytes_in_ReadBuf = 0;
+ UInt64 prevProgress = 0;
+ UInt64 totalStreamRead = 0; // size read from InputStream
+ UInt64 currentInPos = 0; // data that was processed, it doesn't include data in input buffer and data in enc.temp
+ UInt64 outSizeRc = 0;
- _mainStream.SetStream(outStreams[0]); _mainStream.Init();
- _callStream.SetStream(outStreams[1]); _callStream.Init();
- _jumpStream.SetStream(outStreams[2]); _jumpStream.Init();
- _rc.SetStream(outStreams[3]); _rc.Init();
- for (unsigned i = 0; i < 256 + 2; i++)
- _statusEncoder[i].Init();
+ Bcj2Enc_Init(&enc);
- CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
- {
- inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
- }
+ enc.fileIp = 0;
+ enc.fileSize = fileSize_for_Conv;
- UInt32 nowPos = 0;
- UInt64 nowPos64 = 0;
- UInt32 bufPos = 0;
+ enc.relatLimit = _relatLim;
- Byte prevByte = 0;
+ enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
+ bool needSubSize = false;
UInt64 subStreamIndex = 0;
UInt64 subStreamStartPos = 0;
- UInt64 subStreamEndPos = 0;
+ bool readWasFinished = false;
for (;;)
{
- UInt32 processedSize = 0;
- for (;;)
- {
- UInt32 size = kBufSize - (bufPos + processedSize);
- UInt32 processedSizeLoc;
- if (size == 0)
- break;
- RINOK(inStream->Read(_buf + bufPos + processedSize, size, &processedSizeLoc));
- if (processedSizeLoc == 0)
- break;
- processedSize += processedSizeLoc;
- }
- UInt32 endPos = bufPos + processedSize;
-
- if (endPos < 5)
- {
- // change it
- for (bufPos = 0; bufPos < endPos; bufPos++)
- {
- Byte b = _buf[bufPos];
- _mainStream.WriteByte(b);
- UInt32 index;
- if (b == 0xE8)
- index = prevByte;
- else if (b == 0xE9)
- index = 256;
- else if (IsJcc(prevByte, b))
- index = 257;
- else
- {
- prevByte = b;
- continue;
- }
- _statusEncoder[index].Encode(&_rc, 0);
- prevByte = b;
- }
- return Flush();
- }
-
- bufPos = 0;
-
- UInt32 limit = endPos - 5;
- while (bufPos <= limit)
+ if (needSubSize && getSubStreamSize)
{
- Byte b = _buf[bufPos];
- _mainStream.WriteByte(b);
- if (!IsJ(prevByte, b))
+ enc.fileIp = 0;
+ enc.fileSize = fileSize_for_Conv;
+ enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
+
+ for (;;)
{
- bufPos++;
- prevByte = b;
- continue;
- }
- Byte nextByte = _buf[bufPos + 4];
- UInt32 src =
- (UInt32(nextByte) << 24) |
- (UInt32(_buf[bufPos + 3]) << 16) |
- (UInt32(_buf[bufPos + 2]) << 8) |
- (_buf[bufPos + 1]);
- UInt32 dest = (nowPos + bufPos + 5) + src;
- // if (Test86MSByte(nextByte))
- bool convert;
- if (getSubStreamSize)
- {
- UInt64 currentPos = (nowPos64 + bufPos);
- while (subStreamEndPos < currentPos)
+ UInt64 subStreamSize = 0;
+ HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
+ needSubSize = false;
+
+ if (result == S_OK)
{
- UInt64 subStreamSize;
- HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
- if (result == S_OK)
+ UInt64 newEndPos = subStreamStartPos + subStreamSize;
+
+ bool isAccurateEnd = (newEndPos < totalStreamRead ||
+ (newEndPos <= totalStreamRead && readWasFinished));
+
+ if (newEndPos <= currentInPos && isAccurateEnd)
{
- subStreamStartPos = subStreamEndPos;
- subStreamEndPos += subStreamSize;
+ subStreamStartPos = newEndPos;
subStreamIndex++;
+ continue;
}
- else if (result == S_FALSE || result == E_NOTIMPL)
+
+ enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;
+
+ if (isAccurateEnd)
{
- getSubStreamSize.Release();
- subStreamStartPos = 0;
- subStreamEndPos = subStreamStartPos - 1;
+ // data in enc.temp is possible here
+ size_t rem = (size_t)(totalStreamRead - newEndPos);
+
+ /* Pos_of(enc.src) <= old newEndPos <= newEndPos
+ in another case, it's fail in some code */
+ if ((size_t)(enc.srcLim - enc.src) < rem)
+ return E_FAIL;
+
+ enc.srcLim -= rem;
+ enc.finishMode = BCJ2_ENC_FINISH_MODE_END_BLOCK;
}
- else
- return result;
- }
- if (getSubStreamSize == NULL)
- {
- if (sizeIsDefined)
- convert = (dest < inSize);
- else
- convert = Test86MSByte(nextByte);
+
+ if (subStreamSize <= BCJ2_FileSize_MAX)
+ {
+ enc.fileIp = enc.ip + (UInt32)(subStreamStartPos - currentInPos);
+ enc.fileSize = (UInt32)subStreamSize;
+ }
+ break;
}
- else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
- convert = Test86MSByte(nextByte);
- else
+
+ if (result == S_FALSE)
+ break;
+ if (result == E_NOTIMPL)
{
- UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
- convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
+ getSubStreamSize.Release();
+ break;
}
+ return result;
}
- else if (sizeIsDefined)
- convert = (dest < inSize);
- else
- convert = Test86MSByte(nextByte);
- unsigned index = GetIndex(prevByte, b);
- if (convert)
+ }
+
+ if (readWasFinished && totalStreamRead - currentInPos == Bcj2Enc_Get_InputData_Size(&enc))
+ enc.finishMode = BCJ2_ENC_FINISH_MODE_END_STREAM;
+
+ Bcj2Enc_Encode(&enc);
+
+ currentInPos = totalStreamRead - numBytes_in_ReadBuf + (enc.src - _bufs[BCJ2_NUM_STREAMS]) - enc.tempPos;
+
+ if (Bcj2Enc_IsFinished(&enc))
+ break;
+
+ if (enc.state < BCJ2_NUM_STREAMS)
+ {
+ size_t curSize = enc.bufs[enc.state] - _bufs[enc.state];
+ // printf("Write stream = %2d %6d\n", enc.state, curSize);
+ RINOK(WriteStream(outStreams[enc.state], _bufs[enc.state], curSize));
+ if (enc.state == BCJ2_STREAM_RC)
+ outSizeRc += curSize;
+
+ enc.bufs[enc.state] = _bufs[enc.state];
+ enc.lims[enc.state] = _bufs[enc.state] + _bufsCurSizes[enc.state];
+ }
+ else if (enc.state != BCJ2_ENC_STATE_ORIG)
+ return E_FAIL;
+ else
+ {
+ needSubSize = true;
+
+ if (numBytes_in_ReadBuf != (size_t)(enc.src - _bufs[BCJ2_NUM_STREAMS]))
{
- _statusEncoder[index].Encode(&_rc, 1);
- bufPos += 5;
- COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;
- for (int i = 24; i >= 0; i -= 8)
- s.WriteByte((Byte)(dest >> i));
- prevByte = nextByte;
+ enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;
+ continue;
}
- else
+
+ if (readWasFinished)
+ continue;
+
+ numBytes_in_ReadBuf = 0;
+ enc.src = _bufs[BCJ2_NUM_STREAMS];
+ enc.srcLim = _bufs[BCJ2_NUM_STREAMS];
+
+ UInt32 curSize = _bufsCurSizes[BCJ2_NUM_STREAMS];
+ RINOK(inStreams[0]->Read(_bufs[BCJ2_NUM_STREAMS], curSize, &curSize));
+
+ // printf("Read %6d bytes\n", curSize);
+ if (curSize == 0)
{
- _statusEncoder[index].Encode(&_rc, 0);
- bufPos++;
- prevByte = b;
+ readWasFinished = true;
+ continue;
}
+
+ numBytes_in_ReadBuf = curSize;
+ totalStreamRead += numBytes_in_ReadBuf;
+ enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;
}
- nowPos += bufPos;
- nowPos64 += bufPos;
- if (progress)
+ if (progress && currentInPos - prevProgress >= (1 << 20))
{
- /*
- const UInt64 compressedSize =
- _mainStream.GetProcessedSize() +
- _callStream.GetProcessedSize() +
- _jumpStream.GetProcessedSize() +
- _rc.GetProcessedSize();
- */
- RINOK(progress->SetRatioInfo(&nowPos64, NULL));
+ UInt64 outSize2 = currentInPos + outSizeRc + enc.bufs[BCJ2_STREAM_RC] - enc.bufs[BCJ2_STREAM_RC];
+ prevProgress = currentInPos;
+ // printf("progress %8d, %8d\n", (int)inSize2, (int)outSize2);
+ RINOK(progress->SetRatioInfo(&currentInPos, &outSize2));
}
-
- UInt32 i = 0;
- while (bufPos < endPos)
- _buf[i++] = _buf[bufPos++];
- bufPos = i;
}
+
+ for (int i = 0; i < BCJ2_NUM_STREAMS; i++)
+ {
+ RINOK(WriteStream(outStreams[i], _bufs[i], enc.bufs[i] - _bufs[i]));
+ }
+
+ // if (currentInPos != subStreamStartPos + subStreamSize) return E_FAIL;
+
+ return S_OK;
}
-STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
+STDMETHODIMP CEncoder::Code(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
+ ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
try
{
return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);
}
- catch(const COutBufferException &e) { return e.ErrorCode; }
- catch(...) { return S_FALSE; }
+ catch(...) { return E_FAIL; }
}
#endif
-STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _inBufSizes[streamIndex] = size; return S_OK; }
-STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
-CDecoder::CDecoder():
- _outBufSize(1 << 16)
+
+
+
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _bufsNewSizes[streamIndex] = size; return S_OK; }
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _bufsNewSizes[BCJ2_NUM_STREAMS] = size; return S_OK; }
+
+CDecoder::CDecoder(): _finishMode(false), _outSizeDefined(false), _outSize(0)
+{}
+
+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
{
- _inBufSizes[0] = 1 << 20;
- _inBufSizes[1] = 1 << 20;
- _inBufSizes[2] = 1 << 20;
- _inBufSizes[3] = 1 << 20;
+ _finishMode = (finishMode != 0);
+ return S_OK;
}
-HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams,
+void CDecoder::InitCommon()
+{
+ {
+ for (int i = 0; i < BCJ2_NUM_STREAMS; i++)
+ dec.lims[i] = dec.bufs[i] = _bufs[i];
+ }
+
+ {
+ for (int i = 0; i < BCJ2_NUM_STREAMS; i++)
+ {
+ _extraReadSizes[i] = 0;
+ _inStreamsProcessed[i] = 0;
+ _readRes[i] = S_OK;
+ }
+ }
+
+ Bcj2Dec_Init(&dec);
+}
+
+HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
+ ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress)
{
- if (numInStreams != 4 || numOutStreams != 1)
+ if (numInStreams != BCJ2_NUM_STREAMS || numOutStreams != 1)
return E_INVALIDARG;
- if (!_mainStream.Create(_inBufSizes[0])) return E_OUTOFMEMORY;
- if (!_callStream.Create(_inBufSizes[1])) return E_OUTOFMEMORY;
- if (!_jumpStream.Create(_inBufSizes[2])) return E_OUTOFMEMORY;
- if (!_rc.Create(_inBufSizes[3])) return E_OUTOFMEMORY;
- if (!_outStream.Create(_outBufSize)) return E_OUTOFMEMORY;
-
- _mainStream.SetStream(inStreams[0]);
- _callStream.SetStream(inStreams[1]);
- _jumpStream.SetStream(inStreams[2]);
- _rc.SetStream(inStreams[3]);
- _outStream.SetStream(outStreams[0]);
-
- _mainStream.Init();
- _callStream.Init();
- _jumpStream.Init();
- _rc.Init();
- _outStream.Init();
-
- for (unsigned i = 0; i < 256 + 2; i++)
- _statusDecoder[i].Init();
-
- Byte prevByte = 0;
- UInt32 processedBytes = 0;
+ RINOK(Alloc());
+
+ InitCommon();
+
+ dec.destLim = dec.dest = _bufs[BCJ2_NUM_STREAMS];
+
+ UInt64 outSizeProcessed = 0;
+ UInt64 prevProgress = 0;
+
+ HRESULT res = S_OK;
+
for (;;)
{
- if (processedBytes >= (1 << 20) && progress)
+ if (Bcj2Dec_Decode(&dec) != SZ_OK)
+ return S_FALSE;
+
+ if (dec.state < BCJ2_NUM_STREAMS)
{
- /*
- const UInt64 compressedSize =
- _mainStream.GetProcessedSize() +
- _callStream.GetProcessedSize() +
- _jumpStream.GetProcessedSize() +
- _rc.GetProcessedSize();
- */
- const UInt64 nowPos64 = _outStream.GetProcessedSize();
- RINOK(progress->SetRatioInfo(NULL, &nowPos64));
- processedBytes = 0;
+ size_t totalRead = _extraReadSizes[dec.state];
+ {
+ Byte *buf = _bufs[dec.state];
+ for (size_t i = 0; i < totalRead; i++)
+ buf[i] = dec.bufs[dec.state][i];
+ dec.lims[dec.state] =
+ dec.bufs[dec.state] = buf;
+ }
+
+ if (_readRes[dec.state] != S_OK)
+ {
+ res = _readRes[dec.state];
+ break;
+ }
+
+ do
+ {
+ UInt32 curSize = _bufsCurSizes[dec.state] - (UInt32)totalRead;
+ /*
+ we want to call Read even even if size is 0
+ if (inSizes && inSizes[dec.state])
+ {
+ UInt64 rem = *inSizes[dec.state] - _inStreamsProcessed[dec.state];
+ if (curSize > rem)
+ curSize = (UInt32)rem;
+ }
+ */
+
+ HRESULT res2 = inStreams[dec.state]->Read(_bufs[dec.state] + totalRead, curSize, &curSize);
+ _readRes[dec.state] = res2;
+ if (curSize == 0)
+ break;
+ _inStreamsProcessed[dec.state] += curSize;
+ totalRead += curSize;
+ if (res2 != S_OK)
+ break;
+ }
+ while (totalRead < 4 && BCJ2_IS_32BIT_STREAM(dec.state));
+
+ if (_readRes[dec.state] != S_OK)
+ res = _readRes[dec.state];
+
+ if (totalRead == 0)
+ break;
+
+ // res == S_OK;
+
+ if (BCJ2_IS_32BIT_STREAM(dec.state))
+ {
+ unsigned extraSize = ((unsigned)totalRead & 3);
+ _extraReadSizes[dec.state] = extraSize;
+ if (totalRead < 4)
+ {
+ res = (_readRes[dec.state] != S_OK) ? _readRes[dec.state] : S_FALSE;
+ break;
+ }
+ totalRead -= extraSize;
+ }
+
+ dec.lims[dec.state] = _bufs[dec.state] + totalRead;
}
- UInt32 i;
- Byte b = 0;
- const UInt32 kBurstSize = (1 << 18);
- for (i = 0; i < kBurstSize; i++)
+ else // if (dec.state <= BCJ2_STATE_ORIG)
{
- if (!_mainStream.ReadByte(b))
- return _outStream.Flush();
- _outStream.WriteByte(b);
- if (IsJ(prevByte, b))
- break;
- prevByte = b;
+ size_t curSize = dec.dest - _bufs[BCJ2_NUM_STREAMS];
+ if (curSize != 0)
+ {
+ outSizeProcessed += curSize;
+ RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize));
+ }
+ dec.dest = _bufs[BCJ2_NUM_STREAMS];
+ {
+ size_t rem = _bufsCurSizes[BCJ2_NUM_STREAMS];
+ if (outSizes && outSizes[0])
+ {
+ UInt64 outSize = *outSizes[0] - outSizeProcessed;
+ if (rem > outSize)
+ rem = (size_t)outSize;
+ }
+ dec.destLim = dec.dest + rem;
+ if (rem == 0)
+ break;
+ }
}
- processedBytes += i;
- if (i == kBurstSize)
- continue;
- unsigned index = GetIndex(prevByte, b);
- if (_statusDecoder[index].Decode(&_rc) == 1)
+
+ if (progress)
{
- UInt32 src = 0;
- CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;
- for (unsigned i = 0; i < 4; i++)
+ UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]);
+ if (outSize2 - prevProgress >= (1 << 22))
{
- Byte b0;
- if (!s.ReadByte(b0))
+ UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]);
+ RINOK(progress->SetRatioInfo(&inSize2, &outSize2));
+ prevProgress = outSize2;
+ }
+ }
+ }
+
+ size_t curSize = dec.dest - _bufs[BCJ2_NUM_STREAMS];
+ if (curSize != 0)
+ {
+ outSizeProcessed += curSize;
+ RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize));
+ }
+
+ if (res != S_OK)
+ return res;
+
+ if (_finishMode)
+ {
+ if (!Bcj2Dec_IsFinished(&dec))
+ return S_FALSE;
+
+ // we still allow the cases when input streams are larger than required for decoding.
+ // so the case (dec.state == BCJ2_STATE_ORIG) is also allowed, if MAIN stream is larger than required.
+ if (dec.state != BCJ2_STREAM_MAIN &&
+ dec.state != BCJ2_DEC_STATE_ORIG)
+ return S_FALSE;
+
+ if (inSizes)
+ {
+ for (int i = 0; i < BCJ2_NUM_STREAMS; i++)
+ {
+ size_t rem = dec.lims[i] - dec.bufs[i] + _extraReadSizes[i];
+ /*
+ if (rem != 0)
+ return S_FALSE;
+ */
+ if (inSizes[i] && *inSizes[i] != _inStreamsProcessed[i] - rem)
return S_FALSE;
- src <<= 8;
- src |= ((UInt32)b0);
}
- UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;
- _outStream.WriteByte((Byte)(dest));
- _outStream.WriteByte((Byte)(dest >> 8));
- _outStream.WriteByte((Byte)(dest >> 16));
- _outStream.WriteByte((Byte)(dest >> 24));
- prevByte = (Byte)(dest >> 24);
- processedBytes += 4;
}
- else
- prevByte = b;
}
+
+ return S_OK;
}
-STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
- ICompressProgressInfo *progress)
+STDMETHODIMP CDecoder::SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream)
{
- try
+ inStreams[streamIndex] = inStream;
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::ReleaseInStream2(UInt32 streamIndex)
+{
+ inStreams[streamIndex].Release();
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+{
+ _outSizeDefined = (outSize != NULL);
+ _outSize = 0;
+ if (_outSizeDefined)
+ _outSize = *outSize;
+
+ _outSize_Processed = 0;
+
+ HRESULT res = Alloc(false);
+
+ InitCommon();
+ dec.destLim = dec.dest = NULL;
+
+ return res;
+}
+
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ if (size == 0)
+ return S_OK;
+
+ UInt32 totalProcessed = 0;
+
+ if (_outSizeDefined)
{
- return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);
+ UInt64 rem = _outSize - _outSize_Processed;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ dec.dest = (Byte *)data;
+ dec.destLim = (const Byte *)data + size;
+
+ HRESULT res = S_OK;
+
+ for (;;)
+ {
+ SRes sres = Bcj2Dec_Decode(&dec);
+ if (sres != SZ_OK)
+ return S_FALSE;
+
+ {
+ UInt32 curSize = (UInt32)(dec.dest - (Byte *)data);
+ if (curSize != 0)
+ {
+ totalProcessed += curSize;
+ if (processedSize)
+ *processedSize = totalProcessed;
+ data = (void *)((Byte *)data + curSize);
+ size -= curSize;
+ _outSize_Processed += curSize;
+ }
+ }
+
+ if (dec.state >= BCJ2_NUM_STREAMS)
+ break;
+
+ {
+ size_t totalRead = _extraReadSizes[dec.state];
+ {
+ Byte *buf = _bufs[dec.state];
+ for (size_t i = 0; i < totalRead; i++)
+ buf[i] = dec.bufs[dec.state][i];
+ dec.lims[dec.state] =
+ dec.bufs[dec.state] = buf;
+ }
+
+ if (_readRes[dec.state] != S_OK)
+ return _readRes[dec.state];
+
+ do
+ {
+ UInt32 curSize = _bufsCurSizes[dec.state] - (UInt32)totalRead;
+ HRESULT res2 = inStreams[dec.state]->Read(_bufs[dec.state] + totalRead, curSize, &curSize);
+ _readRes[dec.state] = res2;
+ if (curSize == 0)
+ break;
+ _inStreamsProcessed[dec.state] += curSize;
+ totalRead += curSize;
+ if (res2 != S_OK)
+ break;
+ }
+ while (totalRead < 4 && BCJ2_IS_32BIT_STREAM(dec.state));
+
+ if (totalRead == 0)
+ {
+ if (totalProcessed == 0)
+ res = _readRes[dec.state];
+ break;
+ }
+
+ if (BCJ2_IS_32BIT_STREAM(dec.state))
+ {
+ unsigned extraSize = ((unsigned)totalRead & 3);
+ _extraReadSizes[dec.state] = extraSize;
+ if (totalRead < 4)
+ {
+ if (totalProcessed != 0)
+ return S_OK;
+ return (_readRes[dec.state] != S_OK) ? _readRes[dec.state] : S_FALSE;
+ }
+ totalRead -= extraSize;
+ }
+
+ dec.lims[dec.state] = _bufs[dec.state] + totalRead;
+ }
+ }
+
+ if (_finishMode && _outSizeDefined && _outSize == _outSize_Processed)
+ {
+ if (!Bcj2Dec_IsFinished(&dec))
+ return S_FALSE;
+
+ if (dec.state != BCJ2_STREAM_MAIN &&
+ dec.state != BCJ2_DEC_STATE_ORIG)
+ return S_FALSE;
+
+ /*
+ for (int i = 0; i < BCJ2_NUM_STREAMS; i++)
+ if (dec.bufs[i] != dec.lims[i] || _extraReadSizes[i] != 0)
+ return S_FALSE;
+ */
}
- catch(const CInBufferException &e) { return e.ErrorCode; }
- catch(const COutBufferException &e) { return e.ErrorCode; }
- catch(...) { return S_FALSE; }
+
+ return res;
}
}}
diff --git a/CPP/7zip/Compress/Bcj2Coder.h b/CPP/7zip/Compress/Bcj2Coder.h
index d2b3bda3..627e505d 100644
--- a/CPP/7zip/Compress/Bcj2Coder.h
+++ b/CPP/7zip/Compress/Bcj2Coder.h
@@ -3,44 +3,57 @@
#ifndef __COMPRESS_BCJ2_CODER_H
#define __COMPRESS_BCJ2_CODER_H
+#include "../../../C/Bcj2.h"
+
#include "../../Common/MyCom.h"
#include "../ICoder.h"
-#include "RangeCoderBit.h"
-
namespace NCompress {
namespace NBcj2 {
-const unsigned kNumMoveBits = 5;
+class CBaseCoder
+{
+protected:
+ Byte *_bufs[BCJ2_NUM_STREAMS + 1];
+ UInt32 _bufsCurSizes[BCJ2_NUM_STREAMS + 1];
+ UInt32 _bufsNewSizes[BCJ2_NUM_STREAMS + 1];
+
+ HRESULT Alloc(bool allocForOrig = true);
+public:
+ CBaseCoder();
+ ~CBaseCoder();
+};
+
#ifndef EXTRACT_ONLY
class CEncoder:
public ICompressCoder2,
- public CMyUnknownImp
+ public ICompressSetCoderProperties,
+ public ICompressSetBufSize,
+ public CMyUnknownImp,
+ public CBaseCoder
{
- Byte *_buf;
-
- COutBuffer _mainStream;
- COutBuffer _callStream;
- COutBuffer _jumpStream;
- NRangeCoder::CEncoder _rc;
- NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];
+ UInt32 _relatLim;
- HRESULT Flush();
+ HRESULT CodeReal(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
+ ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,
+ ICompressProgressInfo *progress);
public:
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP3(ICompressCoder2, ICompressSetCoderProperties, ICompressSetBufSize)
- HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
- ICompressProgressInfo *progress);
- STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
+ STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
+ ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress);
+
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
- CEncoder(): _buf(0) {};
+ STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
+ STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
+
+ CEncoder();
~CEncoder();
};
@@ -48,29 +61,51 @@ public:
class CDecoder:
public ICompressCoder2,
+ public ICompressSetFinishMode,
+ public ICompressSetInStream2,
+ public ISequentialInStream,
+ public ICompressSetOutStreamSize,
public ICompressSetBufSize,
- public CMyUnknownImp
+ public CMyUnknownImp,
+ public CBaseCoder
{
- CInBuffer _mainStream;
- CInBuffer _callStream;
- CInBuffer _jumpStream;
- NRangeCoder::CDecoder _rc;
- NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];
-
- COutBuffer _outStream;
- UInt32 _inBufSizes[4];
- UInt32 _outBufSize;
-
+ unsigned _extraReadSizes[BCJ2_NUM_STREAMS];
+ UInt64 _inStreamsProcessed[BCJ2_NUM_STREAMS];
+ HRESULT _readRes[BCJ2_NUM_STREAMS];
+ CMyComPtr<ISequentialInStream> inStreams[BCJ2_NUM_STREAMS];
+
+ bool _finishMode;
+ bool _outSizeDefined;
+ UInt64 _outSize;
+ UInt64 _outSize_Processed;
+ CBcj2Dec dec;
+
+ void InitCommon();
+ // HRESULT ReadSpec();
+
public:
- MY_UNKNOWN_IMP1(ICompressSetBufSize);
+ MY_UNKNOWN_IMP6(
+ ICompressCoder2,
+ ICompressSetFinishMode,
+ ICompressSetInStream2,
+ ISequentialInStream,
+ ICompressSetOutStreamSize,
+ ICompressSetBufSize
+ );
- HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
- ICompressProgressInfo *progress);
- STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
+ STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
+ ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress);
+ STDMETHOD(SetFinishMode)(UInt32 finishMode);
+
+ STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream);
+ STDMETHOD(ReleaseInStream2)(UInt32 streamIndex);
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp
index 8eb1e736..ef37ae0c 100644
--- a/CPP/7zip/Compress/Bcj2Register.cpp
+++ b/CPP/7zip/Compress/Bcj2Register.cpp
@@ -6,14 +6,14 @@
#include "Bcj2Coder.h"
-static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); }
+REGISTER_CODEC_CREATE_2(CreateCodec, NCompress::NBcj2::CDecoder(), ICompressCoder2)
#ifndef EXTRACT_ONLY
-static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); }
+REGISTER_CODEC_CREATE_2(CreateCodecOut, NCompress::NBcj2::CEncoder(), ICompressCoder2)
#else
-#define CreateCodecOut 0
+#define CreateCodecOut NULL
#endif
-static CCodecInfo g_CodecInfo =
- { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false };
+REGISTER_CODEC_VAR
+ { CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false };
REGISTER_CODEC(BCJ2)
diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp
index 0e34ef48..37815dce 100644
--- a/CPP/7zip/Compress/BcjCoder.cpp
+++ b/CPP/7zip/Compress/BcjCoder.cpp
@@ -4,12 +4,16 @@
#include "BcjCoder.h"
-UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size)
+STDMETHODIMP CBcjCoder::Init()
{
- return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1);
+ _bufferPos = 0;
+ x86_Convert_Init(_prevMask);
+ return S_OK;
}
-UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size)
+STDMETHODIMP_(UInt32) CBcjCoder::Filter(Byte *data, UInt32 size)
{
- return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0);
+ UInt32 processed = (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, _encode);
+ _bufferPos += processed;
+ return processed;
}
diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h
index 0754bcd2..275fd4f2 100644
--- a/CPP/7zip/Compress/BcjCoder.h
+++ b/CPP/7zip/Compress/BcjCoder.h
@@ -5,15 +5,22 @@
#include "../../../C/Bra.h"
-#include "BranchCoder.h"
+#include "../../Common/MyCom.h"
-struct CBranch86
+#include "../ICoder.h"
+
+class CBcjCoder:
+ public ICompressFilter,
+ public CMyUnknownImp
{
+ UInt32 _bufferPos;
UInt32 _prevMask;
- void x86Init() { x86_Convert_Init(_prevMask); }
-};
+ int _encode;
+public:
+ MY_UNKNOWN_IMP;
+ INTERFACE_ICompressFilter(;)
-MyClassB(BCJ_x86, 0x01, 3, CBranch86 ,
- virtual void SubInit() { x86Init(); })
+ CBcjCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); }
+};
#endif
diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp
index 648ad8e0..83c6830f 100644
--- a/CPP/7zip/Compress/BcjRegister.cpp
+++ b/CPP/7zip/Compress/BcjRegister.cpp
@@ -6,14 +6,7 @@
#include "BcjCoder.h"
-static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); }
-#ifndef EXTRACT_ONLY
-static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); }
-#else
-#define CreateCodecOut 0
-#endif
-
-static CCodecInfo g_CodecInfo =
- { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true };
-
-REGISTER_CODEC(BCJ)
+REGISTER_FILTER_E(BCJ,
+ CBcjCoder(false),
+ CBcjCoder(true),
+ 0x3030103, "BCJ")
diff --git a/CPP/7zip/Compress/BitmDecoder.h b/CPP/7zip/Compress/BitmDecoder.h
index fef20e06..9b1c540e 100644
--- a/CPP/7zip/Compress/BitmDecoder.h
+++ b/CPP/7zip/Compress/BitmDecoder.h
@@ -72,7 +72,22 @@ public:
return res;
}
+ /*
+ unsigned ReadBit()
+ {
+ UInt32 res = ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - 1);
+ if (++_bitPos >= 8)
+ {
+ _value = (_value << 8) | _stream.ReadByte();
+ _bitPos -= 8;
+ }
+ return (unsigned)res;
+ }
+ */
+
void AlignToByte() { MovePos((kNumBigValueBits - _bitPos) & 7); }
+
+ UInt32 ReadAlignBits() { return ReadBits((kNumBigValueBits - _bitPos) & 7); }
};
}
diff --git a/CPP/7zip/Compress/BranchCoder.cpp b/CPP/7zip/Compress/BranchCoder.cpp
deleted file mode 100644
index 43170952..00000000
--- a/CPP/7zip/Compress/BranchCoder.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// BranchCoder.cpp
-
-#include "StdAfx.h"
-
-#include "BranchCoder.h"
-
-STDMETHODIMP CBranchConverter::Init()
-{
- _bufferPos = 0;
- SubInit();
- return S_OK;
-}
-
-STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size)
-{
- UInt32 processedSize = SubFilter(data, size);
- _bufferPos += processedSize;
- return processedSize;
-}
diff --git a/CPP/7zip/Compress/BranchCoder.h b/CPP/7zip/Compress/BranchCoder.h
deleted file mode 100644
index 0e3a5c4e..00000000
--- a/CPP/7zip/Compress/BranchCoder.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// BranchCoder.h
-
-#ifndef __COMPRESS_BRANCH_CODER_H
-#define __COMPRESS_BRANCH_CODER_H
-
-#include "../../Common/MyCom.h"
-
-#include "../ICoder.h"
-
-class CBranchConverter:
- public ICompressFilter,
- public CMyUnknownImp
-{
-protected:
- UInt32 _bufferPos;
- virtual void SubInit() {}
- virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0;
-public:
- MY_UNKNOWN_IMP;
- STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
-};
-
-#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \
- { public: UInt32 SubFilter(Byte *data, UInt32 size); };
-
-#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \
- { public: UInt32 SubFilter(Byte *data, UInt32 size); };
-
-#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \
- { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};
-
-#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \
- { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT};
-
-#define MyClassA(Name, id, subId) \
-MyClassEncoderA(Name ## _Encoder) \
-MyClassDecoderA(Name ## _Decoder)
-
-#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \
-MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \
-MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT)
-
-#endif
diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp
index 239f2513..0bf39b79 100644
--- a/CPP/7zip/Compress/BranchMisc.cpp
+++ b/CPP/7zip/Compress/BranchMisc.cpp
@@ -2,20 +2,17 @@
#include "StdAfx.h"
-#include "../../../C/Bra.h"
-
#include "BranchMisc.h"
-#define SUB_FILTER_IMP2(name, coderStr, coderNum) \
- UInt32 CBC_ ## name ## coderStr::SubFilter(Byte *data, UInt32 size) \
- { return (UInt32)::name ## Convert(data, size, _bufferPos, coderNum); }
-
-#define SUB_FILTER_IMP(name) \
- SUB_FILTER_IMP2(name, Encoder, 1) \
- SUB_FILTER_IMP2(name, Decoder, 0) \
+STDMETHODIMP CBranchCoder::Init()
+{
+ _bufferPos = 0;
+ return S_OK;
+}
-SUB_FILTER_IMP(ARM_)
-SUB_FILTER_IMP(ARMT_)
-SUB_FILTER_IMP(PPC_)
-SUB_FILTER_IMP(SPARC_)
-SUB_FILTER_IMP(IA64_)
+STDMETHODIMP_(UInt32) CBranchCoder::Filter(Byte *data, UInt32 size)
+{
+ UInt32 processed = (UInt32)BraFunc(data, size, _bufferPos, _encode);
+ _bufferPos += processed;
+ return processed;
+}
diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h
index 81198b21..bbb5add9 100644
--- a/CPP/7zip/Compress/BranchMisc.h
+++ b/CPP/7zip/Compress/BranchMisc.h
@@ -3,12 +3,28 @@
#ifndef __COMPRESS_BRANCH_MISC_H
#define __COMPRESS_BRANCH_MISC_H
-#include "BranchCoder.h"
+#include "../../Common/MyCom.h"
-MyClassA(BC_ARM, 0x05, 1)
-MyClassA(BC_ARMT, 0x07, 1)
-MyClassA(BC_PPC, 0x02, 5)
-MyClassA(BC_SPARC, 0x08, 5)
-MyClassA(BC_IA64, 0x04, 1)
+#include "../ICoder.h"
+
+EXTERN_C_BEGIN
+
+typedef SizeT (*Func_Bra)(Byte *data, SizeT size, UInt32 ip, int encoding);
+
+EXTERN_C_END
+
+class CBranchCoder:
+ public ICompressFilter,
+ public CMyUnknownImp
+{
+ UInt32 _bufferPos;
+ int _encode;
+ Func_Bra BraFunc;
+public:
+ MY_UNKNOWN_IMP;
+ INTERFACE_ICompressFilter(;)
+
+ CBranchCoder(Func_Bra bra, int encode): _bufferPos(0), _encode(encode), BraFunc(bra) {}
+};
#endif
diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp
index 380828c6..e1fcff6d 100644
--- a/CPP/7zip/Compress/BranchRegister.cpp
+++ b/CPP/7zip/Compress/BranchRegister.cpp
@@ -2,29 +2,35 @@
#include "StdAfx.h"
+#include "../../../C/Bra.h"
+
#include "../Common/RegisterCodec.h"
#include "BranchMisc.h"
-#define CREATE_CODEC(x) \
- static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \
- static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); }
+#define CREATE_BRA(n) \
+ REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CBranchCoder(n ## _Convert, false)) \
+ REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CBranchCoder(n ## _Convert, true)) \
-CREATE_CODEC(BC_PPC)
-CREATE_CODEC(BC_IA64)
-CREATE_CODEC(BC_ARM)
-CREATE_CODEC(BC_ARMT)
-CREATE_CODEC(BC_SPARC)
+CREATE_BRA(PPC)
+CREATE_BRA(IA64)
+CREATE_BRA(ARM)
+CREATE_BRA(ARMT)
+CREATE_BRA(SPARC)
-#define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true }
+#define METHOD_ITEM(n, id, name) \
+ REGISTER_FILTER_ITEM( \
+ CreateBra_Decoder_ ## n, \
+ CreateBra_Encoder_ ## n, \
+ 0x3030000 + id, name)
-static CCodecInfo g_CodecsInfo[] =
+REGISTER_CODECS_VAR
{
- METHOD_ITEM(BC_PPC, 0x02, 0x05, L"PPC"),
- METHOD_ITEM(BC_IA64, 0x04, 1, L"IA64"),
- METHOD_ITEM(BC_ARM, 0x05, 1, L"ARM"),
- METHOD_ITEM(BC_ARMT, 0x07, 1, L"ARMT"),
- METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC")
+ METHOD_ITEM(PPC, 0x205, "PPC"),
+ METHOD_ITEM(IA64, 0x401, "IA64"),
+ METHOD_ITEM(ARM, 0x501, "ARM"),
+ METHOD_ITEM(ARMT, 0x701, "ARMT"),
+ METHOD_ITEM(SPARC, 0x805, "SPARC")
};
REGISTER_CODECS(Branch)
diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp
index 645b6ffc..f5620d6c 100644
--- a/CPP/7zip/Compress/ByteSwap.cpp
+++ b/CPP/7zip/Compress/ByteSwap.cpp
@@ -14,8 +14,7 @@ class CByteSwap2:
{
public:
MY_UNKNOWN_IMP
- STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+ INTERFACE_ICompressFilter(;)
};
class CByteSwap4:
@@ -24,8 +23,7 @@ class CByteSwap4:
{
public:
MY_UNKNOWN_IMP
- STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+ INTERFACE_ICompressFilter(;)
};
STDMETHODIMP CByteSwap2::Init() { return S_OK; }
@@ -33,14 +31,22 @@ STDMETHODIMP CByteSwap2::Init() { return S_OK; }
STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size)
{
const UInt32 kStep = 2;
- UInt32 i;
- for (i = 0; i + kStep <= size; i += kStep)
+ if (size < kStep)
+ return 0;
+ size &= ~(kStep - 1);
+
+ const Byte *end = data + (size_t)size;
+
+ do
{
- Byte b = data[i];
- data[i] = data[i + 1];
- data[i + 1] = b;
+ Byte b0 = data[0];
+ data[0] = data[1];
+ data[1] = b0;
+ data += kStep;
}
- return i;
+ while (data != end);
+
+ return size;
}
STDMETHODIMP CByteSwap4::Init() { return S_OK; }
@@ -48,26 +54,34 @@ STDMETHODIMP CByteSwap4::Init() { return S_OK; }
STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size)
{
const UInt32 kStep = 4;
- UInt32 i;
- for (i = 0; i + kStep <= size; i += kStep)
+ if (size < kStep)
+ return 0;
+ size &= ~(kStep - 1);
+
+ const Byte *end = data + (size_t)size;
+
+ do
{
- Byte b0 = data[i];
- Byte b1 = data[i + 1];
- data[i] = data[i + 3];
- data[i + 1] = data[i + 2];
- data[i + 2] = b1;
- data[i + 3] = b0;
+ Byte b0 = data[0];
+ Byte b1 = data[1];
+ data[0] = data[3];
+ data[1] = data[2];
+ data[2] = b1;
+ data[3] = b0;
+ data += kStep;
}
- return i;
+ while (data != end);
+
+ return size;
}
-static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); }
-static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); }
+REGISTER_FILTER_CREATE(CreateFilter2, CByteSwap2())
+REGISTER_FILTER_CREATE(CreateFilter4, CByteSwap4())
-static CCodecInfo g_CodecsInfo[] =
+REGISTER_CODECS_VAR
{
- { CreateCodec2, CreateCodec2, 0x020302, L"Swap2", 1, true },
- { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true }
+ REGISTER_FILTER_ITEM(CreateFilter2, CreateFilter2, 0x20302, "Swap2"),
+ REGISTER_FILTER_ITEM(CreateFilter4, CreateFilter4, 0x20304, "Swap4")
};
REGISTER_CODECS(ByteSwap)
diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp
index 726d35fc..019cb3c1 100644
--- a/CPP/7zip/Compress/CodecExports.cpp
+++ b/CPP/7zip/Compress/CodecExports.cpp
@@ -7,118 +7,164 @@
#include "../../Common/ComTry.h"
#include "../../Common/MyCom.h"
+#include "../../Windows/Defs.h"
#include "../../Windows/PropVariant.h"
#include "../ICoder.h"
#include "../Common/RegisterCodec.h"
-extern unsigned int g_NumCodecs;
+extern unsigned g_NumCodecs;
extern const CCodecInfo *g_Codecs[];
-extern unsigned int g_NumHashers;
+extern unsigned g_NumHashers;
extern const CHasherInfo *g_Hashers[];
-static const UInt16 kDecodeId = 0x2790;
-static const UInt16 kEncodeId = 0x2791;
-static const UInt16 kHasherId = 0x2792;
-
-DEFINE_GUID(CLSID_CCodec,
-0x23170F69, 0x40C1, kDecodeId, 0, 0, 0, 0, 0, 0, 0, 0);
-
-static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)
+static void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw()
{
- if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
- value->vt = VT_BSTR;
- return S_OK;
+ UINT len = (UINT)strlen(s);
+ OLECHAR *dest = ::SysAllocStringLen(NULL, len);
+ if (dest)
+ {
+ for (UINT i = 0; i <= len; i++)
+ dest[i] = (Byte)s[i];
+ prop->bstrVal = dest;
+ prop->vt = VT_BSTR;
+ }
}
-static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) throw()
{
- return SetPropString((const char *)&guid, sizeof(GUID), value);
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL)
+ value->vt = VT_BSTR;
+ return S_OK;
}
-static HRESULT SetClassID(CMethodId id, UInt16 typeId, PROPVARIANT *value)
+static HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw()
{
GUID clsId;
- clsId.Data1 = CLSID_CCodec.Data1;
- clsId.Data2 = CLSID_CCodec.Data2;
+ clsId.Data1 = k_7zip_GUID_Data1;
+ clsId.Data2 = k_7zip_GUID_Data2;
clsId.Data3 = typeId;
SetUi64(clsId.Data4, id);
return SetPropGUID(clsId, value);
}
-static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index)
+static HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, bool &encode, int &index) throw()
{
index = -1;
- if (clsID->Data1 != CLSID_CCodec.Data1 ||
- clsID->Data2 != CLSID_CCodec.Data2)
+ if (clsid->Data1 != k_7zip_GUID_Data1 ||
+ clsid->Data2 != k_7zip_GUID_Data2)
return S_OK;
+
encode = true;
- if (clsID->Data3 == kDecodeId)
- encode = false;
- else if (clsID->Data3 != kEncodeId)
- return S_OK;
- UInt64 id = GetUi64(clsID->Data4);
+
+ if (clsid->Data3 == k_7zip_GUID_Data3_Decoder) encode = false;
+ else if (clsid->Data3 != k_7zip_GUID_Data3_Encoder) return S_OK;
+
+ UInt64 id = GetUi64(clsid->Data4);
+
for (unsigned i = 0; i < g_NumCodecs; i++)
{
const CCodecInfo &codec = *g_Codecs[i];
- if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder)
+
+ if (id != codec.Id
+ || (encode ? !codec.CreateEncoder : !codec.CreateDecoder)
+ || (isFilter ? !codec.IsFilter : codec.IsFilter))
continue;
- if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
- codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
+
+ if (codec.NumStreams == 1 ? isCoder2 : !isCoder2)
return E_NOINTERFACE;
+
index = i;
return S_OK;
}
+
return S_OK;
}
-STDAPI CreateCoder2(bool encode, int index, const GUID *iid, void **outObject)
+static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder)
{
COM_TRY_BEGIN
- *outObject = 0;
- bool isCoder = (*iid == IID_ICompressCoder) != 0;
- bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
- bool isFilter = (*iid == IID_ICompressFilter) != 0;
+
const CCodecInfo &codec = *g_Codecs[index];
- if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
- codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
- return E_NOINTERFACE;
+
+ void *c;
if (encode)
- {
- if (!codec.CreateEncoder)
- return CLASS_E_CLASSNOTAVAILABLE;
- *outObject = codec.CreateEncoder();
- }
+ c = codec.CreateEncoder();
else
+ c = codec.CreateDecoder();
+
+ if (c)
{
- if (!codec.CreateDecoder)
- return CLASS_E_CLASSNOTAVAILABLE;
- *outObject = codec.CreateDecoder();
- }
- if (*outObject)
- {
- if (isCoder)
- ((ICompressCoder *)*outObject)->AddRef();
- else if (isCoder2)
- ((ICompressCoder2 *)*outObject)->AddRef();
+ IUnknown *unk;
+ if (codec.IsFilter)
+ unk = (IUnknown *)(ICompressFilter *)c;
+ else if (codec.NumStreams != 1)
+ unk = (IUnknown *)(ICompressCoder2 *)c;
else
- ((ICompressFilter *)*outObject)->AddRef();
+ unk = (IUnknown *)(ICompressCoder *)c;
+ unk->AddRef();
+ *coder = c;
}
return S_OK;
+
COM_TRY_END
}
+static HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)
+{
+ *outObject = NULL;
+
+ const CCodecInfo &codec = *g_Codecs[index];
+
+ if (encode ? !codec.CreateEncoder : !codec.CreateDecoder)
+ return CLASS_E_CLASSNOTAVAILABLE;
+
+ if (codec.IsFilter)
+ {
+ if (*iid != IID_ICompressFilter) return E_NOINTERFACE;
+ }
+ else if (codec.NumStreams != 1)
+ {
+ if (*iid != IID_ICompressCoder2) return E_NOINTERFACE;
+ }
+ else
+ {
+ if (*iid != IID_ICompressCoder) return E_NOINTERFACE;
+ }
+
+ return CreateCoderMain(index, encode, outObject);
+}
+
+STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject)
+{
+ return CreateCoder2(false, index, iid, outObject);
+}
+
+STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject)
+{
+ return CreateCoder2(true, index, iid, outObject);
+}
+
STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)
{
- COM_TRY_BEGIN
- *outObject = 0;
+ *outObject = NULL;
+
+ bool isFilter = false;
+ bool isCoder2 = false;
bool isCoder = (*iid == IID_ICompressCoder) != 0;
- bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
- bool isFilter = (*iid == IID_ICompressFilter) != 0;
- if (!isCoder && !isCoder2 && !isFilter)
- return E_NOINTERFACE;
+ if (!isCoder)
+ {
+ isFilter = (*iid == IID_ICompressFilter) != 0;
+ if (!isFilter)
+ {
+ isCoder2 = (*iid == IID_ICompressCoder2) != 0;
+ if (!isCoder2)
+ return E_NOINTERFACE;
+ }
+ }
+
bool encode;
int codecIndex;
HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);
@@ -127,24 +173,9 @@ STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)
if (codecIndex < 0)
return CLASS_E_CLASSNOTAVAILABLE;
- const CCodecInfo &codec = *g_Codecs[codecIndex];
- if (encode)
- *outObject = codec.CreateEncoder();
- else
- *outObject = codec.CreateDecoder();
- if (*outObject)
- {
- if (isCoder)
- ((ICompressCoder *)*outObject)->AddRef();
- else if (isCoder2)
- ((ICompressCoder2 *)*outObject)->AddRef();
- else
- ((ICompressFilter *)*outObject)->AddRef();
- }
- return S_OK;
- COM_TRY_END
+ return CreateCoderMain(codecIndex, encode, outObject);
}
-
+
STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
{
::VariantClear((VARIANTARG *)value);
@@ -156,24 +187,54 @@ STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
value->vt = VT_UI8;
break;
case NMethodPropID::kName:
- if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)
- value->vt = VT_BSTR;
+ SetPropFromAscii(codec.Name, value);
break;
case NMethodPropID::kDecoder:
if (codec.CreateDecoder)
- return SetClassID(codec.Id, kDecodeId, value);
+ return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value);
break;
case NMethodPropID::kEncoder:
if (codec.CreateEncoder)
- return SetClassID(codec.Id, kEncodeId, value);
+ return MethodToClassID(k_7zip_GUID_Data3_Encoder, codec.Id, value);
+ break;
+ case NMethodPropID::kDecoderIsAssigned:
+ value->vt = VT_BOOL;
+ value->boolVal = BoolToVARIANT_BOOL(codec.CreateDecoder != NULL);
+ break;
+ case NMethodPropID::kEncoderIsAssigned:
+ value->vt = VT_BOOL;
+ value->boolVal = BoolToVARIANT_BOOL(codec.CreateEncoder != NULL);
+ break;
+ case NMethodPropID::kPackStreams:
+ if (codec.NumStreams != 1)
+ {
+ value->vt = VT_UI4;
+ value->ulVal = (ULONG)codec.NumStreams;
+ }
break;
- case NMethodPropID::kInStreams:
- if (codec.NumInStreams != 1)
+ /*
+ case NMethodPropID::kIsFilter:
+ // if (codec.IsFilter)
+ {
+ value->vt = VT_BOOL;
+ value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter);
+ }
+ break;
+ */
+ /*
+ case NMethodPropID::kDecoderFlags:
+ {
+ value->vt = VT_UI4;
+ value->ulVal = (ULONG)codec.DecoderFlags;
+ }
+ break;
+ case NMethodPropID::kEncoderFlags:
{
value->vt = VT_UI4;
- value->ulVal = (ULONG)codec.NumInStreams;
+ value->ulVal = (ULONG)codec.EncoderFlags;
}
break;
+ */
}
return S_OK;
}
@@ -185,13 +246,15 @@ STDAPI GetNumberOfMethods(UINT32 *numCodecs)
}
-static int FindHasherClassId(const GUID *clsID)
+// ---------- Hashers ----------
+
+static int FindHasherClassId(const GUID *clsid) throw()
{
- if (clsID->Data1 != CLSID_CCodec.Data1 ||
- clsID->Data2 != CLSID_CCodec.Data2 ||
- clsID->Data3 != kHasherId)
+ if (clsid->Data1 != k_7zip_GUID_Data1 ||
+ clsid->Data2 != k_7zip_GUID_Data2 ||
+ clsid->Data3 != k_7zip_GUID_Data3_Hasher)
return -1;
- UInt64 id = GetUi64(clsID->Data4);
+ UInt64 id = GetUi64(clsid->Data4);
for (unsigned i = 0; i < g_NumCodecs; i++)
if (id == g_Hashers[i]->Id)
return i;
@@ -230,12 +293,11 @@ STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
value->vt = VT_UI8;
break;
case NMethodPropID::kName:
- if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)
- value->vt = VT_BSTR;
+ SetPropFromAscii(codec.Name, value);
break;
case NMethodPropID::kEncoder:
if (codec.CreateHasher)
- return SetClassID(codec.Id, kHasherId, value);
+ return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value);
break;
case NMethodPropID::kDigestSize:
value->ulVal = (ULONG)codec.DigestSize;
diff --git a/CPP/7zip/Compress/CopyCoder.cpp b/CPP/7zip/Compress/CopyCoder.cpp
index f0863202..ac6ab2e7 100644
--- a/CPP/7zip/Compress/CopyCoder.cpp
+++ b/CPP/7zip/Compress/CopyCoder.cpp
@@ -4,17 +4,15 @@
#include "../../../C/Alloc.h"
-#include "../Common/StreamUtils.h"
-
#include "CopyCoder.h"
namespace NCompress {
-static const UInt32 kBufferSize = 1 << 17;
+static const UInt32 kBufSize = 1 << 17;
CCopyCoder::~CCopyCoder()
{
- ::MidFree(_buffer);
+ ::MidFree(_buf);
}
STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
@@ -22,35 +20,78 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
const UInt64 * /* inSize */, const UInt64 *outSize,
ICompressProgressInfo *progress)
{
- if (!_buffer)
+ if (!_buf)
{
- _buffer = (Byte *)::MidAlloc(kBufferSize);
- if (!_buffer)
+ _buf = (Byte *)::MidAlloc(kBufSize);
+ if (!_buf)
return E_OUTOFMEMORY;
}
TotalSize = 0;
+
for (;;)
{
- UInt32 size = kBufferSize;
+ UInt32 size = kBufSize;
if (outSize && size > *outSize - TotalSize)
size = (UInt32)(*outSize - TotalSize);
- RINOK(inStream->Read(_buffer, size, &size));
if (size == 0)
- break;
+ return S_OK;
+
+ HRESULT readRes = inStream->Read(_buf, size, &size);
+
+ if (size == 0)
+ return readRes;
+
if (outStream)
{
- RINOK(WriteStream(outStream, _buffer, size));
+ UInt32 pos = 0;
+ do
+ {
+ UInt32 curSize = size - pos;
+ HRESULT res = outStream->Write(_buf + pos, curSize, &curSize);
+ pos += curSize;
+ TotalSize += curSize;
+ RINOK(res);
+ if (curSize == 0)
+ return E_FAIL;
+ }
+ while (pos < size);
}
- TotalSize += size;
+ else
+ TotalSize += size;
+
+ RINOK(readRes);
+
if (progress)
{
RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));
}
}
+}
+
+STDMETHODIMP CCopyCoder::SetInStream(ISequentialInStream *inStream)
+{
+ _inStream = inStream;
+ TotalSize = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CCopyCoder::ReleaseInStream()
+{
+ _inStream.Release();
return S_OK;
}
+STDMETHODIMP CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _inStream->Read(data, size, &realProcessedSize);
+ TotalSize += realProcessedSize;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
+}
+
STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)
{
*value = TotalSize;
diff --git a/CPP/7zip/Compress/CopyCoder.h b/CPP/7zip/Compress/CopyCoder.h
index 5e0bb643..a21c0988 100644
--- a/CPP/7zip/Compress/CopyCoder.h
+++ b/CPP/7zip/Compress/CopyCoder.h
@@ -11,19 +11,30 @@ namespace NCompress {
class CCopyCoder:
public ICompressCoder,
+ public ICompressSetInStream,
+ public ISequentialInStream,
public ICompressGetInStreamProcessedSize,
public CMyUnknownImp
{
- Byte *_buffer;
+ Byte *_buf;
+ CMyComPtr<ISequentialInStream> _inStream;
public:
UInt64 TotalSize;
- CCopyCoder(): TotalSize(0), _buffer(0) {};
+
+ CCopyCoder(): _buf(0), TotalSize(0) {};
~CCopyCoder();
- MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)
+ MY_UNKNOWN_IMP4(
+ ICompressCoder,
+ ICompressSetInStream,
+ ISequentialInStream,
+ ICompressGetInStreamProcessedSize)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+ STDMETHOD(ReleaseInStream)();
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
};
diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp
index efb9b9e9..703c52ca 100644
--- a/CPP/7zip/Compress/CopyRegister.cpp
+++ b/CPP/7zip/Compress/CopyRegister.cpp
@@ -6,9 +6,6 @@
#include "CopyCoder.h"
-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); }
+REGISTER_CODEC_CREATE(CreateCodec, NCompress::CCopyCoder())
-static CCodecInfo g_CodecInfo =
-{ CreateCodec, CreateCodec, 0x00, L"Copy", 1, false };
-
-REGISTER_CODEC(Copy)
+REGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, "Copy")
diff --git a/CPP/7zip/Compress/Deflate64Register.cpp b/CPP/7zip/Compress/Deflate64Register.cpp
index 509e675a..4b2cf0f7 100644
--- a/CPP/7zip/Compress/Deflate64Register.cpp
+++ b/CPP/7zip/Compress/Deflate64Register.cpp
@@ -6,15 +6,13 @@
#include "DeflateDecoder.h"
-static void *CreateCodecDeflate64() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CCOMCoder64); }
+REGISTER_CODEC_CREATE(CreateDec, NCompress::NDeflate::NDecoder::CCOMCoder64())
+
#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY)
#include "DeflateEncoder.h"
-static void *CreateCodecOutDeflate64() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NEncoder::CCOMCoder64); }
+REGISTER_CODEC_CREATE(CreateEnc, NCompress::NDeflate::NEncoder::CCOMCoder64())
#else
-#define CreateCodecOutDeflate64 0
+#define CreateEnc NULL
#endif
-static CCodecInfo g_CodecInfo =
- { CreateCodecDeflate64, CreateCodecOutDeflate64, 0x040109, L"Deflate64", 1, false };
-
-REGISTER_CODEC(Deflate64)
+REGISTER_CODEC_2(Deflate64, CreateDec, CreateEnc, 0x40109, "Deflate64")
diff --git a/CPP/7zip/Compress/DeflateConst.h b/CPP/7zip/Compress/DeflateConst.h
index c3ae5719..cfbbf886 100644
--- a/CPP/7zip/Compress/DeflateConst.h
+++ b/CPP/7zip/Compress/DeflateConst.h
@@ -6,37 +6,37 @@
namespace NCompress {
namespace NDeflate {
-const int kNumHuffmanBits = 15;
+const unsigned kNumHuffmanBits = 15;
const UInt32 kHistorySize32 = (1 << 15);
const UInt32 kHistorySize64 = (1 << 16);
-const UInt32 kDistTableSize32 = 30;
-const UInt32 kDistTableSize64 = 32;
+const unsigned kDistTableSize32 = 30;
+const unsigned kDistTableSize64 = 32;
-const UInt32 kNumLenSymbols32 = 256;
-const UInt32 kNumLenSymbols64 = 255; // don't change it. It must be <= 255.
-const UInt32 kNumLenSymbolsMax = kNumLenSymbols32;
+const unsigned kNumLenSymbols32 = 256;
+const unsigned kNumLenSymbols64 = 255; // don't change it. It must be <= 255.
+const unsigned kNumLenSymbolsMax = kNumLenSymbols32;
-const UInt32 kNumLenSlots = 29;
+const unsigned kNumLenSlots = 29;
-const UInt32 kFixedDistTableSize = 32;
-const UInt32 kFixedLenTableSize = 31;
+const unsigned kFixedDistTableSize = 32;
+const unsigned kFixedLenTableSize = 31;
-const UInt32 kSymbolEndOfBlock = 0x100;
-const UInt32 kSymbolMatch = kSymbolEndOfBlock + 1;
+const unsigned kSymbolEndOfBlock = 0x100;
+const unsigned kSymbolMatch = kSymbolEndOfBlock + 1;
-const UInt32 kMainTableSize = kSymbolMatch + kNumLenSlots;
-const UInt32 kFixedMainTableSize = kSymbolMatch + kFixedLenTableSize;
+const unsigned kMainTableSize = kSymbolMatch + kNumLenSlots;
+const unsigned kFixedMainTableSize = kSymbolMatch + kFixedLenTableSize;
-const UInt32 kLevelTableSize = 19;
+const unsigned kLevelTableSize = 19;
-const UInt32 kTableDirectLevels = 16;
-const UInt32 kTableLevelRepNumber = kTableDirectLevels;
-const UInt32 kTableLevel0Number = kTableLevelRepNumber + 1;
-const UInt32 kTableLevel0Number2 = kTableLevel0Number + 1;
+const unsigned kTableDirectLevels = 16;
+const unsigned kTableLevelRepNumber = kTableDirectLevels;
+const unsigned kTableLevel0Number = kTableLevelRepNumber + 1;
+const unsigned kTableLevel0Number2 = kTableLevel0Number + 1;
-const UInt32 kLevelMask = 0xF;
+const unsigned kLevelMask = 0xF;
const Byte kLenStart32[kFixedLenTableSize] =
{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, 0, 0};
@@ -58,12 +58,12 @@ const Byte kLevelDirectBits[3] = {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 kMatchMaxLen32 = kNumLenSymbols32 + kMatchMinLen - 1; //256 + 2
-const UInt32 kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; //255 + 2
-const UInt32 kMatchMaxLen = kMatchMaxLen32;
+const unsigned kMatchMinLen = 3;
+const unsigned kMatchMaxLen32 = kNumLenSymbols32 + kMatchMinLen - 1; // 256 + 2
+const unsigned kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; // 255 + 2
+const unsigned kMatchMaxLen = kMatchMaxLen32;
-const int kFinalBlockFieldSize = 1;
+const unsigned kFinalBlockFieldSize = 1;
namespace NFinalBlockField
{
@@ -74,7 +74,7 @@ namespace NFinalBlockField
};
}
-const int kBlockTypeFieldSize = 2;
+const unsigned kBlockTypeFieldSize = 2;
namespace NBlockType
{
@@ -86,17 +86,17 @@ namespace NBlockType
};
}
-const int kNumLenCodesFieldSize = 5;
-const int kNumDistCodesFieldSize = 5;
-const int kNumLevelCodesFieldSize = 4;
+const unsigned kNumLenCodesFieldSize = 5;
+const unsigned kNumDistCodesFieldSize = 5;
+const unsigned kNumLevelCodesFieldSize = 4;
-const UInt32 kNumLitLenCodesMin = 257;
-const UInt32 kNumDistCodesMin = 1;
-const UInt32 kNumLevelCodesMin = 4;
+const unsigned kNumLitLenCodesMin = 257;
+const unsigned kNumDistCodesMin = 1;
+const unsigned kNumLevelCodesMin = 4;
-const int kLevelFieldSize = 3;
+const unsigned kLevelFieldSize = 3;
-const int kStoredBlockLengthFieldSize = 16;
+const unsigned kStoredBlockLengthFieldSize = 16;
struct CLevels
{
@@ -105,7 +105,7 @@ struct CLevels
void SubClear()
{
- UInt32 i;
+ unsigned i;
for (i = kNumLitLenCodesMin; i < kFixedMainTableSize; i++)
litLenLevels[i] = 0;
for (i = 0; i < kFixedDistTableSize; i++)
@@ -114,7 +114,7 @@ struct CLevels
void SetFixedLevels()
{
- int i = 0;
+ unsigned i = 0;
for (; i < 144; i++) litLenLevels[i] = 8;
for (; i < 256; i++) litLenLevels[i] = 9;
diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp
index 5285e143..5e2d5d3e 100644
--- a/CPP/7zip/Compress/DeflateDecoder.cpp
+++ b/CPP/7zip/Compress/DeflateDecoder.cpp
@@ -106,7 +106,7 @@ bool CCoder::ReadTables(void)
Byte levelLevels[kLevelTableSize];
for (unsigned i = 0; i < kLevelTableSize; i++)
{
- int position = kCodeLengthAlphabetOrder[i];
+ unsigned position = kCodeLengthAlphabetOrder[i];
if (i < numLevelCodes)
levelLevels[position] = (Byte)ReadBits(kLevelFieldSize);
else
@@ -299,7 +299,7 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream,
finishInputStream = true;
}
}
- if (curSize == 0)
+ if (!finishInputStream && curSize == 0)
break;
RINOK(CodeSpec(curSize, finishInputStream));
if (_remainLen == kLenIdFinished)
@@ -314,12 +314,12 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream,
if (_remainLen == kLenIdFinished && ZlibMode)
{
m_InBitStream.AlignToByte();
- for (int i = 0; i < 4; i++)
+ for (unsigned i = 0; i < 4; i++)
ZlibFooter[i] = ReadAlignedByte();
}
flusher.NeedFlush = false;
res = Flush();
- if (res == S_OK && InputEofError())
+ if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError())
return S_FALSE;
DEFLATE_TRY_END(res)
return res;
diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp
index 392ee93d..eb012e8d 100644
--- a/CPP/7zip/Compress/DeflateEncoder.cpp
+++ b/CPP/7zip/Compress/DeflateEncoder.cpp
@@ -21,7 +21,7 @@ namespace NCompress {
namespace NDeflate {
namespace NEncoder {
-static const int kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.
+static const unsigned kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.
static const UInt32 kNumTables = (1 << kNumDivPassesMax);
static const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.
@@ -34,8 +34,8 @@ static const UInt32 kMatchArrayLimit = kMatchArraySize - kMatchMaxLen * 4 * size
static const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize -
kMatchMaxLen - kNumOpts;
-static const int kMaxCodeBitLength = 11;
-static const int kMaxLevelBitLength = 7;
+static const unsigned kMaxCodeBitLength = 11;
+static const unsigned kMaxLevelBitLength = 7;
static const Byte kNoLiteralStatPrice = 11;
static const Byte kNoLenStatPrice = 11;
@@ -49,17 +49,17 @@ class CFastPosInit
public:
CFastPosInit()
{
- int i;
+ unsigned i;
for (i = 0; i < kNumLenSlots; i++)
{
- int c = kLenStart32[i];
- int j = 1 << kLenDirectBits32[i];
- for (int k = 0; k < j; k++, c++)
+ unsigned c = kLenStart32[i];
+ unsigned j = 1 << kLenDirectBits32[i];
+ for (unsigned k = 0; k < j; k++, c++)
g_LenSlots[c] = (Byte)i;
}
- const int kFastSlots = 18;
- int c = 0;
+ const unsigned kFastSlots = 18;
+ unsigned c = 0;
for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++)
{
UInt32 k = (1 << kDistDirectBits[slotFast]);
@@ -79,10 +79,6 @@ inline UInt32 GetPosSlot(UInt32 pos)
return g_FastPos[pos >> 8] + 16;
}
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
void CEncProps::Normalize()
{
int level = Level;
@@ -183,7 +179,7 @@ HRESULT CCoder::Create()
if (!m_Created)
{
- _lzInWindow.btMode = _btMode ? 1 : 0;
+ _lzInWindow.btMode = (Byte)(_btMode ? 1 : 0);
_lzInWindow.numHashBytes = 3;
if (!MatchFinder_Create(&_lzInWindow,
m_Deflate64Mode ? kHistorySize64 : kHistorySize32,
@@ -348,7 +344,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
MovePos(lenMain - 1);
return lenMain;
}
- m_Optimum[1].Price = m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset)];
+ m_Optimum[1].Price = m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset)];
m_Optimum[1].PosPrev = 0;
m_Optimum[2].Price = kIfinityPrice;
@@ -392,7 +388,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
}
}
UInt32 curPrice = m_Optimum[cur].Price;
- UInt32 curAnd1Price = curPrice + m_LiteralPrices[Inline_MatchFinder_GetIndexByte(&_lzInWindow, cur - m_AdditionalOffset)];
+ UInt32 curAnd1Price = curPrice + m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) + cur - m_AdditionalOffset)];
COptimal &optimum = m_Optimum[cur + 1];
if (curAnd1Price < optimum.Price)
{
@@ -453,21 +449,23 @@ void CTables::InitStructures()
distLevels[i] = 5;
}
-NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs)
+NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, unsigned numLevels, UInt32 *freqs)
{
- int prevLen = 0xFF;
- int nextLen = levels[0];
- int count = 0;
- int maxCount = 7;
- int minCount = 4;
+ unsigned prevLen = 0xFF;
+ unsigned nextLen = levels[0];
+ unsigned count = 0;
+ unsigned maxCount = 7;
+ unsigned minCount = 4;
+
if (nextLen == 0)
{
maxCount = 138;
minCount = 3;
}
- for (int n = 0; n < numLevels; n++)
+
+ for (unsigned n = 0; n < numLevels; n++)
{
- int curLen = nextLen;
+ unsigned curLen = nextLen;
nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF;
count++;
if (count < maxCount && curLen == nextLen)
@@ -510,7 +508,7 @@ NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, int numLevels, UInt32
}
}
-NO_INLINE void CCoder::WriteBits(UInt32 value, int numBits)
+NO_INLINE void CCoder::WriteBits(UInt32 value, unsigned numBits)
{
m_OutStream.WriteBits(value, numBits);
}
@@ -518,28 +516,30 @@ NO_INLINE void CCoder::WriteBits(UInt32 value, int numBits)
#define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i])
#define WRITE_HF(i) WriteBits(codes[i], lens[i])
-NO_INLINE void CCoder::LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes)
+NO_INLINE void CCoder::LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes)
{
- int prevLen = 0xFF;
- int nextLen = levels[0];
- int count = 0;
- int maxCount = 7;
- int minCount = 4;
+ unsigned prevLen = 0xFF;
+ unsigned nextLen = levels[0];
+ unsigned count = 0;
+ unsigned maxCount = 7;
+ unsigned minCount = 4;
+
if (nextLen == 0)
{
maxCount = 138;
minCount = 3;
}
- for (int n = 0; n < numLevels; n++)
+
+ for (unsigned n = 0; n < numLevels; n++)
{
- int curLen = nextLen;
+ unsigned curLen = nextLen;
nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF;
count++;
if (count < maxCount && curLen == nextLen)
continue;
if (count < minCount)
- for (int i = 0; i < count; i++)
+ for (unsigned i = 0; i < count; i++)
WRITE_HF(curLen);
else if (curLen != 0)
{
@@ -644,7 +644,7 @@ NO_INLINE void CCoder::TryBlock()
}
else
{
- Byte b = Inline_MatchFinder_GetIndexByte(&_lzInWindow, 0 - m_AdditionalOffset);
+ Byte b = *(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset);
mainFreqs[b]++;
codeValue.SetAsLiteral();
codeValue.Pos = b;
@@ -719,13 +719,13 @@ NO_INLINE void CCoder::WriteBlock()
WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock);
}
-static UInt32 GetStorePrice(UInt32 blockSize, int bitPosition)
+static UInt32 GetStorePrice(UInt32 blockSize, unsigned bitPosition)
{
UInt32 price = 0;
do
{
UInt32 nextBitPosition = (bitPosition + kFinalBlockFieldSize + kBlockTypeFieldSize) & 7;
- int numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0;
+ unsigned numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0;
UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;
price += kFinalBlockFieldSize + kBlockTypeFieldSize + numBitsForAlign + (2 + 2) * 8 + curBlockSize * 8;
bitPosition = 0;
@@ -754,7 +754,7 @@ void CCoder::WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool fin
while (blockSize != 0);
}
-NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses)
+NO_INLINE UInt32 CCoder::TryDynBlock(unsigned tableIndex, UInt32 numPasses)
{
CTables &t = m_Tables[tableIndex];
BlockSizeRes = t.BlockSizeRes;
@@ -806,7 +806,7 @@ NO_INLINE UInt32 CCoder::TryDynBlock(int tableIndex, UInt32 numPasses)
m_NumLevelCodes * kLevelFieldSize + kFinalBlockFieldSize + kBlockTypeFieldSize;
}
-NO_INLINE UInt32 CCoder::TryFixedBlock(int tableIndex)
+NO_INLINE UInt32 CCoder::TryFixedBlock(unsigned tableIndex)
{
CTables &t = m_Tables[tableIndex];
BlockSizeRes = t.BlockSizeRes;
@@ -817,7 +817,7 @@ NO_INLINE UInt32 CCoder::TryFixedBlock(int tableIndex)
return kFinalBlockFieldSize + kBlockTypeFieldSize + GetLzBlockPrice();
}
-NO_INLINE UInt32 CCoder::GetBlockPrice(int tableIndex, int numDivPasses)
+NO_INLINE UInt32 CCoder::GetBlockPrice(unsigned tableIndex, unsigned numDivPasses)
{
CTables &t = m_Tables[tableIndex];
t.StaticMode = false;
@@ -864,12 +864,13 @@ NO_INLINE UInt32 CCoder::GetBlockPrice(int tableIndex, int numDivPasses)
price = subPrice;
}
}
+
m_AdditionalOffset = additionalOffsetEnd;
m_Pos = posTemp;
return price;
}
-void CCoder::CodeBlock(int tableIndex, bool finalBlock)
+void CCoder::CodeBlock(unsigned tableIndex, bool finalBlock)
{
CTables &t = m_Tables[tableIndex];
if (t.UseSubBlocks)
@@ -888,8 +889,8 @@ void CCoder::CodeBlock(int tableIndex, bool finalBlock)
{
WriteBits(NBlockType::kFixedHuffman, kBlockTypeFieldSize);
TryFixedBlock(tableIndex);
- int i;
- const int kMaxStaticHuffLen = 9;
+ unsigned i;
+ const unsigned kMaxStaticHuffLen = 9;
for (i = 0; i < kFixedMainTableSize; i++)
mainFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.litLenLevels[i]);
for (i = 0; i < kFixedDistTableSize; i++)
diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h
index d8e88f89..62423a34 100644
--- a/CPP/7zip/Compress/DeflateEncoder.h
+++ b/CPP/7zip/Compress/DeflateEncoder.h
@@ -91,8 +91,8 @@ public:
UInt32 m_Pos;
- int m_NumPasses;
- int m_NumDivPasses;
+ unsigned m_NumPasses;
+ unsigned m_NumDivPasses;
bool m_CheckStatic;
bool m_IsMultiPass;
UInt32 m_ValueBlockSize;
@@ -106,8 +106,8 @@ public:
bool m_Deflate64Mode;
Byte m_LevelLevels[kLevelTableSize];
- int m_NumLitLenLevels;
- int m_NumDistLevels;
+ unsigned m_NumLitLenLevels;
+ unsigned m_NumDistLevels;
UInt32 m_NumLevelCodes;
UInt32 m_ValueIndex;
@@ -142,17 +142,17 @@ public:
UInt32 GetOptimal(UInt32 &backRes);
UInt32 GetOptimalFast(UInt32 &backRes);
- void LevelTableDummy(const Byte *levels, int numLevels, UInt32 *freqs);
+ void LevelTableDummy(const Byte *levels, unsigned numLevels, UInt32 *freqs);
- void WriteBits(UInt32 value, int numBits);
- void LevelTableCode(const Byte *levels, int numLevels, const Byte *lens, const UInt32 *codes);
+ void WriteBits(UInt32 value, unsigned numBits);
+ void LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes);
void MakeTables(unsigned maxHuffLen);
UInt32 GetLzBlockPrice() const;
void TryBlock();
- UInt32 TryDynBlock(int tableIndex, UInt32 numPasses);
+ UInt32 TryDynBlock(unsigned tableIndex, UInt32 numPasses);
- UInt32 TryFixedBlock(int tableIndex);
+ UInt32 TryFixedBlock(unsigned tableIndex);
void SetPrices(const CLevels &levels);
void WriteBlock();
@@ -165,8 +165,8 @@ public:
void WriteBlockData(bool writeMode, bool finalBlock);
- UInt32 GetBlockPrice(int tableIndex, int numDivPasses);
- void CodeBlock(int tableIndex, bool finalBlock);
+ UInt32 GetBlockPrice(unsigned tableIndex, unsigned numDivPasses);
+ void CodeBlock(unsigned tableIndex, bool finalBlock);
void SetProps(const CEncProps *props2);
public:
diff --git a/CPP/7zip/Compress/DeflateRegister.cpp b/CPP/7zip/Compress/DeflateRegister.cpp
index 45f55219..32221fcc 100644
--- a/CPP/7zip/Compress/DeflateRegister.cpp
+++ b/CPP/7zip/Compress/DeflateRegister.cpp
@@ -6,16 +6,13 @@
#include "DeflateDecoder.h"
-static void *CreateCodecDeflate() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NDecoder::CCOMCoder); }
+REGISTER_CODEC_CREATE(CreateDec, NCompress::NDeflate::NDecoder::CCOMCoder)
#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY)
#include "DeflateEncoder.h"
-static void *CreateCodecOutDeflate() { return (void *)(ICompressCoder *)(new NCompress::NDeflate::NEncoder::CCOMCoder); }
+REGISTER_CODEC_CREATE(CreateEnc, NCompress::NDeflate::NEncoder::CCOMCoder)
#else
-#define CreateCodecOutDeflate 0
+#define CreateEnc NULL
#endif
-static CCodecInfo g_CodecInfo =
- { CreateCodecDeflate, CreateCodecOutDeflate, 0x040108, L"Deflate", 1, false };
-
-REGISTER_CODEC(Deflate)
+REGISTER_CODEC_2(Deflate, CreateDec, CreateEnc, 0x40108, "Deflate")
diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp
index d8378a60..d90f62f5 100644
--- a/CPP/7zip/Compress/DeltaFilter.cpp
+++ b/CPP/7zip/Compress/DeltaFilter.cpp
@@ -4,18 +4,24 @@
#include "../../../C/Delta.h"
-#include "../Common/RegisterCodec.h"
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
-#include "BranchCoder.h"
+#include "../Common/RegisterCodec.h"
struct CDelta
{
unsigned _delta;
Byte _state[DELTA_STATE_SIZE];
+
CDelta(): _delta(1) {}
void DeltaInit() { Delta_Init(_state); }
};
+
+#ifndef EXTRACT_ONLY
+
class CDeltaEncoder:
public ICompressFilter,
public ICompressSetCoderProperties,
@@ -25,25 +31,11 @@ class CDeltaEncoder:
{
public:
MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)
- STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+ INTERFACE_ICompressFilter(;)
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
};
-class CDeltaDecoder:
- public ICompressFilter,
- public ICompressSetDecoderProperties2,
- CDelta,
- public CMyUnknownImp
-{
-public:
- MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
- STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
- STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
-};
-
STDMETHODIMP CDeltaEncoder::Init()
{
DeltaInit();
@@ -89,6 +81,21 @@ STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream
return outStream->Write(&prop, 1, NULL);
}
+#endif
+
+
+class CDeltaDecoder:
+ public ICompressFilter,
+ public ICompressSetDecoderProperties2,
+ CDelta,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
+ INTERFACE_ICompressFilter(;)
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+};
+
STDMETHODIMP CDeltaDecoder::Init()
{
DeltaInit();
@@ -109,17 +116,8 @@ STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size
return S_OK;
}
-#define CREATE_CODEC(x) \
- static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## Decoder); } \
- static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## Encoder); }
-
-CREATE_CODEC(Delta)
-
-#define METHOD_ITEM(x, id, name) { CreateCodec ## x, CreateCodec ## x ## Out, id, name, 1, true }
-
-static CCodecInfo g_CodecsInfo[] =
-{
- METHOD_ITEM(Delta, 3, L"Delta")
-};
-REGISTER_CODECS(Delta)
+REGISTER_FILTER_E(Delta,
+ CDeltaDecoder(),
+ CDeltaEncoder(),
+ 3, "Delta")
diff --git a/CPP/7zip/Compress/DllExports2Compress.cpp b/CPP/7zip/Compress/DllExports2Compress.cpp
index 286ef08b..a6ff6905 100644
--- a/CPP/7zip/Compress/DllExports2Compress.cpp
+++ b/CPP/7zip/Compress/DllExports2Compress.cpp
@@ -1,4 +1,4 @@
-// DllExports.cpp
+// DllExports2Compress.cpp
#include "StdAfx.h"
@@ -20,11 +20,6 @@ BOOL WINAPI DllMain(
return TRUE;
}
-static const UInt16 kDecodeId = 0x2790;
-
-DEFINE_GUID(CLSID_CCodec,
-0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-
STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
diff --git a/CPP/7zip/Compress/DllExportsCompress.cpp b/CPP/7zip/Compress/DllExportsCompress.cpp
index be429277..c58d2d5e 100644
--- a/CPP/7zip/Compress/DllExportsCompress.cpp
+++ b/CPP/7zip/Compress/DllExportsCompress.cpp
@@ -40,11 +40,6 @@ BOOL WINAPI DllMain(
}
#endif
-static const UInt16 kDecodeId = 0x2790;
-
-DEFINE_GUID(CLSID_CCodec,
-0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-
STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h
index 21f96f0d..6faf8005 100644
--- a/CPP/7zip/Compress/HuffmanDecoder.h
+++ b/CPP/7zip/Compress/HuffmanDecoder.h
@@ -8,39 +8,42 @@
namespace NCompress {
namespace NHuffman {
-const int kNumTableBits = 9;
+const unsigned kNumTableBits = 9;
-template <int kNumBitsMax, UInt32 m_NumSymbols>
+template <unsigned kNumBitsMax, UInt32 m_NumSymbols>
class CDecoder
{
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.
+ Byte m_Lengths[1 << kNumTableBits]; // Table of length for short codes
public:
-
- bool SetCodeLengths(const Byte *codeLengths)
+
+ bool SetCodeLengths(const Byte *lens)
{
- int lenCounts[kNumBitsMax + 1];
+ unsigned lenCounts[kNumBitsMax + 1];
UInt32 tmpPositions[kNumBitsMax + 1];
- int i;
+ unsigned i;
for (i = 1; i <= kNumBitsMax; i++)
lenCounts[i] = 0;
UInt32 symbol;
+
for (symbol = 0; symbol < m_NumSymbols; symbol++)
{
- int len = codeLengths[symbol];
+ unsigned len = lens[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);
@@ -56,19 +59,21 @@ public:
m_Lengths[index] = (Byte)i;
}
}
+
for (symbol = 0; symbol < m_NumSymbols; symbol++)
{
- int len = codeLengths[symbol];
+ unsigned len = lens[symbol];
if (len != 0)
m_Symbols[tmpPositions[len]++] = symbol;
}
+
return true;
}
template <class TBitDecoder>
UInt32 DecodeSymbol(TBitDecoder *bitStream)
{
- int numBits;
+ unsigned numBits;
UInt32 value = bitStream->GetValue(kNumBitsMax);
if (value < m_Limits[kNumTableBits])
numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp
index 2170326e..d385d7b1 100644
--- a/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp
+++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.cpp
@@ -21,9 +21,9 @@ CDecoder::~CDecoder()
bool CDecoder::SetCodeLengths(const Byte *codeLengths)
{
- // int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1];
- int lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1];
- int i;
+ // unsigned lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1];
+ unsigned lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1];
+ unsigned i;
for (i = 0; i <= kNumBitsInLongestCode; i++)
lenCounts[i] = 0;
UInt32 symbolIndex;
@@ -67,7 +67,7 @@ UInt32 CDecoder::DecodeSymbol(CInBit *inStream)
{
UInt32 numBits = 0;
UInt32 value = inStream->GetValue(kNumBitsInLongestCode);
- int i;
+ unsigned i;
for (i = kNumBitsInLongestCode; i > 0; i--)
{
if (value < m_Limitits[i])
diff --git a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h
index 6120a35a..691a8e93 100644
--- a/CPP/7zip/Compress/ImplodeHuffmanDecoder.h
+++ b/CPP/7zip/Compress/ImplodeHuffmanDecoder.h
@@ -11,7 +11,7 @@ namespace NCompress {
namespace NImplode {
namespace NHuffman {
-const int kNumBitsInLongestCode = 16;
+const unsigned kNumBitsInLongestCode = 16;
typedef NBitl::CDecoder<CInBuffer> CInBit;
diff --git a/CPP/7zip/Compress/LzOutWindow.h b/CPP/7zip/Compress/LzOutWindow.h
index 507aa7f4..5591744d 100644
--- a/CPP/7zip/Compress/LzOutWindow.h
+++ b/CPP/7zip/Compress/LzOutWindow.h
@@ -35,10 +35,13 @@ public:
}
else do
{
+ UInt32 pos2;
if (pos == _bufSize)
pos = 0;
- _buf[_pos++] = _buf[pos++];
- if (_pos == _limitPos)
+ pos2 = _pos;
+ _buf[pos2++] = _buf[pos++];
+ _pos = pos2;
+ if (pos2 == _limitPos)
FlushWithCheck();
}
while (--len != 0);
@@ -47,15 +50,17 @@ public:
void PutByte(Byte b)
{
- _buf[_pos++] = b;
- if (_pos == _limitPos)
+ UInt32 pos = _pos;
+ _buf[pos++] = b;
+ _pos = pos;
+ if (pos == _limitPos)
FlushWithCheck();
}
Byte GetByte(UInt32 distance) const
{
UInt32 pos = _pos - distance - 1;
- if (pos >= _bufSize)
+ if (distance >= _pos)
pos += _bufSize;
return _buf[pos];
}
diff --git a/CPP/7zip/Compress/LzhDecoder.cpp b/CPP/7zip/Compress/LzhDecoder.cpp
index ad6e873a..bf4a0b68 100644
--- a/CPP/7zip/Compress/LzhDecoder.cpp
+++ b/CPP/7zip/Compress/LzhDecoder.cpp
@@ -8,208 +8,240 @@ namespace NCompress{
namespace NLzh {
namespace NDecoder {
-static const UInt32 kHistorySize = (1 << 16);
+static const UInt32 kWindowSizeMin = 1 << 16;
-static const int kBlockSizeBits = 16;
-static const int kNumCBits = 9;
-static const int kNumLevelBits = 5; // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/
-
-UInt32 CCoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
-
-HRESULT CCoder::ReadLevelTable()
+static bool CheckCodeLens(const Byte *lens, unsigned num)
{
- int n = ReadBits(kNumLevelBits);
- if (n == 0)
- {
- m_LevelHuffman.Symbol = ReadBits(kNumLevelBits);
- if (m_LevelHuffman.Symbol >= kNumLevelSymbols)
- return S_FALSE;
- }
- else
+ UInt32 sum = 0;
+ for (unsigned i = 0; i < num; i++)
{
- if (n > kNumLevelSymbols)
- return S_FALSE;
- m_LevelHuffman.Symbol = -1;
- Byte lens[kNumLevelSymbols];
- int i = 0;
- while (i < n)
- {
- int c = m_InBitStream.ReadBits(3);
- if (c == 7)
- while (ReadBits(1))
- if (c++ > kMaxHuffmanLen)
- return S_FALSE;
- lens[i++] = (Byte)c;
- if (i == kNumSpecLevelSymbols)
- {
- c = ReadBits(2);
- while (--c >= 0)
- lens[i++] = 0;
- }
- }
- while (i < kNumLevelSymbols)
- lens[i++] = 0;
- m_LevelHuffman.SetCodeLengths(lens);
+ unsigned len = lens[i];
+ if (len != 0)
+ sum += ((UInt32)1 << (NUM_CODE_BITS - len));
}
- return S_OK;
+ return sum == ((UInt32)1 << NUM_CODE_BITS);
}
-HRESULT CCoder::ReadPTable(int numBits)
+bool CCoder::ReadTP(unsigned num, unsigned numBits, int spec)
{
- int n = ReadBits(numBits);
+ _symbolT = -1;
+
+ UInt32 n = _inBitStream.ReadBits(numBits);
if (n == 0)
{
- m_PHuffmanDecoder.Symbol = ReadBits(numBits);
- if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols)
- return S_FALSE;
+ _symbolT = _inBitStream.ReadBits(numBits);
+ return ((unsigned)_symbolT < num);
}
- else
+
+ if (n > num)
+ return false;
+
{
- if (n > kNumDistanceSymbols)
- return S_FALSE;
- m_PHuffmanDecoder.Symbol = -1;
- Byte lens[kNumDistanceSymbols];
- int i = 0;
- while (i < n)
+ Byte lens[NPT];
+ unsigned i;
+ for (i = 0; i < NPT; i++)
+ lens[i] = 0;
+
+ i = 0;
+
+ do
{
- int c = m_InBitStream.ReadBits(3);
+ UInt32 val = _inBitStream.GetValue(16);
+ unsigned c = val >> 13;
+
if (c == 7)
- while (ReadBits(1))
+ {
+ UInt32 mask = 1 << 12;
+ while (mask & val)
{
- if (c > kMaxHuffmanLen)
- return S_FALSE;
+ mask >>= 1;
c++;
}
+ if (c > 16)
+ return false;
+ }
+
+ _inBitStream.MovePos(c < 7 ? 3 : c - 3);
lens[i++] = (Byte)c;
+
+ if (i == (unsigned)spec)
+ i += _inBitStream.ReadBits(2);
}
- while (i < kNumDistanceSymbols)
- lens[i++] = 0;
- m_PHuffmanDecoder.SetCodeLengths(lens);
+ while (i < n);
+
+ if (!CheckCodeLens(lens, NPT))
+ return false;
+ return _decoderT.SetCodeLengths(lens);
}
- return S_OK;
}
-HRESULT CCoder::ReadCTable()
+static const unsigned NUM_C_BITS = 9;
+
+bool CCoder::ReadC()
{
- int n = ReadBits(kNumCBits);
+ _symbolC = -1;
+
+ unsigned n = _inBitStream.ReadBits(NUM_C_BITS);
+
if (n == 0)
{
- m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits);
- if (m_CHuffmanDecoder.Symbol >= kNumCSymbols)
- return S_FALSE;
+ _symbolC = _inBitStream.ReadBits(NUM_C_BITS);
+ return ((unsigned)_symbolC < NC);
}
- else
+
+ if (n > NC)
+ return false;
+
{
- if (n > kNumCSymbols)
- return S_FALSE;
- m_CHuffmanDecoder.Symbol = -1;
- Byte lens[kNumCSymbols];
- int i = 0;
- while (i < n)
+ Byte lens[NC];
+
+ unsigned i = 0;
+
+ do
{
- int c = m_LevelHuffman.Decode(&m_InBitStream);
- if (c < kNumSpecLevelSymbols)
+ UInt32 c = (unsigned)_symbolT;
+ if (_symbolT < 0)
+ c = _decoderT.DecodeSymbol(&_inBitStream);
+
+ if (c <= 2)
{
if (c == 0)
c = 1;
else if (c == 1)
- c = ReadBits(4) + 3;
+ c = _inBitStream.ReadBits(4) + 3;
else
- c = ReadBits(kNumCBits) + 20;
- while (--c >= 0)
- {
- if (i > kNumCSymbols)
- return S_FALSE;
+ c = _inBitStream.ReadBits(NUM_C_BITS) + 20;
+
+ if (i + c > n)
+ return false;
+
+ do
lens[i++] = 0;
- }
+ while (--c);
}
else
lens[i++] = (Byte)(c - 2);
}
- while (i < kNumCSymbols)
+ while (i < n);
+
+ while (i < NC)
lens[i++] = 0;
- m_CHuffmanDecoder.SetCodeLengths(lens);
+
+ if (!CheckCodeLens(lens, NC))
+ return false;
+ return _decoderC.SetCodeLengths(lens);
}
- return S_OK;
}
-STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,
- ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
- ICompressProgressInfo *progress)
+HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
{
- if (outSize == NULL)
- return E_INVALIDARG;
-
- if (!m_OutWindowStream.Create(kHistorySize))
- return E_OUTOFMEMORY;
- if (!m_InBitStream.Create(1 << 20))
- return E_OUTOFMEMORY;
-
- UInt64 pos = 0;
- m_OutWindowStream.SetStream(outStream);
- m_OutWindowStream.Init(false);
- m_InBitStream.SetStream(inStream);
- m_InBitStream.Init();
-
- CCoderReleaser coderReleaser(this);
-
- int pbit;
- if (m_NumDictBits <= 13)
- pbit = 4;
- else
- pbit = 5;
+ unsigned pbit = (DictSize <= (1 << 14) ? 4 : 5);
UInt32 blockSize = 0;
- while (pos < *outSize)
+ while (rem != 0)
{
- // for (i = 0; i < dictSize; i++) dtext[i] = 0x20;
-
if (blockSize == 0)
{
- if (progress != NULL)
+ if (_inBitStream.ExtraBitsWereRead())
+ return S_FALSE;
+
+ if (progress)
{
- UInt64 packSize = m_InBitStream.GetProcessedSize();
+ UInt64 packSize = _inBitStream.GetProcessedSize();
+ UInt64 pos = _outWindow.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos));
}
- blockSize = ReadBits(kBlockSizeBits);
- ReadLevelTable();
- ReadCTable();
- RINOK(ReadPTable(pbit));
+
+ blockSize = _inBitStream.ReadBits(16);
+ if (blockSize == 0)
+ return S_FALSE;
+
+ if (!ReadTP(NT, 5, 3))
+ return S_FALSE;
+ if (!ReadC())
+ return S_FALSE;
+ if (!ReadTP(NP, pbit, -1))
+ return S_FALSE;
}
+
blockSize--;
- UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream);
- if (c < 256)
+
+ UInt32 number = (unsigned)_symbolC;
+ if (_symbolC < 0)
+ number = _decoderC.DecodeSymbol(&_inBitStream);
+
+ if (number < 256)
{
- m_OutWindowStream.PutByte((Byte)c);
- pos++;
+ _outWindow.PutByte((Byte)number);
+ rem--;
}
- else if (c >= kNumCSymbols)
- return S_FALSE;
else
{
- // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3;
- UInt32 len = c - 256 + kMinMatch;
- UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream);
- if (distance != 0)
- distance = (1 << (distance - 1)) + ReadBits(distance - 1);
- if (distance >= pos)
+ UInt32 len = number - 256 + kMatchMinLen;
+
+ UInt32 dist = (unsigned)_symbolT;
+ if (_symbolT < 0)
+ dist = _decoderT.DecodeSymbol(&_inBitStream);
+
+ if (dist > 1)
+ {
+ dist--;
+ dist = ((UInt32)1 << dist) + _inBitStream.ReadBits((unsigned)dist);
+ }
+
+ if (dist >= DictSize)
return S_FALSE;
- if (pos + len > *outSize)
- len = (UInt32)(*outSize - pos);
- pos += len;
- m_OutWindowStream.CopyBlock(distance, len);
+
+ if (len > rem)
+ len = (UInt32)rem;
+
+ if (!_outWindow.CopyBlock(dist, len))
+ return S_FALSE;
+ rem -= len;
}
}
- coderReleaser.NeedFlush = false;
- return m_OutWindowStream.Flush();
+
+ if (FinishMode)
+ {
+ if (blockSize != 0)
+ return S_FALSE;
+ if (_inBitStream.ReadAlignBits() != 0)
+ return S_FALSE;
+ }
+
+ if (_inBitStream.ExtraBitsWereRead())
+ return S_FALSE;
+
+ return S_OK;
}
-STDMETHODIMP CCoder::Code(ISequentialInStream *inStream,
- ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
- ICompressProgressInfo *progress)
+
+STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{
- try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
+ try
+ {
+ if (!outSize)
+ return E_INVALIDARG;
+
+ if (!_outWindow.Create(DictSize > kWindowSizeMin ? DictSize : kWindowSizeMin))
+ return E_OUTOFMEMORY;
+ if (!_inBitStream.Create(1 << 17))
+ return E_OUTOFMEMORY;
+
+ _outWindow.SetStream(outStream);
+ _outWindow.Init(false);
+ _inBitStream.SetStream(inStream);
+ _inBitStream.Init();
+
+ CCoderReleaser coderReleaser(this);
+
+ RINOK(CodeReal(*outSize, progress));
+
+ coderReleaser.Disable();
+ return _outWindow.Flush();
+ }
catch(const CInBufferException &e) { return e.ErrorCode; }
catch(const CLzOutWindowException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
diff --git a/CPP/7zip/Compress/LzhDecoder.h b/CPP/7zip/Compress/LzhDecoder.h
index a0a7b244..5e13d823 100644
--- a/CPP/7zip/Compress/LzhDecoder.h
+++ b/CPP/7zip/Compress/LzhDecoder.h
@@ -17,89 +17,56 @@ namespace NCompress {
namespace NLzh {
namespace NDecoder {
-const int kMaxHuffmanLen = 16; // Check it
-
-const int kNumSpecLevelSymbols = 3;
-const int kNumLevelSymbols = kNumSpecLevelSymbols + kMaxHuffmanLen;
-
-const int kDictBitsMax = 16;
-const int kNumDistanceSymbols = kDictBitsMax + 1;
-
-const int kMaxMatch = 256;
-const int kMinMatch = 3;
-const int kNumCSymbols = 256 + kMaxMatch + 2 - kMinMatch;
-
-template <UInt32 m_NumSymbols>
-class CHuffmanDecoder:public NCompress::NHuffman::CDecoder<kMaxHuffmanLen, m_NumSymbols>
-{
-public:
- int Symbol;
- template <class TBitDecoder>
- UInt32 Decode(TBitDecoder *bitStream)
- {
- if (Symbol >= 0)
- return (UInt32)Symbol;
- return this->DecodeSymbol(bitStream);
- }
-};
-
-class CCoder :
+const unsigned kMatchMinLen = 3;
+const unsigned kMatchMaxLen = 256;
+const unsigned NC = (256 + kMatchMaxLen - kMatchMinLen + 1);
+const unsigned NUM_CODE_BITS = 16;
+const unsigned NUM_DIC_BITS_MAX = 25;
+const unsigned NT = (NUM_CODE_BITS + 3);
+const unsigned NP = (NUM_DIC_BITS_MAX + 1);
+const unsigned NPT = NP; // Max(NT, NP)
+
+class CCoder:
public ICompressCoder,
public CMyUnknownImp
{
- CLzOutWindow m_OutWindowStream;
- NBitm::CDecoder<CInBuffer> m_InBitStream;
-
- int m_NumDictBits;
+ CLzOutWindow _outWindow;
+ NBitm::CDecoder<CInBuffer> _inBitStream;
- CHuffmanDecoder<kNumLevelSymbols> m_LevelHuffman;
- CHuffmanDecoder<kNumDistanceSymbols> m_PHuffmanDecoder;
- CHuffmanDecoder<kNumCSymbols> m_CHuffmanDecoder;
+ int _symbolT;
+ int _symbolC;
- /*
- void ReleaseStreams()
- {
- m_OutWindowStream.ReleaseStream();
- }
- */
+ NHuffman::CDecoder<NUM_CODE_BITS, NPT> _decoderT;
+ NHuffman::CDecoder<NUM_CODE_BITS, NC> _decoderC;
class CCoderReleaser
{
- CCoder *m_Coder;
+ CCoder *_coder;
public:
- bool NeedFlush;
- CCoderReleaser(CCoder *coder): m_Coder(coder), NeedFlush(true) {}
- ~CCoderReleaser()
- {
- if (NeedFlush)
- m_Coder->m_OutWindowStream.Flush();
- // m_Coder->ReleaseStreams();
- }
+ CCoderReleaser(CCoder *coder): _coder(coder) {}
+ void Disable() { _coder = NULL; }
+ ~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); }
};
friend class CCoderReleaser;
- void MakeTable(int nchar, Byte *bitlen, int tablebits,
- UInt32 *table, int tablesize);
-
- UInt32 ReadBits(int numBits);
- HRESULT ReadLevelTable();
- HRESULT ReadPTable(int numBits);
- HRESULT ReadCTable();
+ bool ReadTP(unsigned num, unsigned numBits, int spec);
+ bool ReadC();
+ HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress);
public:
-
MY_UNKNOWN_IMP
- STDMETHOD(CodeReal)(ISequentialInStream *inStream,
- ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
- ICompressProgressInfo *progress);
+ UInt32 DictSize;
+ bool FinishMode;
+
+ STDMETHOD(Code)(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);
+ void SetDictSize(unsigned dictSize) { DictSize = dictSize; }
+
+ CCoder(): DictSize(1 << 16), FinishMode(false) {}
- void SetDictionary(int numDictBits) { m_NumDictBits = numDictBits; }
- CCoder(): m_NumDictBits(0) {}
+ UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }
};
}}}
diff --git a/CPP/7zip/Compress/Lzma2Decoder.cpp b/CPP/7zip/Compress/Lzma2Decoder.cpp
index 322015e2..05b136a7 100644
--- a/CPP/7zip/Compress/Lzma2Decoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Decoder.cpp
@@ -24,32 +24,40 @@ static HRESULT SResToHRESULT(SRes res)
namespace NCompress {
namespace NLzma2 {
-static const UInt32 kInBufSize = 1 << 20;
-
-CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false)
+CDecoder::CDecoder():
+ _inBuf(NULL),
+ _inBufSize(0),
+ _inBufSizeNew(1 << 20),
+ _outStepSize(1 << 22),
+ _outSizeDefined(false),
+ _finishMode(false)
{
Lzma2Dec_Construct(&_state);
}
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStepSize = size; return S_OK; }
CDecoder::~CDecoder()
{
Lzma2Dec_Free(&_state, &g_Alloc);
- MyFree(_inBuf);
+ MidFree(_inBuf);
}
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
{
- if (size != 1) return SZ_ERROR_UNSUPPORTED;
+ if (size != 1)
+ return E_NOTIMPL;
+
RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc)));
- if (_inBuf == 0)
+ if (!_inBuf || _inBufSize != _inBufSizeNew)
{
- _inBuf = (Byte *)MyAlloc(kInBufSize);
- if (_inBuf == 0)
+ MidFree(_inBuf);
+ _inBufSize = 0;
+ _inBuf = (Byte *)MidAlloc(_inBufSizeNew);
+ if (!_inBuf)
return E_OUTOFMEMORY;
+ _inBufSize = _inBufSizeNew;
}
return S_OK;
@@ -62,6 +70,7 @@ STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
{
_outSizeDefined = (outSize != NULL);
+ _outSize = 0;
if (_outSizeDefined)
_outSize = *outSize;
@@ -72,39 +81,55 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
return S_OK;
}
+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
+{
+ _finishMode = (finishMode != 0);
+ return S_OK;
+}
+
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
- ISequentialOutStream *outStream, const UInt64 * /* inSize */,
+ ISequentialOutStream *outStream, const UInt64 *inSize,
const UInt64 *outSize, ICompressProgressInfo *progress)
{
- if (_inBuf == 0)
+ if (!_inBuf)
return S_FALSE;
SetOutStreamSize(outSize);
+ UInt32 step = _outStepSize;
+ const UInt32 kOutStepSize_Min = 1 << 12;
+ if (step < kOutStepSize_Min)
+ step = kOutStepSize_Min;
+
+ SizeT wrPos = _state.decoder.dicPos;
+
+ SizeT next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ?
+ _state.decoder.dicBufSize :
+ _state.decoder.dicPos + step;
+
+ HRESULT hres = S_OK;
+
for (;;)
{
if (_inPos == _inSize)
{
_inPos = _inSize = 0;
- RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize));
+ hres = inStream->Read(_inBuf, _inBufSize, &_inSize);
+ if (hres != S_OK)
+ break;
}
SizeT dicPos = _state.decoder.dicPos;
- SizeT curSize = _state.decoder.dicBufSize - dicPos;
- const UInt32 kStepSize = ((UInt32)1 << 22);
- if (curSize > kStepSize)
- curSize = (SizeT)kStepSize;
-
+ SizeT curSize = next - dicPos;
+
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
if (_outSizeDefined)
{
const UInt64 rem = _outSize - _outSizeProcessed;
- if (rem < curSize)
+ if (curSize >= rem)
{
curSize = (SizeT)rem;
- /*
- // finishMode = LZMA_FINISH_END;
- we can't use LZMA_FINISH_END here to allow partial decoding
- */
+ if (_finishMode)
+ finishMode = LZMA_FINISH_END;
}
}
@@ -117,71 +142,123 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
SizeT outSizeProcessed = _state.decoder.dicPos - dicPos;
_outSizeProcessed += outSizeProcessed;
- bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);
- bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);
+ bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0
+ || status == LZMA_STATUS_FINISHED_WITH_MARK);
+ bool outFinished = (_outSizeDefined && _outSizeProcessed >= _outSize);
- if (res != 0 || _state.decoder.dicPos == _state.decoder.dicBufSize || finished || stopDecoding)
+ if (res != 0
+ || _state.decoder.dicPos >= next
+ || finished
+ || outFinished)
{
- HRESULT res2 = WriteStream(outStream, _state.decoder.dic, _state.decoder.dicPos);
+ HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);
+
+ if (_state.decoder.dicPos == _state.decoder.dicBufSize)
+ _state.decoder.dicPos = 0;
+
+ wrPos = _state.decoder.dicPos;
+
+ next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ?
+ _state.decoder.dicBufSize :
+ _state.decoder.dicPos + step;
+
if (res != 0)
return S_FALSE;
RINOK(res2);
- if (stopDecoding)
- return S_OK;
+
if (finished)
- return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);
- }
- if (_state.decoder.dicPos == _state.decoder.dicBufSize)
- _state.decoder.dicPos = 0;
+ {
+ if (status == LZMA_STATUS_FINISHED_WITH_MARK)
+ {
+ if (_finishMode && inSize && *inSize != _inSizeProcessed)
+ return S_FALSE;
+ if (finishMode == LZMA_FINISH_END && !outFinished)
+ return S_FALSE;
+ return S_OK;
+ }
+ return (finishMode == LZMA_FINISH_END) ? S_FALSE : S_OK;
+ }
- if (progress != NULL)
+ if (outFinished && finishMode == LZMA_FINISH_ANY)
+ return S_OK;
+ }
+
+ if (progress)
{
RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed));
}
}
+
+ HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);
+ if (hres != S_OK)
+ return hres;
+ return res2;
}
#ifndef NO_READ_FROM_CODER
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
{
+ UInt32 totalProcessed = 0;
+
if (processedSize)
*processedSize = 0;
- do
+
+ for (;;)
{
if (_inPos == _inSize)
{
_inPos = _inSize = 0;
- RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize));
+ RINOK(_inStream->Read(_inBuf, _inBufSize, &_inSize));
}
{
- SizeT inProcessed = _inSize - _inPos;
-
+ ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
if (_outSizeDefined)
{
const UInt64 rem = _outSize - _outSizeProcessed;
- if (rem < size)
+ if (rem <= size)
+ {
size = (UInt32)rem;
+ if (_finishMode)
+ finishMode = LZMA_FINISH_END;
+ }
}
SizeT outProcessed = size;
+ SizeT inProcessed = _inSize - _inPos;
+
ELzmaStatus status;
SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
- _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);
+ _inBuf + _inPos, &inProcessed, finishMode, &status);
+
_inPos += (UInt32)inProcessed;
_inSizeProcessed += inProcessed;
_outSizeProcessed += outProcessed;
size -= (UInt32)outProcessed;
data = (Byte *)data + outProcessed;
+
+ totalProcessed += (UInt32)outProcessed;
if (processedSize)
- *processedSize += (UInt32)outProcessed;
- RINOK(SResToHRESULT(res));
+ *processedSize = totalProcessed;
+
+ if (res != SZ_OK)
+ {
+ if (totalProcessed != 0)
+ return S_OK;
+ return SResToHRESULT(res);
+ }
+
if (inProcessed == 0 && outProcessed == 0)
return S_OK;
+ if (status == LZMA_STATUS_FINISHED_WITH_MARK)
+ return S_OK;
+ if (outProcessed != 0)
+ {
+ if (finishMode != LZMA_FINISH_END || _outSize != _outSizeProcessed)
+ return S_OK;
+ }
}
}
- while (size != 0);
- return S_OK;
}
#endif
diff --git a/CPP/7zip/Compress/Lzma2Decoder.h b/CPP/7zip/Compress/Lzma2Decoder.h
index fd7ca2f3..a87912fb 100644
--- a/CPP/7zip/Compress/Lzma2Decoder.h
+++ b/CPP/7zip/Compress/Lzma2Decoder.h
@@ -15,7 +15,9 @@ namespace NLzma2 {
class CDecoder:
public ICompressCoder,
public ICompressSetDecoderProperties2,
+ public ICompressSetFinishMode,
public ICompressGetInStreamProcessedSize,
+ public ICompressSetBufSize,
#ifndef NO_READ_FROM_CODER
public ICompressSetInStream,
public ICompressSetOutStreamSize,
@@ -27,36 +29,49 @@ class CDecoder:
Byte *_inBuf;
UInt32 _inPos;
UInt32 _inSize;
- CLzma2Dec _state;
+
+ bool _finishMode;
bool _outSizeDefined;
UInt64 _outSize;
+
UInt64 _inSizeProcessed;
UInt64 _outSizeProcessed;
+
+ UInt32 _inBufSize;
+ UInt32 _inBufSizeNew;
+ UInt32 _outStepSize;
+
+ CLzma2Dec _state;
public:
+ MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
+ MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
#ifndef NO_READ_FROM_CODER
- MY_UNKNOWN_IMP5(
- ICompressSetDecoderProperties2,
- ICompressGetInStreamProcessedSize,
- ICompressSetInStream,
- ICompressSetOutStreamSize,
- ISequentialInStream)
- #else
- MY_UNKNOWN_IMP2(
- ICompressSetDecoderProperties2,
- ICompressGetInStreamProcessedSize)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
+ MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
#endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
- STDMETHOD(Code)(ISequentialInStream *inStream,
- ISequentialOutStream *outStream, const UInt64 *_inSize, const UInt64 *outSize,
- ICompressProgressInfo *progress);
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+ STDMETHOD(SetFinishMode)(UInt32 finishMode);
+
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+ STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
+ STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
+
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
+
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
#ifndef NO_READ_FROM_CODER
diff --git a/CPP/7zip/Compress/Lzma2Encoder.cpp b/CPP/7zip/Compress/Lzma2Encoder.cpp
index 5e4c71be..dea297c4 100644
--- a/CPP/7zip/Compress/Lzma2Encoder.cpp
+++ b/CPP/7zip/Compress/Lzma2Encoder.cpp
@@ -19,14 +19,6 @@ HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep);
namespace NLzma2 {
-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
-static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }
-static void SzFree(void *, void *address) { MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
CEncoder::CEncoder()
{
_encoder = 0;
diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp
index cace871e..d684d9d0 100644
--- a/CPP/7zip/Compress/Lzma2Register.cpp
+++ b/CPP/7zip/Compress/Lzma2Register.cpp
@@ -6,15 +6,12 @@
#include "Lzma2Decoder.h"
-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CDecoder); }
#ifndef EXTRACT_ONLY
#include "Lzma2Encoder.h"
-static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma2::CEncoder); }
-#else
-#define CreateCodecOut 0
#endif
-static CCodecInfo g_CodecInfo =
- { CreateCodec, CreateCodecOut, 0x21, L"LZMA2", 1, false };
-
-REGISTER_CODEC(LZMA2)
+REGISTER_CODEC_E(LZMA2,
+ NCompress::NLzma2::CDecoder(),
+ NCompress::NLzma2::CEncoder(),
+ 0x21,
+ "LZMA2")
diff --git a/CPP/7zip/Compress/LzmaDecoder.cpp b/CPP/7zip/Compress/LzmaDecoder.cpp
index a7ee31ba..d96be8ce 100644
--- a/CPP/7zip/Compress/LzmaDecoder.cpp
+++ b/CPP/7zip/Compress/LzmaDecoder.cpp
@@ -25,20 +25,16 @@ namespace NCompress {
namespace NLzma {
CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),
- _inBufSize(1 << 20),
- _outBufSize(1 << 22),
- FinishStream(false),
- NeedMoreInput(false)
+ _inBufSize(1 << 20),
+ _outBufSize(1 << 22),
+ FinishStream(false),
+ NeedMoreInput(false)
{
_inSizeProcessed = 0;
_inPos = _inSize = 0;
LzmaDec_Construct(&_state);
}
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
-static void SzFree(void *p, void *address) { p = p; MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
CDecoder::~CDecoder()
{
LzmaDec_Free(&_state, &g_Alloc);
@@ -87,6 +83,12 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
return S_OK;
}
+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
+{
+ FinishStream = (finishMode != 0);
+ return S_OK;
+}
+
HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
if (_inBuf == 0 || !_propsWereSet)
diff --git a/CPP/7zip/Compress/LzmaDecoder.h b/CPP/7zip/Compress/LzmaDecoder.h
index 754eaa3f..f1f839a4 100644
--- a/CPP/7zip/Compress/LzmaDecoder.h
+++ b/CPP/7zip/Compress/LzmaDecoder.h
@@ -14,6 +14,7 @@ namespace NLzma {
class CDecoder:
public ICompressCoder,
public ICompressSetDecoderProperties2,
+ public ICompressSetFinishMode,
public ICompressSetBufSize,
#ifndef NO_READ_FROM_CODER
public ICompressSetInStream,
@@ -45,6 +46,7 @@ class CDecoder:
public:
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
#ifndef NO_READ_FROM_CODER
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
@@ -57,6 +59,7 @@ public:
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+ STDMETHOD(SetFinishMode)(UInt32 finishMode);
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp
index 484d0452..0a7e294d 100644
--- a/CPP/7zip/Compress/LzmaEncoder.cpp
+++ b/CPP/7zip/Compress/LzmaEncoder.cpp
@@ -12,29 +12,21 @@
namespace NCompress {
namespace NLzma {
-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
-static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }
-static void SzFree(void *, void *address) { MyFree(address); }
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
CEncoder::CEncoder()
{
- _encoder = 0;
+ _encoder = NULL;
_encoder = LzmaEnc_Create(&g_Alloc);
- if (_encoder == 0)
+ if (!_encoder)
throw 1;
}
CEncoder::~CEncoder()
{
- if (_encoder != 0)
+ if (_encoder)
LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc);
}
-inline wchar_t GetUpperChar(wchar_t c)
+static inline wchar_t GetUpperChar(wchar_t c)
{
if (c >= 'a' && c <= 'z')
c -= 0x20;
@@ -51,22 +43,21 @@ static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)
int numHashBytesLoc = (int)(*s++ - L'0');
if (numHashBytesLoc < 4 || numHashBytesLoc > 4)
return 0;
- if (*s++ != 0)
+ if (*s != 0)
return 0;
*btMode = 0;
*numHashBytes = numHashBytesLoc;
return 1;
}
+
if (c != L'B')
return 0;
-
if (GetUpperChar(*s++) != L'T')
return 0;
int numHashBytesLoc = (int)(*s++ - L'0');
if (numHashBytesLoc < 2 || numHashBytesLoc > 4)
return 0;
- c = GetUpperChar(*s++);
- if (c != L'\0')
+ if (*s != 0)
return 0;
*btMode = 1;
*numHashBytes = numHashBytesLoc;
diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp
index 96ed0bae..c12416f2 100644
--- a/CPP/7zip/Compress/LzmaRegister.cpp
+++ b/CPP/7zip/Compress/LzmaRegister.cpp
@@ -6,15 +6,12 @@
#include "LzmaDecoder.h"
-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); }
#ifndef EXTRACT_ONLY
#include "LzmaEncoder.h"
-static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder); }
-#else
-#define CreateCodecOut 0
#endif
-static CCodecInfo g_CodecInfo =
- { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false };
-
-REGISTER_CODEC(LZMA)
+REGISTER_CODEC_E(LZMA,
+ NCompress::NLzma::CDecoder(),
+ NCompress::NLzma::CEncoder(),
+ 0x30101,
+ "LZMA")
diff --git a/CPP/7zip/Compress/PpmdDecoder.cpp b/CPP/7zip/Compress/PpmdDecoder.cpp
index c02f44f1..ce00343b 100644
--- a/CPP/7zip/Compress/PpmdDecoder.cpp
+++ b/CPP/7zip/Compress/PpmdDecoder.cpp
@@ -23,10 +23,6 @@ enum
kStatus_Error
};
-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
CDecoder::~CDecoder()
{
::MidFree(_outBuf);
diff --git a/CPP/7zip/Compress/PpmdEncoder.cpp b/CPP/7zip/Compress/PpmdEncoder.cpp
index 5bf83529..00ea9668 100644
--- a/CPP/7zip/Compress/PpmdEncoder.cpp
+++ b/CPP/7zip/Compress/PpmdEncoder.cpp
@@ -14,10 +14,6 @@ namespace NPpmd {
static const UInt32 kBufSize = (1 << 20);
-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 };
void CEncProps::Normalize(int level)
@@ -40,7 +36,7 @@ void CEncProps::Normalize(int level)
}
}
}
- if (Order == -1) Order = kOrders[level];
+ if (Order == -1) Order = kOrders[(unsigned)level];
}
CEncoder::CEncoder():
diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp
index 9f59fcdd..17f84bd0 100644
--- a/CPP/7zip/Compress/PpmdRegister.cpp
+++ b/CPP/7zip/Compress/PpmdRegister.cpp
@@ -1,5 +1,4 @@
// PpmdRegister.cpp
-// 2009-05-30 : Igor Pavlov : Public domain
#include "StdAfx.h"
@@ -7,15 +6,12 @@
#include "PpmdDecoder.h"
-static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CDecoder); }
#ifndef EXTRACT_ONLY
#include "PpmdEncoder.h"
-static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NPpmd::CEncoder); }
-#else
-#define CreateCodecOut 0
#endif
-static CCodecInfo g_CodecInfo =
- { CreateCodec, CreateCodecOut, 0x030401, L"PPMD", 1, false };
-
-REGISTER_CODEC(PPMD)
+REGISTER_CODEC_E(PPMD,
+ NCompress::NPpmd::CDecoder(),
+ NCompress::NPpmd::CEncoder(),
+ 0x30401,
+ "PPMD")
diff --git a/CPP/7zip/Compress/PpmdZip.cpp b/CPP/7zip/Compress/PpmdZip.cpp
index 036f3c72..24dd32f2 100644
--- a/CPP/7zip/Compress/PpmdZip.cpp
+++ b/CPP/7zip/Compress/PpmdZip.cpp
@@ -12,10 +12,6 @@
namespace NCompress {
namespace NPpmdZip {
-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
CDecoder::CDecoder(bool fullFileMode):
_fullFileMode(fullFileMode)
{
@@ -260,14 +256,4 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
}
}
-/*
-static void *CreateCodec() { return (void *)(ICompressCoder *)(new CDecoder(false)); }
-static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new CEncoder); }
-
-static CCodecInfo g_CodecInfo =
- { CreateCodec, CreateCodecOut, 0x040162, L"PPMdZIP", 1, false };
-
-REGISTER_CODEC(PPMdZIP)
-*/
-
}}
diff --git a/CPP/7zip/Compress/RangeCoder.h b/CPP/7zip/Compress/RangeCoder.h
deleted file mode 100644
index 0b0d44ae..00000000
--- a/CPP/7zip/Compress/RangeCoder.h
+++ /dev/null
@@ -1,201 +0,0 @@
-// Compress/RangeCoder.h
-// 2013-01-10 : Igor Pavlov : Public domain
-
-#ifndef __COMPRESS_RANGE_CODER_H
-#define __COMPRESS_RANGE_CODER_H
-
-#include "../Common/InBuffer.h"
-#include "../Common/OutBuffer.h"
-
-namespace NCompress {
-namespace NRangeCoder {
-
-const unsigned kNumTopBits = 24;
-const UInt32 kTopValue = (1 << kNumTopBits);
-
-class CEncoder
-{
- UInt32 _cacheSize;
- Byte _cache;
-public:
- UInt64 Low;
- UInt32 Range;
- COutBuffer Stream;
- bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }
-
- void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
- void Init()
- {
- Stream.Init();
- Low = 0;
- Range = 0xFFFFFFFF;
- _cacheSize = 1;
- _cache = 0;
- }
-
- void FlushData()
- {
- // Low += 1;
- for (int i = 0; i < 5; i++)
- ShiftLow();
- }
-
- HRESULT FlushStream() { return Stream.Flush(); }
-
- void Encode(UInt32 start, UInt32 size, UInt32 total)
- {
- Low += start * (Range /= total);
- Range *= size;
- while (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
-
- void ShiftLow()
- {
- if ((UInt32)Low < (UInt32)0xFF000000 || (unsigned)(Low >> 32) != 0)
- {
- Byte temp = _cache;
- do
- {
- Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
- temp = 0xFF;
- }
- while (--_cacheSize != 0);
- _cache = (Byte)((UInt32)Low >> 24);
- }
- _cacheSize++;
- Low = (UInt32)Low << 8;
- }
-
- void EncodeDirectBits(UInt32 value, int numBits)
- {
- for (numBits--; numBits >= 0; numBits--)
- {
- Range >>= 1;
- Low += Range & (0 - ((value >> numBits) & 1));
- if (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
- }
-
- void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)
- {
- UInt32 newBound = (Range >> numTotalBits) * size0;
- if (symbol == 0)
- Range = newBound;
- else
- {
- Low += newBound;
- Range -= newBound;
- }
- while (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
-
- UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }
-};
-
-class CDecoder
-{
-public:
- CInBuffer Stream;
- UInt32 Range;
- UInt32 Code;
- bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }
-
- void Normalize()
- {
- while (Range < kTopValue)
- {
- Code = (Code << 8) | Stream.ReadByte();
- Range <<= 8;
- }
- }
-
- void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
- void Init()
- {
- Stream.Init();
- Code = 0;
- Range = 0xFFFFFFFF;
- for (int i = 0; i < 5; i++)
- Code = (Code << 8) | Stream.ReadByte();
- }
-
- UInt32 GetThreshold(UInt32 total)
- {
- return (Code) / (Range /= total);
- }
-
- void Decode(UInt32 start, UInt32 size)
- {
- Code -= start * Range;
- Range *= size;
- Normalize();
- }
-
- UInt32 DecodeDirectBits(int numTotalBits)
- {
- UInt32 range = Range;
- UInt32 code = Code;
- UInt32 result = 0;
- for (int i = numTotalBits; i != 0; i--)
- {
- range >>= 1;
- /*
- result <<= 1;
- if (code >= range)
- {
- code -= range;
- result |= 1;
- }
- */
- UInt32 t = (code - range) >> 31;
- code -= range & (t - 1);
- result = (result << 1) | (1 - t);
-
- if (range < kTopValue)
- {
- code = (code << 8) | Stream.ReadByte();
- range <<= 8;
- }
- }
- Range = range;
- Code = code;
- return result;
- }
-
- UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
- {
- UInt32 newBound = (Range >> numTotalBits) * size0;
- UInt32 symbol;
- if (Code < newBound)
- {
- symbol = 0;
- Range = newBound;
- }
- else
- {
- symbol = 1;
- Code -= newBound;
- Range -= newBound;
- }
- Normalize();
- return symbol;
- }
-
- UInt64 GetProcessedSize() { return Stream.GetProcessedSize(); }
-};
-
-}}
-
-#endif
diff --git a/CPP/7zip/Compress/RangeCoderBit.h b/CPP/7zip/Compress/RangeCoderBit.h
deleted file mode 100644
index 0eddd558..00000000
--- a/CPP/7zip/Compress/RangeCoderBit.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Compress/RangeCoderBit.h
-// 2013-01-10 : Igor Pavlov : Public domain
-
-#ifndef __COMPRESS_RANGE_CODER_BIT_H
-#define __COMPRESS_RANGE_CODER_BIT_H
-
-#include "RangeCoder.h"
-
-namespace NCompress {
-namespace NRangeCoder {
-
-const unsigned kNumBitModelTotalBits = 11;
-const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);
-
-const unsigned kNumMoveReducingBits = 4;
-
-const unsigned kNumBitPriceShiftBits = 4;
-const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;
-
-extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
-
-template <unsigned numMoveBits>
-class CBitModel
-{
-public:
- UInt32 Prob;
- void UpdateModel(UInt32 symbol)
- {
- /*
- Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;
- Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);
- */
- if (symbol == 0)
- Prob += (kBitModelTotal - Prob) >> numMoveBits;
- else
- Prob -= (Prob) >> numMoveBits;
- }
-public:
- void Init() { Prob = kBitModelTotal / 2; }
-};
-
-template <unsigned numMoveBits>
-class CBitEncoder: public CBitModel<numMoveBits>
-{
-public:
- void Encode(CEncoder *encoder, UInt32 symbol)
- {
- /*
- encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);
- this->UpdateModel(symbol);
- */
- UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;
- if (symbol == 0)
- {
- encoder->Range = newBound;
- this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
- }
- else
- {
- encoder->Low += newBound;
- encoder->Range -= newBound;
- this->Prob -= (this->Prob) >> numMoveBits;
- }
- if (encoder->Range < kTopValue)
- {
- encoder->Range <<= 8;
- encoder->ShiftLow();
- }
- }
- UInt32 GetPrice(UInt32 symbol) const
- {
- return ProbPrices[(this->Prob ^ ((-(int)(Int32)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
- }
- UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; }
- UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; }
-};
-
-
-template <unsigned numMoveBits>
-class CBitDecoder: public CBitModel<numMoveBits>
-{
-public:
- UInt32 Decode(CDecoder *decoder)
- {
- UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;
- if (decoder->Code < newBound)
- {
- decoder->Range = newBound;
- this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
- if (decoder->Range < kTopValue)
- {
- decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
- decoder->Range <<= 8;
- }
- return 0;
- }
- else
- {
- decoder->Range -= newBound;
- decoder->Code -= newBound;
- this->Prob -= (this->Prob) >> numMoveBits;
- if (decoder->Range < kTopValue)
- {
- decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
- decoder->Range <<= 8;
- }
- return 1;
- }
- }
-};
-
-}}
-
-#endif
diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp
index 8eb904df..12de7e19 100644
--- a/CPP/7zip/Compress/Rar1Decoder.cpp
+++ b/CPP/7zip/Compress/Rar1Decoder.cpp
@@ -9,13 +9,13 @@
namespace NCompress {
namespace NRar1 {
-static UInt32 PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32, 256};
-static UInt32 PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36, 256};
-static UInt32 PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33, 257};
-static UInt32 PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127, 257};
-static UInt32 PosHf2[]={0,0,0,0,0,0,2,7,53,117,233, 257,0};
-static UInt32 PosHf3[]={0,0,0,0,0,0,0,2,16,218,251, 257,0};
-static UInt32 PosHf4[]={0,0,0,0,0,0,0,0,0,255, 257,0,0};
+static const UInt32 PosL1[] = {0,0,0,2,3,5,7,11,16,20,24,32,32, 256};
+static const UInt32 PosL2[] = {0,0,0,0,5,7,9,13,18,22,26,34,36, 256};
+static const UInt32 PosHf0[] = {0,0,0,0,0,8,16,24,33,33,33,33,33, 257};
+static const UInt32 PosHf1[] = {0,0,0,0,0,0,4,44,60,76,80,80,127, 257};
+static const UInt32 PosHf2[] = {0,0,0,0,0,0,2,7,53,117,233, 257,0};
+static const UInt32 PosHf3[] = {0,0,0,0,0,0,0,2,16,218,251, 257,0};
+static const UInt32 PosHf4[] = {0,0,0,0,0,0,0,0,0,255, 257,0,0};
static const UInt32 kHistorySize = (1 << 16);
@@ -67,18 +67,18 @@ UInt32 CDecoder::DecodeNum(const UInt32 *posTab)
return((num >> (12 - startPos)) + posTab[startPos]);
}
-static Byte kShortLen1 [] = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 };
-static Byte kShortLen1a[] = {1,4,4,4,5,6,7,8,8,4,4,5,6,6,4 };
-static Byte kShortLen2 [] = {2,3,3,3,4,4,5,6,6,4,4,5,6,6 };
-static Byte kShortLen2a[] = {2,3,3,4,4,4,5,6,6,4,4,5,6,6,4 };
-static UInt32 kShortXor1[] = {0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
-static UInt32 kShortXor2[] = {0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
+static const Byte kShortLen1 [] = {1,3,4,4,5,6,7,8,8,4,4,5,6,6 };
+static const Byte kShortLen1a[] = {1,4,4,4,5,6,7,8,8,4,4,5,6,6,4 };
+static const Byte kShortLen2 [] = {2,3,3,3,4,4,5,6,6,4,4,5,6,6 };
+static const Byte kShortLen2a[] = {2,3,3,4,4,4,5,6,6,4,4,5,6,6,4 };
+static const UInt32 kShortXor1[] = {0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
+static const UInt32 kShortXor2[] = {0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
HRESULT CDecoder::ShortLZ()
{
UInt32 len, saveLen, dist;
int distancePlace;
- Byte *kShortLen;
+ const Byte *kShortLen;
const UInt32 *kShortXor;
NumHuf = 0;
@@ -143,17 +143,18 @@ HRESULT CDecoder::ShortLZ()
AvrLn1 -= AvrLn1 >> 4;
distancePlace = DecodeNum(PosHf2) & 0xff;
- dist = ChSetA[distancePlace];
+ dist = ChSetA[(unsigned)distancePlace];
if (--distancePlace != -1)
{
PlaceA[dist]--;
- UInt32 lastDistance = ChSetA[distancePlace];
+ UInt32 lastDistance = ChSetA[(unsigned)distancePlace];
PlaceA[lastDistance]++;
- ChSetA[distancePlace + 1] = lastDistance;
- ChSetA[distancePlace] = dist;
+ ChSetA[(unsigned)distancePlace + 1] = lastDistance;
+ ChSetA[(unsigned)distancePlace] = dist;
}
len += 2;
}
+
m_RepDists[m_RepDistPtr++] = dist;
m_RepDistPtr &= 3;
LastLength = len;
@@ -210,6 +211,7 @@ HRESULT CDecoder::LongLZ()
AvrPlcB += distancePlace;
AvrPlcB -= AvrPlcB >> 8;
+
for (;;)
{
dist = ChSetB[distancePlace & 0xff];
@@ -226,6 +228,7 @@ HRESULT CDecoder::LongLZ()
dist = ((dist & 0xff00) >> 1) | ReadBits(7);
oldAvr3 = AvrLn3;
+
if (len != 1 && len != 4)
if (len == 0 && dist <= MaxDist3)
{
@@ -235,19 +238,24 @@ HRESULT CDecoder::LongLZ()
else
if (AvrLn3 > 0)
AvrLn3--;
+
len += 3;
+
if (dist >= MaxDist3)
len++;
if (dist <= 256)
len += 8;
+
if (oldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && oldAvr2 < 0x40)
MaxDist3 = 0x7f00;
else
MaxDist3 = 0x2001;
+
m_RepDists[m_RepDistPtr++] = --dist;
m_RepDistPtr &= 3;
LastLength = len;
LastDist = dist;
+
return CopyBlock(dist, len);
}
@@ -264,6 +272,7 @@ HRESULT CDecoder::HuffDecode()
else if (AvrPlc > 0x35ff) bytePlace = DecodeNum(PosHf2);
else if (AvrPlc > 0x0dff) bytePlace = DecodeNum(PosHf1);
else bytePlace = DecodeNum(PosHf0);
+
if (StMode)
{
if (--bytePlace == -1)
@@ -284,10 +293,12 @@ HRESULT CDecoder::HuffDecode()
}
else if (NumHuf++ >= 16 && FlagsCnt == 0)
StMode = 1;
+
bytePlace &= 0xff;
AvrPlc += bytePlace;
AvrPlc -= AvrPlc >> 8;
Nhfb+=16;
+
if (Nhfb > 0xff)
{
Nhfb=0x90;
diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp
index c4312f9b..6f42d2e6 100644
--- a/CPP/7zip/Compress/Rar2Decoder.cpp
+++ b/CPP/7zip/Compress/Rar2Decoder.cpp
@@ -20,19 +20,22 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte)
int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3);
Byte realValue = (Byte)(predictedValue - deltaByte);
- int i = ((int)(signed char)deltaByte) << 3;
+
+ {
+ int i = ((int)(signed char)deltaByte) << 3;
- Dif[0] += abs(i);
- Dif[1] += abs(i - D1);
- Dif[2] += abs(i + D1);
- Dif[3] += abs(i - D2);
- Dif[4] += abs(i + D2);
- Dif[5] += abs(i - D3);
- Dif[6] += abs(i + D3);
- Dif[7] += abs(i - D4);
- Dif[8] += abs(i + D4);
- Dif[9] += abs(i - channelDelta);
- Dif[10] += abs(i + channelDelta);
+ Dif[0] += abs(i);
+ Dif[1] += abs(i - D1);
+ Dif[2] += abs(i + D1);
+ Dif[3] += abs(i - D2);
+ Dif[4] += abs(i + D2);
+ Dif[5] += abs(i - D3);
+ Dif[6] += abs(i + D3);
+ Dif[7] += abs(i - D4);
+ Dif[8] += abs(i + D4);
+ Dif[9] += abs(i - channelDelta);
+ Dif[10] += abs(i + channelDelta);
+ }
channelDelta = LastDelta = (signed char)(realValue - LastChar);
LastChar = realValue;
@@ -42,7 +45,8 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte)
UInt32 minDif = Dif[0];
UInt32 numMinDif = 0;
Dif[0] = 0;
- for (i = 1; i < sizeof(Dif) / sizeof(Dif[0]); i++)
+
+ for (unsigned i = 1; i < ARRAY_SIZE(Dif); i++)
{
if (Dif[i] < minDif)
{
@@ -51,6 +55,7 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte)
}
Dif[i] = 0;
}
+
switch(numMinDif)
{
case 1: if (K1 >= -16) K1--; break;
@@ -65,14 +70,13 @@ Byte CFilter::Decode(int &channelDelta, Byte deltaByte)
case 10:if (K5 < 16) K5++; break;
}
}
+
return realValue;
}
}
static const UInt32 kHistorySize = 1 << 20;
-static const int kNumStats = 11;
-
static const UInt32 kWindowReservSize = (1 << 22) + 256;
CDecoder::CDecoder():
@@ -83,14 +87,14 @@ CDecoder::CDecoder():
void CDecoder::InitStructures()
{
m_MmFilter.Init();
- for (int i = 0; i < kNumRepDists; i++)
+ for (unsigned i = 0; i < kNumRepDists; i++)
m_RepDists[i] = 0;
m_RepDistPtr = 0;
m_LastLength = 0;
memset(m_LastLevels, 0, kMaxTableSize);
}
-UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
+UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numBits); }
#define RIF(x) { if (!(x)) return false; }
@@ -102,7 +106,9 @@ bool CDecoder::ReadTables(void)
if (ReadBits(1) == 0)
memset(m_LastLevels, 0, kMaxTableSize);
- int numLevels;
+
+ unsigned numLevels;
+
if (m_AudioMode)
{
m_NumChannels = ReadBits(2) + 1;
@@ -113,11 +119,13 @@ bool CDecoder::ReadTables(void)
else
numLevels = kHeapTablesSizesSum;
- int i;
+ unsigned i;
for (i = 0; i < kLevelTableSize; i++)
levelLevels[i] = (Byte)ReadBits(4);
RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
+
i = 0;
+
while (i < numLevels)
{
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
@@ -130,24 +138,25 @@ bool CDecoder::ReadTables(void)
{
if (number == kTableLevelRepNumber)
{
- int t = ReadBits(2) + 3;
- for (int reps = t; reps > 0 && i < numLevels ; reps--, i++)
+ unsigned t = ReadBits(2) + 3;
+ for (unsigned reps = t; reps > 0 && i < numLevels; reps--, i++)
newLevels[i] = newLevels[i - 1];
}
else
{
- int num;
+ unsigned num;
if (number == kTableLevel0Number)
num = ReadBits(3) + 3;
else if (number == kTableLevel0Number2)
num = ReadBits(7) + 11;
else
return false;
- for (;num > 0 && i < numLevels; num--)
+ for (; num > 0 && i < numLevels; num--)
newLevels[i++] = 0;
}
}
}
+
if (m_AudioMode)
for (i = 0; i < m_NumChannels; i++)
{
@@ -159,6 +168,7 @@ bool CDecoder::ReadTables(void)
RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize]));
RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize]));
}
+
memcpy(m_LastLevels, newLevels, kMaxTableSize);
return true;
}
diff --git a/CPP/7zip/Compress/Rar2Decoder.h b/CPP/7zip/Compress/Rar2Decoder.h
index 44b262c1..3a0535cc 100644
--- a/CPP/7zip/Compress/Rar2Decoder.h
+++ b/CPP/7zip/Compress/Rar2Decoder.h
@@ -18,10 +18,10 @@
namespace NCompress {
namespace NRar2 {
-const UInt32 kNumRepDists = 4;
-const UInt32 kDistTableSize = 48;
+const unsigned kNumRepDists = 4;
+const unsigned kDistTableSize = 48;
-const int kMMTableSize = 256 + 1;
+const unsigned kMMTableSize = 256 + 1;
const UInt32 kMainTableSize = 298;
const UInt32 kLenTableSize = 28;
@@ -89,14 +89,14 @@ struct CFilter
};
-const int kNumChanelsMax = 4;
+const unsigned kNumChanelsMax = 4;
class CFilter2
{
public:
CFilter m_Filters[kNumChanelsMax];
int m_ChannelDelta;
- int CurrentChannel;
+ unsigned CurrentChannel;
void Init() { memset(this, 0, sizeof(*this)); }
Byte Decode(Byte delta)
@@ -110,7 +110,7 @@ public:
typedef NBitm::CDecoder<CInBuffer> CBitDecoder;
-const int kNumHuffmanBits = 15;
+const unsigned kNumHuffmanBits = 15;
class CDecoder :
public ICompressCoder,
@@ -128,7 +128,7 @@ class CDecoder :
bool m_AudioMode;
NMultimedia::CFilter2 m_MmFilter;
- int m_NumChannels;
+ unsigned m_NumChannels;
UInt32 m_RepDists[kNumRepDists];
UInt32 m_RepDistPtr;
@@ -141,7 +141,7 @@ class CDecoder :
bool m_IsSolid;
void InitStructures();
- UInt32 ReadBits(int numBits);
+ UInt32 ReadBits(unsigned numBits);
bool ReadTables();
bool ReadLastTables();
diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp
index 3c70e1c0..f0553c85 100644
--- a/CPP/7zip/Compress/Rar3Decoder.cpp
+++ b/CPP/7zip/Compress/Rar3Decoder.cpp
@@ -15,10 +15,6 @@
namespace NCompress {
namespace NRar3 {
-static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
-static void SzBigFree(void *, void *address) { BigFree(address); }
-static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
-
static const UInt32 kNumAlignReps = 15;
static const UInt32 kSymbolReadTable = 256;
diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp
index 5b113bfa..3cbfb0e1 100644
--- a/CPP/7zip/Compress/Rar3Vm.cpp
+++ b/CPP/7zip/Compress/Rar3Vm.cpp
@@ -696,11 +696,11 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
cmd->OpCode = (ECommand)inp.ReadBits(3);
else
cmd->OpCode = (ECommand)(8 + inp.ReadBits(5));
- if (kCmdFlags[cmd->OpCode] & CF_BYTEMODE)
+ if (kCmdFlags[(unsigned)cmd->OpCode] & CF_BYTEMODE)
cmd->ByteMode = (inp.ReadBit()) ? true : false;
else
cmd->ByteMode = 0;
- int opNum = (kCmdFlags[cmd->OpCode] & CF_OPMASK);
+ int opNum = (kCmdFlags[(unsigned)cmd->OpCode] & CF_OPMASK);
if (opNum > 0)
{
DecodeArg(inp, cmd->Op1, cmd->ByteMode);
@@ -708,7 +708,7 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
DecodeArg(inp, cmd->Op2, cmd->ByteMode);
else
{
- if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[cmd->OpCode] & (CF_JUMP | CF_PROC)))
+ if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[(unsigned)cmd->OpCode] & (CF_JUMP | CF_PROC)))
{
int dist = cmd->Op1.Data;
if (dist >= 256)
@@ -784,7 +784,7 @@ kStdFilters[]=
static int FindStandardFilter(const Byte *code, UInt32 codeSize)
{
UInt32 crc = CrcCalc(code, codeSize);
- for (int i = 0; i < sizeof(kStdFilters) / sizeof(kStdFilters[0]); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(kStdFilters); i++)
{
const CStandardFilterSignature &sfs = kStdFilters[i];
if (sfs.CRC == crc && sfs.Length == codeSize)
@@ -857,6 +857,7 @@ static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos)
return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF;
}
+static const Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
{
@@ -867,7 +868,6 @@ static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
int b = (data[0] & 0x1F) - 0x10;
if (b >= 0)
{
- static Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
Byte cmdMask = kCmdMasks[b];
if (cmdMask != 0)
for (int i = 0; i < 3; i++)
@@ -993,7 +993,7 @@ static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)
{
UInt32 minDif = dif[0], numMinDif = 0;
dif[0] = 0;
- for (int j = 1; j < sizeof(dif) / sizeof(dif[0]); j++)
+ for (unsigned j = 1; j < ARRAY_SIZE(dif); j++)
{
if (dif[j] < minDif)
{
@@ -1029,7 +1029,7 @@ static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
return destPos - dataSize;
}
-void CVm::ExecuteStandardFilter(int filterIndex)
+void CVm::ExecuteStandardFilter(unsigned filterIndex)
{
UInt32 dataSize = R[4];
if (dataSize >= kGlobalOffset)
diff --git a/CPP/7zip/Compress/Rar3Vm.h b/CPP/7zip/Compress/Rar3Vm.h
index 55842b90..23f4abab 100644
--- a/CPP/7zip/Compress/Rar3Vm.h
+++ b/CPP/7zip/Compress/Rar3Vm.h
@@ -157,7 +157,7 @@ private:
bool ExecuteCode(const CProgram *prg);
#ifdef RARVM_STANDARD_FILTERS
- void ExecuteStandardFilter(int filterIndex);
+ void ExecuteStandardFilter(unsigned filterIndex);
#endif
Byte *Mem;
diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp
index e3f6a05c..66fcc9a9 100644
--- a/CPP/7zip/Compress/RarCodecsRegister.cpp
+++ b/CPP/7zip/Compress/RarCodecsRegister.cpp
@@ -8,19 +8,19 @@
#include "Rar2Decoder.h"
#include "Rar3Decoder.h"
-#define CREATE_CODEC(x) static void *CreateCodec ## x() { return (void *)(ICompressCoder *)(new NCompress::NRar ## x::CDecoder); }
+#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder())
CREATE_CODEC(1)
CREATE_CODEC(2)
CREATE_CODEC(3)
-#define RAR_CODEC(x, name) { CreateCodec ## x, 0, 0x040300 + x, L"Rar" name, 1, false }
+#define RAR_CODEC(x, name) { CreateCodec ## x, NULL, 0x40300 + x, "Rar" name, 1, false }
-static CCodecInfo g_CodecsInfo[] =
+REGISTER_CODECS_VAR
{
- RAR_CODEC(1, L"1"),
- RAR_CODEC(2, L"2"),
- RAR_CODEC(3, L"3"),
+ RAR_CODEC(1, "1"),
+ RAR_CODEC(2, "2"),
+ RAR_CODEC(3, "3"),
};
REGISTER_CODECS(Rar)
diff --git a/CPP/7zip/Crc.mak b/CPP/7zip/Crc.mak
index 7f2552c1..f2b0874c 100644
--- a/CPP/7zip/Crc.mak
+++ b/CPP/7zip/Crc.mak
@@ -1,6 +1,6 @@
C_OBJS = $(C_OBJS) \
$O\7zCrc.obj
-!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS"
+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM"
C_OBJS = $(C_OBJS) \
!ELSE
ASM_OBJS = $(ASM_OBJS) \
diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp
index 548c674b..a3c725eb 100644
--- a/CPP/7zip/Crypto/7zAes.cpp
+++ b/CPP/7zip/Crypto/7zAes.cpp
@@ -4,9 +4,12 @@
#include "../../../C/Sha256.h"
+#include "../../Common/ComTry.h"
+
+#ifndef _7ZIP_ST
#include "../../Windows/Synchronization.h"
+#endif
-#include "../Common/StreamObjects.h"
#include "../Common/StreamUtils.h"
#include "7zAes.h"
@@ -16,60 +19,71 @@
#include "RandGen.h"
#endif
-using namespace NWindows;
-
namespace NCrypto {
-namespace NSevenZ {
+namespace N7z {
+
+static const unsigned k_NumCyclesPower_Supported_MAX = 24;
bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const
{
if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)
return false;
- for (UInt32 i = 0; i < SaltSize; i++)
+ for (unsigned i = 0; i < SaltSize; i++)
if (Salt[i] != a.Salt[i])
return false;
return (Password == a.Password);
}
-void CKeyInfo::CalculateDigest()
+void CKeyInfo::CalcKey()
{
if (NumCyclesPower == 0x3F)
{
- UInt32 pos;
+ unsigned pos;
for (pos = 0; pos < SaltSize; pos++)
Key[pos] = Salt[pos];
- for (UInt32 i = 0; i < Password.Size() && pos < kKeySize; i++)
+ for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++)
Key[pos++] = Password[i];
for (; pos < kKeySize; pos++)
Key[pos] = 0;
}
else
{
+ size_t bufSize = 8 + SaltSize + Password.Size();
+ CObjArray<Byte> buf(bufSize);
+ memcpy(buf, Salt, SaltSize);
+ memcpy(buf + SaltSize, Password, Password.Size());
+
CSha256 sha;
Sha256_Init(&sha);
- const UInt64 numRounds = (UInt64)1 << NumCyclesPower;
- Byte temp[8] = { 0,0,0,0,0,0,0,0 };
- for (UInt64 round = 0; round < numRounds; round++)
+
+ Byte *ctr = buf + SaltSize + Password.Size();
+
+ for (unsigned i = 0; i < 8; i++)
+ ctr[i] = 0;
+
+ UInt64 numRounds = (UInt64)1 << NumCyclesPower;
+
+ do
{
- Sha256_Update(&sha, Salt, (size_t)SaltSize);
- Sha256_Update(&sha, Password, Password.Size());
- Sha256_Update(&sha, temp, 8);
- for (int i = 0; i < 8; i++)
- if (++(temp[i]) != 0)
+ Sha256_Update(&sha, buf, bufSize);
+ for (unsigned i = 0; i < 8; i++)
+ if (++(ctr[i]) != 0)
break;
}
+ while(--numRounds != 0);
+
Sha256_Final(&sha, Key);
}
}
-bool CKeyInfoCache::Find(CKeyInfo &key)
+bool CKeyInfoCache::GetKey(CKeyInfo &key)
{
FOR_VECTOR (i, Keys)
{
const CKeyInfo &cached = Keys[i];
if (key.IsEqualTo(cached))
{
- for (int j = 0; j < kKeySize; j++)
+ for (unsigned j = 0; j < kKeySize; j++)
key.Key[j] = cached.Key[j];
if (i != 0)
Keys.MoveToFront(i);
@@ -79,40 +93,60 @@ bool CKeyInfoCache::Find(CKeyInfo &key)
return false;
}
-void CKeyInfoCache::Add(CKeyInfo &key)
+void CKeyInfoCache::FindAndAdd(const CKeyInfo &key)
+{
+ FOR_VECTOR (i, Keys)
+ {
+ const CKeyInfo &cached = Keys[i];
+ if (key.IsEqualTo(cached))
+ {
+ if (i != 0)
+ Keys.MoveToFront(i);
+ return;
+ }
+ }
+ Add(key);
+}
+
+void CKeyInfoCache::Add(const CKeyInfo &key)
{
- if (Find(key))
- return;
if (Keys.Size() >= Size)
Keys.DeleteBack();
Keys.Insert(0, key);
}
static CKeyInfoCache g_GlobalKeyCache(32);
-static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
+
+#ifndef _7ZIP_ST
+ static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
+ #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
+#else
+ #define MT_LOCK
+#endif
CBase::CBase():
_cachedKeys(16),
_ivSize(0)
{
- for (int i = 0; i < sizeof(_iv); i++)
+ for (unsigned i = 0; i < sizeof(_iv); i++)
_iv[i] = 0;
}
-void CBase::CalculateDigest()
+void CBase::PrepareKey()
{
- NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
- if (_cachedKeys.Find(_key))
- g_GlobalKeyCache.Add(_key);
- else
+ // BCJ2 threads use same password. So we use long lock.
+ MT_LOCK
+
+ bool finded = false;
+ if (!_cachedKeys.GetKey(_key))
{
- if (!g_GlobalKeyCache.Find(_key))
- {
- _key.CalculateDigest();
- g_GlobalKeyCache.Add(_key);
- }
+ finded = g_GlobalKeyCache.GetKey(_key);
+ if (!finded)
+ _key.CalcKey();
_cachedKeys.Add(_key);
}
+ if (!finded)
+ g_GlobalKeyCache.FindAndAdd(_key);
}
#ifndef EXTRACT_ONLY
@@ -128,102 +162,114 @@ STDMETHODIMP CEncoder::ResetSalt()
STDMETHODIMP CEncoder::ResetInitVector()
{
+ for (unsigned i = 0; i < sizeof(_iv); i++)
+ _iv[i] = 0;
_ivSize = 8;
- g_RandomGenerator.Generate(_iv, (unsigned)_ivSize);
+ g_RandomGenerator.Generate(_iv, _ivSize);
return S_OK;
}
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
- // _key.Init();
- for (UInt32 i = _ivSize; i < sizeof(_iv); i++)
- _iv[i] = 0;
+ Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)];
+ unsigned propsSize = 1;
- UInt32 ivSize = _ivSize;
-
- // _key.NumCyclesPower = 0x3F;
- _key.NumCyclesPower = 19;
+ props[0] = (Byte)(_key.NumCyclesPower
+ | (_key.SaltSize == 0 ? 0 : (1 << 7))
+ | (_ivSize == 0 ? 0 : (1 << 6)));
- Byte firstByte = (Byte)(_key.NumCyclesPower |
- (((_key.SaltSize == 0) ? 0 : 1) << 7) |
- (((ivSize == 0) ? 0 : 1) << 6));
- RINOK(outStream->Write(&firstByte, 1, NULL));
- if (_key.SaltSize == 0 && ivSize == 0)
- return S_OK;
- Byte saltSizeSpec = (Byte)((_key.SaltSize == 0) ? 0 : (_key.SaltSize - 1));
- Byte ivSizeSpec = (Byte)((ivSize == 0) ? 0 : (ivSize - 1));
- Byte secondByte = (Byte)(((saltSizeSpec) << 4) | ivSizeSpec);
- RINOK(outStream->Write(&secondByte, 1, NULL));
- if (_key.SaltSize > 0)
+ if (_key.SaltSize != 0 || _ivSize != 0)
{
- RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize));
+ props[1] = (Byte)(
+ ((_key.SaltSize == 0 ? 0 : _key.SaltSize - 1) << 4)
+ | (_ivSize == 0 ? 0 : _ivSize - 1));
+ memcpy(props + 2, _key.Salt, _key.SaltSize);
+ propsSize = 2 + _key.SaltSize;
+ memcpy(props + propsSize, _iv, _ivSize);
+ propsSize += _ivSize;
}
- if (ivSize > 0)
- {
- RINOK(WriteStream(outStream, _iv, ivSize));
- }
- return S_OK;
+
+ return WriteStream(outStream, props, propsSize);
}
-HRESULT CEncoder::CreateFilter()
+CEncoder::CEncoder()
{
+ // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
+ // _key.NumCyclesPower = 0x3F;
+ _key.NumCyclesPower = 19;
_aesFilter = new CAesCbcEncoder(kKeySize);
- return S_OK;
}
#endif
+CDecoder::CDecoder()
+{
+ _aesFilter = new CAesCbcDecoder(kKeySize);
+}
+
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
- _key.Init();
- UInt32 i;
+ _key.ClearProps();
+
+ _ivSize = 0;
+ unsigned i;
for (i = 0; i < sizeof(_iv); i++)
_iv[i] = 0;
+
if (size == 0)
return S_OK;
- UInt32 pos = 0;
- Byte firstByte = data[pos++];
+
+ Byte b0 = data[0];
- _key.NumCyclesPower = firstByte & 0x3F;
- if ((firstByte & 0xC0) == 0)
- return S_OK;
- _key.SaltSize = (firstByte >> 7) & 1;
- UInt32 ivSize = (firstByte >> 6) & 1;
+ _key.NumCyclesPower = b0 & 0x3F;
+ if ((b0 & 0xC0) == 0)
+ return size == 1 ? S_OK : E_INVALIDARG;
- if (pos >= size)
+ if (size <= 1)
return E_INVALIDARG;
- Byte secondByte = data[pos++];
-
- _key.SaltSize += (secondByte >> 4);
- ivSize += (secondByte & 0x0F);
+
+ Byte b1 = data[1];
+
+ unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4);
+ unsigned ivSize = ((b0 >> 6) & 1) + (b1 & 0x0F);
- if (pos + _key.SaltSize + ivSize > size)
+ if (size != 2 + saltSize + ivSize)
return E_INVALIDARG;
- for (i = 0; i < _key.SaltSize; i++)
- _key.Salt[i] = data[pos++];
+ _key.SaltSize = saltSize;
+ data += 2;
+ for (i = 0; i < saltSize; i++)
+ _key.Salt[i] = *data++;
for (i = 0; i < ivSize; i++)
- _iv[i] = data[pos++];
- return (_key.NumCyclesPower <= 24) ? S_OK : E_NOTIMPL;
+ _iv[i] = *data++;
+ return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX
+ || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL;
}
+
STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
+ COM_TRY_BEGIN
+
_key.Password.CopyFrom(data, (size_t)size);
return S_OK;
+
+ COM_TRY_END
}
STDMETHODIMP CBaseCoder::Init()
{
- CalculateDigest();
- if (_aesFilter == 0)
- {
- RINOK(CreateFilter());
- }
+ COM_TRY_BEGIN
+
+ PrepareKey();
CMyComPtr<ICryptoProperties> cp;
RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
- RINOK(cp->SetKey(_key.Key, sizeof(_key.Key)));
+ if (!cp)
+ return E_FAIL;
+ RINOK(cp->SetKey(_key.Key, kKeySize));
RINOK(cp->SetInitVector(_iv, sizeof(_iv)));
return _aesFilter->Init();
+
+ COM_TRY_END
}
STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)
@@ -231,10 +277,4 @@ STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)
return _aesFilter->Filter(data, size);
}
-HRESULT CDecoder::CreateFilter()
-{
- _aesFilter = new CAesCbcDecoder(kKeySize);
- return S_OK;
-}
-
}}
diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h
index 560af5c2..4bd7d291 100644
--- a/CPP/7zip/Crypto/7zAes.h
+++ b/CPP/7zip/Crypto/7zAes.h
@@ -11,28 +11,30 @@
#include "../IPassword.h"
namespace NCrypto {
-namespace NSevenZ {
+namespace N7z {
-const int kKeySize = 32;
+const unsigned kKeySize = 32;
+const unsigned kSaltSizeMax = 16;
+const unsigned kIvSizeMax = 16; // AES_BLOCK_SIZE;
class CKeyInfo
{
public:
- int NumCyclesPower;
- UInt32 SaltSize;
- Byte Salt[16];
+ unsigned NumCyclesPower;
+ unsigned SaltSize;
+ Byte Salt[kSaltSizeMax];
CByteBuffer Password;
Byte Key[kKeySize];
bool IsEqualTo(const CKeyInfo &a) const;
- void CalculateDigest();
+ void CalcKey();
- CKeyInfo() { Init(); }
- void Init()
+ CKeyInfo() { ClearProps(); }
+ void ClearProps()
{
NumCyclesPower = 0;
SaltSize = 0;
- for (int i = 0; i < sizeof(Salt); i++)
+ for (unsigned i = 0; i < sizeof(Salt); i++)
Salt[i] = 0;
}
};
@@ -43,9 +45,9 @@ class CKeyInfoCache
CObjectVector<CKeyInfo> Keys;
public:
CKeyInfoCache(unsigned size): Size(size) {}
- bool Find(CKeyInfo &key);
- // HRESULT Calculate(CKeyInfo &key);
- void Add(CKeyInfo &key);
+ bool GetKey(CKeyInfo &key);
+ void Add(const CKeyInfo &key);
+ void FindAndAdd(const CKeyInfo &key);
};
class CBase
@@ -53,9 +55,10 @@ class CBase
CKeyInfoCache _cachedKeys;
protected:
CKeyInfo _key;
- Byte _iv[16];
- UInt32 _ivSize;
- void CalculateDigest();
+ Byte _iv[kIvSizeMax];
+ unsigned _ivSize;
+
+ void PrepareKey();
CBase();
};
@@ -68,13 +71,8 @@ class CBaseCoder:
protected:
CMyComPtr<ICompressFilter> _aesFilter;
- virtual HRESULT CreateFilter() = 0;
- #ifndef CRYPTO_AES
- HRESULT CreateFilterFromDLL(REFCLSID clsID);
- #endif
public:
- STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+ INTERFACE_ICompressFilter(;)
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
};
@@ -87,7 +85,6 @@ class CEncoder:
// public ICryptoResetSalt,
public ICryptoResetInitVector
{
- virtual HRESULT CreateFilter();
public:
MY_UNKNOWN_IMP3(
ICryptoSetPassword,
@@ -97,19 +94,21 @@ public:
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
// STDMETHOD(ResetSalt)();
STDMETHOD(ResetInitVector)();
+ CEncoder();
};
+
#endif
class CDecoder:
public CBaseCoder,
public ICompressSetDecoderProperties2
{
- virtual HRESULT CreateFilter();
public:
MY_UNKNOWN_IMP2(
ICryptoSetPassword,
ICompressSetDecoderProperties2)
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+ CDecoder();
};
}}
diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp
index 5e57748f..7debc7d1 100644
--- a/CPP/7zip/Crypto/7zAesRegister.cpp
+++ b/CPP/7zip/Crypto/7zAesRegister.cpp
@@ -3,16 +3,10 @@
#include "StdAfx.h"
#include "../Common/RegisterCodec.h"
-#include "7zAes.h"
-
-static void *CreateCodec() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CDecoder()); }
-#ifndef EXTRACT_ONLY
-static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new NCrypto::NSevenZ::CEncoder()); }
-#else
-#define CreateCodecOut 0
-#endif
-static CCodecInfo g_CodecInfo =
- { CreateCodec, CreateCodecOut, 0x06F10701, L"7zAES", 1, true };
+#include "7zAes.h"
-REGISTER_CODEC(7zAES)
+REGISTER_FILTER_E(7zAES,
+ NCrypto::N7z::CDecoder(),
+ NCrypto::N7z::CEncoder(),
+ 0x6F10701, "7zAES") \ No newline at end of file
diff --git a/CPP/7zip/Crypto/HmacSha1.cpp b/CPP/7zip/Crypto/HmacSha1.cpp
index a66d6271..359b65bc 100644
--- a/CPP/7zip/Crypto/HmacSha1.cpp
+++ b/CPP/7zip/Crypto/HmacSha1.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../C/CpuArch.h"
+
#include "HmacSha1.h"
namespace NCrypto {
@@ -11,24 +13,29 @@ void CHmac::SetKey(const Byte *key, size_t keySize)
{
Byte keyTemp[kBlockSize];
size_t i;
+
for (i = 0; i < kBlockSize; i++)
keyTemp[i] = 0;
- if(keySize > kBlockSize)
+
+ if (keySize > kBlockSize)
{
_sha.Init();
_sha.Update(key, keySize);
_sha.Final(keyTemp);
- keySize = kDigestSize;
}
else
for (i = 0; i < keySize; i++)
keyTemp[i] = key[i];
+
for (i = 0; i < kBlockSize; i++)
keyTemp[i] ^= 0x36;
+
_sha.Init();
_sha.Update(keyTemp, kBlockSize);
+
for (i = 0; i < kBlockSize; i++)
keyTemp[i] ^= 0x36 ^ 0x5C;
+
_sha2.Init();
_sha2.Update(keyTemp, kBlockSize);
}
@@ -39,18 +46,20 @@ void CHmac::Final(Byte *mac, size_t macSize)
_sha.Final(digest);
_sha2.Update(digest, kDigestSize);
_sha2.Final(digest);
- for(size_t i = 0; i < macSize; i++)
+ for (size_t i = 0; i < macSize; i++)
mac[i] = digest[i];
}
void CHmac32::SetKey(const Byte *key, size_t keySize)
{
- UInt32 keyTemp[kBlockSizeInWords];
+ UInt32 keyTemp[kNumBlockWords];
size_t i;
- for (i = 0; i < kBlockSizeInWords; i++)
+
+ for (i = 0; i < kNumBlockWords; i++)
keyTemp[i] = 0;
- if(keySize > kBlockSize)
+
+ if (keySize > kBlockSize)
{
CContext sha;
sha.Init();
@@ -58,50 +67,52 @@ void CHmac32::SetKey(const Byte *key, size_t keySize)
Byte digest[kDigestSize];
sha.Final(digest);
- for (int i = 0 ; i < kDigestSizeInWords; i++)
- keyTemp[i] =
- ((UInt32)(digest[i * 4 + 0]) << 24) |
- ((UInt32)(digest[i * 4 + 1]) << 16) |
- ((UInt32)(digest[i * 4 + 2]) << 8) |
- ((UInt32)(digest[i * 4 + 3]));
- keySize = kDigestSizeInWords;
+ for (i = 0 ; i < kNumDigestWords; i++)
+ keyTemp[i] = GetBe32(digest + i * 4 + 0);
}
else
- for (size_t i = 0; i < keySize; i++)
+ for (i = 0; i < keySize; i++)
keyTemp[i / 4] |= (key[i] << (24 - 8 * (i & 3)));
- for (i = 0; i < kBlockSizeInWords; i++)
+
+ for (i = 0; i < kNumBlockWords; i++)
keyTemp[i] ^= 0x36363636;
+
_sha.Init();
- _sha.Update(keyTemp, kBlockSizeInWords);
- for (i = 0; i < kBlockSizeInWords; i++)
+ _sha.Update(keyTemp, kNumBlockWords);
+
+ for (i = 0; i < kNumBlockWords; i++)
keyTemp[i] ^= 0x36363636 ^ 0x5C5C5C5C;
+
_sha2.Init();
- _sha2.Update(keyTemp, kBlockSizeInWords);
+ _sha2.Update(keyTemp, kNumBlockWords);
}
void CHmac32::Final(UInt32 *mac, size_t macSize)
{
- UInt32 digest[kDigestSizeInWords];
+ UInt32 digest[kNumDigestWords];
_sha.Final(digest);
- _sha2.Update(digest, kDigestSizeInWords);
+ _sha2.Update(digest, kNumDigestWords);
_sha2.Final(digest);
- for(size_t i = 0; i < macSize; i++)
+ for (size_t i = 0; i < macSize; i++)
mac[i] = digest[i];
}
void CHmac32::GetLoopXorDigest(UInt32 *mac, UInt32 numIteration)
{
- UInt32 block[kBlockSizeInWords];
- UInt32 block2[kBlockSizeInWords];
- _sha.PrepareBlock(block, kDigestSizeInWords);
- _sha2.PrepareBlock(block2, kDigestSizeInWords);
- for(unsigned int s = 0; s < kDigestSizeInWords; s++)
+ UInt32 block[kNumBlockWords];
+ UInt32 block2[kNumBlockWords];
+
+ _sha.PrepareBlock(block, kNumDigestWords);
+ _sha2.PrepareBlock(block2, kNumDigestWords);
+
+ for (unsigned s = 0; s < kNumDigestWords; s++)
block[s] = mac[s];
- for(UInt32 i = 0; i < numIteration; i++)
+
+ for (UInt32 i = 0; i < numIteration; i++)
{
_sha.GetBlockDigest(block, block2);
_sha2.GetBlockDigest(block2, block);
- for (unsigned int s = 0; s < kDigestSizeInWords; s++)
+ for (unsigned s = 0; s < kNumDigestWords; s++)
mac[s] ^= block[s];
}
}
diff --git a/CPP/7zip/Crypto/HmacSha1.h b/CPP/7zip/Crypto/HmacSha1.h
index d7181329..6ba015e8 100644
--- a/CPP/7zip/Crypto/HmacSha1.h
+++ b/CPP/7zip/Crypto/HmacSha1.h
@@ -4,7 +4,7 @@
#ifndef __CRYPTO_HMAC_SHA1_H
#define __CRYPTO_HMAC_SHA1_H
-#include "Sha1.h"
+#include "Sha1Cls.h"
namespace NCrypto {
namespace NSha1 {
@@ -28,9 +28,9 @@ class CHmac32
public:
void SetKey(const Byte *key, size_t keySize);
void Update(const UInt32 *data, size_t dataSize) { _sha.Update(data, dataSize); }
- void Final(UInt32 *mac, size_t macSize = kDigestSizeInWords);
+ void Final(UInt32 *mac, size_t macSize = kNumDigestWords);
- // It'sa for hmac function. in,out: mac[kDigestSizeInWords].
+ // It'sa for hmac function. in,out: mac[kNumDigestWords].
void GetLoopXorDigest(UInt32 *mac, UInt32 numIteration);
};
diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h
index 99a17fef..289935eb 100644
--- a/CPP/7zip/Crypto/MyAes.h
+++ b/CPP/7zip/Crypto/MyAes.h
@@ -26,13 +26,17 @@ class CAesCbcCoder:
Byte _iv[AES_BLOCK_SIZE];
bool SetFunctions(UInt32 algo);
+
public:
CAesCbcCoder(bool encodeMode, unsigned keySize);
+
MY_UNKNOWN_IMP2(ICryptoProperties, ICompressSetCoderProperties)
- STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+
+ INTERFACE_ICompressFilter(;)
+
STDMETHOD(SetKey)(const Byte *data, UInt32 size);
STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);
+
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
};
@@ -46,7 +50,6 @@ struct CAesCbcDecoder: public CAesCbcCoder
CAesCbcDecoder(unsigned keySize = 0): CAesCbcCoder(false, keySize) {}
};
-
}
#endif
diff --git a/CPP/7zip/Crypto/MyAesReg.cpp b/CPP/7zip/Crypto/MyAesReg.cpp
index faaa104b..91d62b94 100644
--- a/CPP/7zip/Crypto/MyAesReg.cpp
+++ b/CPP/7zip/Crypto/MyAesReg.cpp
@@ -6,14 +6,7 @@
#include "MyAes.h"
-static void *CreateCodecCbc() { return (void *)(ICompressFilter *)(new NCrypto::CAesCbcDecoder(32)); }
-#ifndef EXTRACT_ONLY
-static void *CreateCodecCbcOut() { return (void *)(ICompressFilter *)(new NCrypto::CAesCbcEncoder(32)); }
-#else
-#define CreateCodecCbcOut 0
-#endif
-
-static CCodecInfo g_CodecInfo =
- { CreateCodecCbc, CreateCodecCbcOut, 0x06F00181, L"AES256CBC", 1, true };
-REGISTER_CODEC(AES256CBC)
-
+REGISTER_FILTER_E(AES256CBC,
+ NCrypto::CAesCbcDecoder(32),
+ NCrypto::CAesCbcEncoder(32),
+ 0x6F00181, "AES256CBC") \ No newline at end of file
diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp
index cbbdec89..a7fcb728 100644
--- a/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp
+++ b/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp
@@ -2,26 +2,34 @@
#include "StdAfx.h"
+#include "../../../C/CpuArch.h"
+
#include "HmacSha1.h"
namespace NCrypto {
namespace NSha1 {
-void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize,
- UInt32 numIterations, Byte *key, size_t keySize)
+void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize,
+ const Byte *salt, size_t saltSize,
+ UInt32 numIterations,
+ Byte *key, size_t keySize)
{
CHmac baseCtx;
baseCtx.SetKey(pwd, pwdSize);
- for (UInt32 i = 1; keySize > 0; i++)
+
+ for (UInt32 i = 1; keySize != 0; i++)
{
CHmac ctx = baseCtx;
ctx.Update(salt, saltSize);
- Byte u[kDigestSize] = { (Byte)(i >> 24), (Byte)(i >> 16), (Byte)(i >> 8), (Byte)(i) };
- const unsigned int curSize = (keySize < kDigestSize) ? (unsigned int)keySize : kDigestSize;
+
+ Byte u[kDigestSize];
+ SetBe32(u, i);
+
ctx.Update(u, 4);
ctx.Final(u, kDigestSize);
- unsigned int s;
+ const unsigned curSize = (keySize < kDigestSize) ? (unsigned)keySize : kDigestSize;
+ unsigned s;
for (s = 0; s < curSize; s++)
key[s] = u[s];
@@ -39,26 +47,32 @@ void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSi
}
}
-void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize,
- UInt32 numIterations, UInt32 *key, size_t keySize)
+void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize,
+ const UInt32 *salt, size_t saltSize,
+ UInt32 numIterations,
+ UInt32 *key, size_t keySize)
{
CHmac32 baseCtx;
baseCtx.SetKey(pwd, pwdSize);
- for (UInt32 i = 1; keySize > 0; i++)
+
+ for (UInt32 i = 1; keySize != 0; i++)
{
CHmac32 ctx = baseCtx;
ctx.Update(salt, saltSize);
- UInt32 u[kDigestSizeInWords] = { i };
- const unsigned int curSize = (keySize < kDigestSizeInWords) ? (unsigned int)keySize : kDigestSizeInWords;
+
+ UInt32 u[kNumDigestWords];
+ u[0] = i;
+
ctx.Update(u, 1);
- ctx.Final(u, kDigestSizeInWords);
+ ctx.Final(u, kNumDigestWords);
// Speed-optimized code start
ctx = baseCtx;
ctx.GetLoopXorDigest(u, numIterations - 1);
// Speed-optimized code end
- unsigned int s;
+ const unsigned curSize = (keySize < kNumDigestWords) ? (unsigned)keySize : kNumDigestWords;
+ unsigned s;
for (s = 0; s < curSize; s++)
key[s] = u[s];
@@ -67,8 +81,8 @@ void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t sa
for (UInt32 j = numIterations; j > 1; j--)
{
ctx = baseCtx;
- ctx.Update(u, kDigestSizeInWords);
- ctx.Final(u, kDigestSizeInWords);
+ ctx.Update(u, kNumDigestWords);
+ ctx.Final(u, kNumDigestWords);
for (s = 0; s < curSize; s++)
key[s] ^= u[s];
}
diff --git a/CPP/7zip/Crypto/RandGen.cpp b/CPP/7zip/Crypto/RandGen.cpp
index 0ed65a30..f5ea31f0 100644
--- a/CPP/7zip/Crypto/RandGen.cpp
+++ b/CPP/7zip/Crypto/RandGen.cpp
@@ -2,7 +2,9 @@
#include "StdAfx.h"
+#ifndef _7ZIP_ST
#include "../../Windows/Synchronization.h"
+#endif
#include "RandGen.h"
@@ -85,14 +87,20 @@ void CRandomGenerator::Init()
_needInit = false;
}
-static NWindows::NSynchronization::CCriticalSection g_CriticalSection;
+#ifndef _7ZIP_ST
+ static NWindows::NSynchronization::CCriticalSection g_CriticalSection;
+ #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+ #define MT_LOCK
+#endif
void CRandomGenerator::Generate(Byte *data, unsigned size)
{
- g_CriticalSection.Enter();
+ MT_LOCK
+
if (_needInit)
Init();
- while (size > 0)
+ while (size != 0)
{
CSha256 hash;
@@ -106,10 +114,9 @@ void CRandomGenerator::Generate(Byte *data, unsigned size)
Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
Byte buff[SHA256_DIGEST_SIZE];
Sha256_Final(&hash, buff);
- for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size > 0; i++, size--)
+ for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--)
*data++ = buff[i];
}
- g_CriticalSection.Leave();
}
CRandomGenerator g_RandomGenerator;
diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp
index c2df0e52..1523151d 100644
--- a/CPP/7zip/Crypto/Rar20Crypto.cpp
+++ b/CPP/7zip/Crypto/Rar20Crypto.cpp
@@ -11,9 +11,9 @@
namespace NCrypto {
namespace NRar20 {
-static const int kNumRounds = 32;
+static const unsigned kNumRounds = 32;
-static const Byte InitSubstTable[256] = {
+static const Byte g_InitSubstTable[256] = {
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
@@ -34,8 +34,8 @@ static const Byte InitSubstTable[256] = {
void CData::UpdateKeys(const Byte *data)
{
- for (int i = 0; i < 16; i += 4)
- for (int j = 0; j < 4; j++)
+ for (unsigned i = 0; i < 16; i += 4)
+ for (unsigned j = 0; j < 4; j++)
Keys[j] ^= g_CrcTable[data[i + j]];
}
@@ -46,7 +46,7 @@ static void Swap(Byte *b1, Byte *b2)
*b2 = b;
}
-void CData::SetPassword(const Byte *password, UInt32 passwordLen)
+void CData::SetPassword(const Byte *data, UInt32 size)
{
Keys[0] = 0xD3A3B879L;
Keys[1] = 0x3F6D12F7L;
@@ -54,19 +54,22 @@ void CData::SetPassword(const Byte *password, UInt32 passwordLen)
Keys[3] = 0xA4E7F123L;
Byte psw[256];
+ if (size >= sizeof(psw))
+ size = sizeof(psw) - 1;
memset(psw, 0, sizeof(psw));
- memcpy(psw, password, passwordLen);
- memcpy(SubstTable, InitSubstTable, sizeof(SubstTable));
+ if (size != 0)
+ memcpy(psw, data, size);
+ memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable));
for (UInt32 j = 0; j < 256; j++)
- for (UInt32 i = 0; i < passwordLen; i += 2)
+ for (UInt32 i = 0; i < size; i += 2)
{
UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++)
Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]);
}
- for (UInt32 i = 0; i < passwordLen; i+= 16)
+ for (UInt32 i = 0; i < size; i += 16)
EncryptBlock(&psw[i]);
}
@@ -83,7 +86,7 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
if (!encrypt)
memcpy(inBuf, buf, sizeof(inBuf));
- for (int i = 0; i < kNumRounds; i++)
+ for (unsigned i = 0; i < kNumRounds; i++)
{
UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];
T = ((C + rotlFixed(D, 11)) ^ key);
diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h
index 1b6d6024..b0445932 100644
--- a/CPP/7zip/Crypto/Rar20Crypto.h
+++ b/CPP/7zip/Crypto/Rar20Crypto.h
@@ -11,17 +11,20 @@
namespace NCrypto {
namespace NRar20 {
+/* ICompressFilter::Init() does nothing for this filter.
+ Call CryptoSetPassword() to initialize filter. */
+
class CData
{
Byte SubstTable[256];
UInt32 Keys[4];
- UInt32 SubstLong(UInt32 t)
+ UInt32 SubstLong(UInt32 t) const
{
- return (UInt32)SubstTable[(int)t & 255] |
- ((UInt32)SubstTable[(int)(t >> 8) & 255] << 8) |
- ((UInt32)SubstTable[(int)(t >> 16) & 255] << 16) |
- ((UInt32)SubstTable[(int)(t >> 24) & 255] << 24);
+ return (UInt32)SubstTable[(unsigned)t & 255]
+ | ((UInt32)SubstTable[(unsigned)(t >> 8) & 255] << 8)
+ | ((UInt32)SubstTable[(unsigned)(t >> 16) & 255] << 16)
+ | ((UInt32)SubstTable[(unsigned)(t >> 24) & 255] << 24);
}
void UpdateKeys(const Byte *data);
void CryptBlock(Byte *buf, bool encrypt);
@@ -34,7 +37,8 @@ public:
class CDecoder:
public ICompressFilter,
public ICryptoSetPassword,
- public CMyUnknownImp
+ public CMyUnknownImp,
+ public CData
{
CData _cipher;
public:
diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp
index e8f716d9..f562023a 100644
--- a/CPP/7zip/Crypto/RarAes.cpp
+++ b/CPP/7zip/Crypto/RarAes.cpp
@@ -4,32 +4,36 @@
#include "StdAfx.h"
#include "RarAes.h"
-#include "Sha1.h"
+#include "Sha1Cls.h"
namespace NCrypto {
namespace NRar29 {
CDecoder::CDecoder():
- CAesCbcDecoder(kRarAesKeySize),
- _thereIsSalt(false),
- _needCalculate(true),
- _rar350Mode(false)
+ CAesCbcDecoder(kRarAesKeySize),
+ _thereIsSalt(false),
+ _needCalc(true),
+ _rar350Mode(false)
{
- for (int i = 0; i < sizeof(_salt); i++)
+ for (unsigned i = 0; i < sizeof(_salt); i++)
_salt[i] = 0;
}
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
- bool thereIsSaltPrev = _thereIsSalt;
+ bool prev = _thereIsSalt;
_thereIsSalt = false;
if (size == 0)
+ {
+ if (!_needCalc && prev)
+ _needCalc = true;
return S_OK;
+ }
if (size < 8)
return E_INVALIDARG;
_thereIsSalt = true;
bool same = false;
- if (_thereIsSalt == thereIsSaltPrev)
+ if (_thereIsSalt == prev)
{
same = true;
if (_thereIsSalt)
@@ -44,91 +48,88 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
}
for (unsigned i = 0; i < sizeof(_salt); i++)
_salt[i] = data[i];
- if (!_needCalculate && !same)
- _needCalculate = true;
+ if (!_needCalc && !same)
+ _needCalc = true;
return S_OK;
}
-static const unsigned kMaxPasswordLength = 127 * 2;
+static const unsigned kPasswordLen_MAX = 127 * 2;
STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
{
- if (size > kMaxPasswordLength)
- size = kMaxPasswordLength;
+ if (size > kPasswordLen_MAX)
+ size = kPasswordLen_MAX;
bool same = false;
- if (size == buffer.Size())
+ if (size == _password.Size())
{
same = true;
for (UInt32 i = 0; i < size; i++)
- if (data[i] != buffer[i])
+ if (data[i] != _password[i])
{
same = false;
break;
}
}
- if (!_needCalculate && !same)
- _needCalculate = true;
- buffer.CopyFrom(data, (size_t)size);
+ if (!_needCalc && !same)
+ _needCalc = true;
+ _password.CopyFrom(data, (size_t)size);
return S_OK;
}
STDMETHODIMP CDecoder::Init()
{
- Calculate();
- RINOK(SetKey(aesKey, kRarAesKeySize));
- RINOK(SetInitVector(_aesInit, AES_BLOCK_SIZE));
+ CalcKey();
+ RINOK(SetKey(_key, kRarAesKeySize));
+ RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
return CAesCbcCoder::Init();
}
-void CDecoder::Calculate()
+void CDecoder::CalcKey()
{
- if (_needCalculate)
- {
- const unsigned kSaltSize = 8;
-
- Byte rawPassword[kMaxPasswordLength + kSaltSize];
-
- memcpy(rawPassword, buffer, buffer.Size());
-
- size_t rawLength = buffer.Size();
-
- if (_thereIsSalt)
- {
- memcpy(rawPassword + rawLength, _salt, kSaltSize);
- rawLength += kSaltSize;
- }
-
- NSha1::CContext sha;
- sha.Init();
+ if (!_needCalc)
+ return;
- // rar reverts hash for sha.
- const unsigned kNumRounds = (1 << 18);
- unsigned i;
- for (i = 0; i < kNumRounds; i++)
+ const unsigned kSaltSize = 8;
+
+ Byte buf[kPasswordLen_MAX + kSaltSize];
+
+ if (_password.Size() != 0)
+ memcpy(buf, _password, _password.Size());
+
+ size_t rawSize = _password.Size();
+
+ if (_thereIsSalt)
+ {
+ memcpy(buf + rawSize, _salt, kSaltSize);
+ rawSize += kSaltSize;
+ }
+
+ NSha1::CContext sha;
+ sha.Init();
+
+ Byte digest[NSha1::kDigestSize];
+ // rar reverts hash for sha.
+ const UInt32 kNumRounds = (1 << 18);
+ UInt32 i;
+ for (i = 0; i < kNumRounds; i++)
+ {
+ sha.UpdateRar(buf, rawSize, _rar350Mode);
+ Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
+ sha.UpdateRar(pswNum, 3, _rar350Mode);
+ if (i % (kNumRounds / 16) == 0)
{
- sha.UpdateRar(rawPassword, rawLength, _rar350Mode);
- Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
- sha.UpdateRar(pswNum, 3, _rar350Mode);
- if (i % (kNumRounds / 16) == 0)
- {
- NSha1::CContext shaTemp = sha;
- Byte digest[NSha1::kDigestSize];
- shaTemp.Final(digest);
- _aesInit[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3];
- }
+ NSha1::CContext shaTemp = sha;
+ shaTemp.Final(digest);
+ _iv[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3];
}
- /*
- // it's test message for sha
- const char *message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
- sha.Update((const Byte *)message, strlen(message));
- */
- Byte digest[20];
- sha.Final(digest);
- for (i = 0; i < 4; i++)
- for (unsigned j = 0; j < 4; j++)
- aesKey[i * 4 + j] = (digest[i * 4 + 3 - j]);
}
- _needCalculate = false;
+
+ sha.Final(digest);
+ for (i = 0; i < 4; i++)
+ for (unsigned j = 0; j < 4; j++)
+ _key[i * 4 + j] = (digest[i * 4 + 3 - j]);
+
+ _needCalc = false;
}
}}
diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h
index 9d9ee127..197a0b2d 100644
--- a/CPP/7zip/Crypto/RarAes.h
+++ b/CPP/7zip/Crypto/RarAes.h
@@ -18,22 +18,24 @@ const UInt32 kRarAesKeySize = 16;
class CDecoder:
public CAesCbcDecoder,
- public ICompressSetDecoderProperties2,
+ // public ICompressSetDecoderProperties2,
public ICryptoSetPassword
{
Byte _salt[8];
bool _thereIsSalt;
- CByteBuffer buffer;
- Byte aesKey[kRarAesKeySize];
- Byte _aesInit[AES_BLOCK_SIZE];
- bool _needCalculate;
+ bool _needCalc;
bool _rar350Mode;
+
+ CByteBuffer _password;
+
+ Byte _key[kRarAesKeySize];
+ Byte _iv[AES_BLOCK_SIZE];
- void Calculate();
+ void CalcKey();
public:
- MY_UNKNOWN_IMP2(
- ICryptoSetPassword,
- ICompressSetDecoderProperties2)
+ MY_UNKNOWN_IMP1(
+ ICryptoSetPassword)
+ // ICompressSetDecoderProperties2
STDMETHOD(Init)();
STDMETHOD(CryptoSetPassword)(const Byte *aData, UInt32 aSize);
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
diff --git a/CPP/7zip/Crypto/Sha1.cpp b/CPP/7zip/Crypto/Sha1.cpp
deleted file mode 100644
index 2f284071..00000000
--- a/CPP/7zip/Crypto/Sha1.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-// Crypto/Sha1.cpp
-// This file is based on public domain
-// Steve Reid and Wei Dai's code from Crypto++
-
-#include "StdAfx.h"
-
-#include "../../../C/RotateDefs.h"
-
-#include "Sha1.h"
-
-namespace NCrypto {
-namespace NSha1 {
-
-// define it for speed optimization
-// #define _SHA1_UNROLL
-
-static const unsigned kNumW =
- #ifdef _SHA1_UNROLL
- 16;
- #else
- 80;
- #endif
-
-
-#define w0(i) (W[(i)] = data[(i)])
-
-#ifdef _SHA1_UNROLL
-#define w1(i) (W[(i)&15] = rotlFixed(W[((i)-3)&15] ^ W[((i)-8)&15] ^ W[((i)-14)&15] ^ W[((i)-16)&15], 1))
-#else
-#define w1(i) (W[(i)] = rotlFixed(W[(i)-3] ^ W[(i)-8] ^ W[(i)-14] ^ W[(i)-16], 1))
-#endif
-
-#define f1(x,y,z) (z^(x&(y^z)))
-#define f2(x,y,z) (x^y^z)
-#define f3(x,y,z) ((x&y)|(z&(x|y)))
-#define f4(x,y,z) (x^y^z)
-
-#define RK1(a,b,c,d,e,i, f, w, k) e += f(b,c,d) + w(i) + k + rotlFixed(a,5); b = rotlFixed(b,30);
-
-#define R0(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w0, 0x5A827999)
-#define R1(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f1, w1, 0x5A827999)
-#define R2(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f2, w1, 0x6ED9EBA1)
-#define R3(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f3, w1, 0x8F1BBCDC)
-#define R4(a,b,c,d,e,i) RK1(a,b,c,d,e,i, f4, w1, 0xCA62C1D6)
-
-#define RX_1_4(rx1, rx4, i) rx1(a,b,c,d,e,i); rx4(e,a,b,c,d,i+1); rx4(d,e,a,b,c,i+2); rx4(c,d,e,a,b,i+3); rx4(b,c,d,e,a,i+4);
-#define RX_5(rx, i) RX_1_4(rx, rx, i);
-
-void CContextBase::Init()
-{
- _state[0] = 0x67452301;
- _state[1] = 0xEFCDAB89;
- _state[2] = 0x98BADCFE;
- _state[3] = 0x10325476;
- _state[4] = 0xC3D2E1F0;
- _count = 0;
-}
-
-void CContextBase::GetBlockDigest(UInt32 *data, UInt32 *destDigest, bool returnRes)
-{
- UInt32 a, b, c, d, e;
- UInt32 W[kNumW];
-
- a = _state[0];
- b = _state[1];
- c = _state[2];
- d = _state[3];
- e = _state[4];
- #ifdef _SHA1_UNROLL
- RX_5(R0, 0); RX_5(R0, 5); RX_5(R0, 10);
- #else
- int i;
- for (i = 0; i < 15; i += 5) { RX_5(R0, i); }
- #endif
-
- RX_1_4(R0, R1, 15);
-
-
- #ifdef _SHA1_UNROLL
- RX_5(R2, 20); RX_5(R2, 25); RX_5(R2, 30); RX_5(R2, 35);
- RX_5(R3, 40); RX_5(R3, 45); RX_5(R3, 50); RX_5(R3, 55);
- RX_5(R4, 60); RX_5(R4, 65); RX_5(R4, 70); RX_5(R4, 75);
- #else
- i = 20;
- for (; i < 40; i += 5) { RX_5(R2, i); }
- for (; i < 60; i += 5) { RX_5(R3, i); }
- for (; i < 80; i += 5) { RX_5(R4, i); }
- #endif
-
- destDigest[0] = _state[0] + a;
- destDigest[1] = _state[1] + b;
- destDigest[2] = _state[2] + c;
- destDigest[3] = _state[3] + d;
- destDigest[4] = _state[4] + e;
-
- if (returnRes)
- for (int i = 0 ; i < 16; i++)
- data[i] = W[kNumW - 16 + i];
-
- // Wipe variables
- // a = b = c = d = e = 0;
-}
-
-void CContextBase::PrepareBlock(UInt32 *block, unsigned size) const
-{
- unsigned curBufferPos = size & 0xF;
- block[curBufferPos++] = 0x80000000;
- while (curBufferPos != (16 - 2))
- block[curBufferPos++] = 0;
- const UInt64 lenInBits = (_count << 9) + ((UInt64)size << 5);
- block[curBufferPos++] = (UInt32)(lenInBits >> 32);
- block[curBufferPos++] = (UInt32)(lenInBits);
-}
-
-void CContext::Update(const Byte *data, size_t size)
-{
- unsigned curBufferPos = _count2;
- while (size--)
- {
- unsigned pos = (curBufferPos & 3);
- if (pos == 0)
- _buffer[curBufferPos >> 2] = 0;
- _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos));
- if (++curBufferPos == kBlockSize)
- {
- curBufferPos = 0;
- CContextBase::UpdateBlock(_buffer, false);
- }
- }
- _count2 = curBufferPos;
-}
-
-void CContext::UpdateRar(Byte *data, size_t size, bool rar350Mode)
-{
- bool returnRes = false;
- unsigned curBufferPos = _count2;
- while (size--)
- {
- unsigned pos = (curBufferPos & 3);
- if (pos == 0)
- _buffer[curBufferPos >> 2] = 0;
- _buffer[curBufferPos >> 2] |= ((UInt32)*data++) << (8 * (3 - pos));
- if (++curBufferPos == kBlockSize)
- {
- curBufferPos = 0;
- CContextBase::UpdateBlock(_buffer, returnRes);
- if (returnRes)
- for (unsigned i = 0; i < kBlockSizeInWords; i++)
- {
- UInt32 d = _buffer[i];
- data[(int)i * 4 + 0 - (int)kBlockSize] = (Byte)(d);
- data[(int)i * 4 + 1 - (int)kBlockSize] = (Byte)(d >> 8);
- data[(int)i * 4 + 2 - (int)kBlockSize] = (Byte)(d >> 16);
- data[(int)i * 4 + 3 - (int)kBlockSize] = (Byte)(d >> 24);
- }
- returnRes = rar350Mode;
- }
- }
- _count2 = curBufferPos;
-}
-
-void CContext::Final(Byte *digest)
-{
- const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 3);
- unsigned curBufferPos = _count2;
- unsigned pos = (curBufferPos & 3);
- curBufferPos >>= 2;
- if (pos == 0)
- _buffer[curBufferPos] = 0;
- _buffer[curBufferPos++] |= ((UInt32)0x80) << (8 * (3 - pos));
-
- while (curBufferPos != (16 - 2))
- {
- curBufferPos &= 0xF;
- if (curBufferPos == 0)
- UpdateBlock();
- _buffer[curBufferPos++] = 0;
- }
- _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32);
- _buffer[curBufferPos++] = (UInt32)(lenInBits);
- UpdateBlock();
-
- unsigned i;
- for (i = 0; i < kDigestSizeInWords; i++)
- {
- UInt32 state = _state[i] & 0xFFFFFFFF;
- *digest++ = (Byte)(state >> 24);
- *digest++ = (Byte)(state >> 16);
- *digest++ = (Byte)(state >> 8);
- *digest++ = (Byte)(state);
- }
- Init();
-}
-
-///////////////////////////
-// Words version
-
-void CContext32::Update(const UInt32 *data, size_t size)
-{
- while (size--)
- {
- _buffer[_count2++] = *data++;
- if (_count2 == kBlockSizeInWords)
- {
- _count2 = 0;
- UpdateBlock();
- }
- }
-}
-
-void CContext32::Final(UInt32 *digest)
-{
- const UInt64 lenInBits = (_count << 9) + ((UInt64)_count2 << 5);
- unsigned curBufferPos = _count2;
- _buffer[curBufferPos++] = 0x80000000;
- while (curBufferPos != (16 - 2))
- {
- curBufferPos &= 0xF;
- if (curBufferPos == 0)
- UpdateBlock();
- _buffer[curBufferPos++] = 0;
- }
- _buffer[curBufferPos++] = (UInt32)(lenInBits >> 32);
- _buffer[curBufferPos++] = (UInt32)(lenInBits);
- GetBlockDigest(_buffer, digest);
- Init();
-}
-
-}}
diff --git a/CPP/7zip/Crypto/Sha1.h b/CPP/7zip/Crypto/Sha1.h
deleted file mode 100644
index df9477d8..00000000
--- a/CPP/7zip/Crypto/Sha1.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Crypto/Sha1.h
-// This file is based on public domain
-// Steve Reid and Wei Dai's code from Crypto++
-
-#ifndef __CRYPTO_SHA1_H
-#define __CRYPTO_SHA1_H
-
-#include <stddef.h>
-
-#include "../../Common/MyTypes.h"
-
-// Sha1 implementation in RAR before version 3.60 has bug:
-// it changes data bytes in some cases.
-// So this class supports both versions: normal_SHA and rar3Mode
-
-namespace NCrypto {
-namespace NSha1 {
-
-const unsigned kBlockSize = 64;
-const unsigned kDigestSize = 20;
-
-const unsigned kBlockSizeInWords = (kBlockSize >> 2);
-const unsigned kDigestSizeInWords = (kDigestSize >> 2);
-
-class CContextBase
-{
-protected:
- UInt32 _state[5];
- UInt64 _count;
- void UpdateBlock(UInt32 *data, bool returnRes = false)
- {
- GetBlockDigest(data, _state, returnRes);
- _count++;
- }
-public:
- void Init();
- void GetBlockDigest(UInt32 *blockData, UInt32 *destDigest, bool returnRes = false);
- // PrepareBlock can be used only when size <= 13. size in Words
- void PrepareBlock(UInt32 *block, unsigned int size) const;
-};
-
-class CContextBase2: public CContextBase
-{
-protected:
- unsigned _count2;
- UInt32 _buffer[kBlockSizeInWords];
- void UpdateBlock() { CContextBase::UpdateBlock(_buffer); }
-public:
- void Init() { CContextBase::Init(); _count2 = 0; }
-};
-
-class CContext: public CContextBase2
-{
-public:
- void Update(const Byte *data, size_t size);
- void UpdateRar(Byte *data, size_t size, bool rar350Mode);
- void Final(Byte *digest);
-};
-
-class CContext32: public CContextBase2
-{
-public:
- void Update(const UInt32 *data, size_t size);
- void Final(UInt32 *digest);
-};
-
-}}
-
-#endif
diff --git a/CPP/7zip/Crypto/Sha1Cls.h b/CPP/7zip/Crypto/Sha1Cls.h
new file mode 100644
index 00000000..18c761f9
--- /dev/null
+++ b/CPP/7zip/Crypto/Sha1Cls.h
@@ -0,0 +1,51 @@
+// Crypto/Sha1.h
+
+#ifndef __CRYPTO_SHA1_H
+#define __CRYPTO_SHA1_H
+
+#include "../../../C/Sha1.h"
+
+namespace NCrypto {
+namespace NSha1 {
+
+const unsigned kNumBlockWords = SHA1_NUM_BLOCK_WORDS;
+const unsigned kNumDigestWords = SHA1_NUM_DIGEST_WORDS;
+
+const unsigned kBlockSize = SHA1_BLOCK_SIZE;
+const unsigned kDigestSize = SHA1_DIGEST_SIZE;
+
+class CContextBase
+{
+protected:
+ CSha1 _s;
+
+public:
+ void Init() throw() { Sha1_Init(&_s); }
+ void GetBlockDigest(const UInt32 *blockData, UInt32 *destDigest) throw() { Sha1_GetBlockDigest(&_s, blockData, destDigest); }
+};
+
+class CContext: public CContextBase
+{
+public:
+ void Update(const Byte *data, size_t size) throw() { Sha1_Update(&_s, data, size); }
+ void UpdateRar(Byte *data, size_t size, bool rar350Mode) throw() { Sha1_Update_Rar(&_s, data, size, rar350Mode ? 1 : 0); }
+ void Final(Byte *digest) throw() { Sha1_Final(&_s, digest); }
+};
+
+class CContext32: public CContextBase
+{
+public:
+ void Update(const UInt32 *data, size_t size) throw() { Sha1_32_Update(&_s, data, size); }
+ void Final(UInt32 *digest) throw() { Sha1_32_Final(&_s, digest); }
+
+ /* PrepareBlock can be used only when size <= 13. size in Words
+ _buffer must be empty (_count & 0xF) == 0) */
+ void PrepareBlock(UInt32 *block, unsigned size) const throw()
+ {
+ Sha1_32_PrepareBlock(&_s, block, size);
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Crypto/Sha1Reg.cpp b/CPP/7zip/Crypto/Sha1Reg.cpp
deleted file mode 100644
index a32972e4..00000000
--- a/CPP/7zip/Crypto/Sha1Reg.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Sha1Reg.cpp
-
-#include "StdAfx.h"
-
-#include "../../Common/MyCom.h"
-
-#include "../ICoder.h"
-#include "../Common/RegisterCodec.h"
-
-#include "Sha1.h"
-
-using namespace NCrypto;
-using namespace NSha1;
-
-class CSha1Hasher:
- public IHasher,
- public CMyUnknownImp
-{
- CContext _sha;
-public:
- CSha1Hasher() { Init(); }
-
- MY_UNKNOWN_IMP
-
- STDMETHOD_(void, Init)();
- STDMETHOD_(void, Update)(const void *data, UInt32 size);
- STDMETHOD_(void, Final)(Byte *digest);
- STDMETHOD_(UInt32, GetDigestSize)();
-};
-
-STDMETHODIMP_(void) CSha1Hasher::Init()
-{
- _sha.Init();
-}
-
-STDMETHODIMP_(void) CSha1Hasher::Update(const void *data, UInt32 size)
-{
- _sha.Update((const Byte *)data, size);
-}
-
-STDMETHODIMP_(void) CSha1Hasher::Final(Byte *digest)
-{
- _sha.Final(digest);
-}
-
-STDMETHODIMP_(UInt32) CSha1Hasher::GetDigestSize()
-{
- return kDigestSize;
-}
-
-static IHasher *CreateHasher() { return new CSha1Hasher; }
-
-static CHasherInfo g_HasherInfo = { CreateHasher, 0x201, L"SHA1", kDigestSize };
-
-REGISTER_HASHER(Sha1)
diff --git a/CPP/7zip/Crypto/WzAes.cpp b/CPP/7zip/Crypto/WzAes.cpp
index 4194c02f..4572f06e 100644
--- a/CPP/7zip/Crypto/WzAes.cpp
+++ b/CPP/7zip/Crypto/WzAes.cpp
@@ -1,21 +1,22 @@
// Crypto/WzAes.cpp
/*
This code implements Brian Gladman's scheme
-specified in password Based File Encryption Utility.
+specified in "A Password Based File Encryption Utility".
Note: you must include MyAes.cpp to project to initialize AES tables
*/
#include "StdAfx.h"
-#include "../Common/StreamObjects.h"
+#include "../../../C/CpuArch.h"
+
#include "../Common/StreamUtils.h"
#include "Pbkdf2HmacSha1.h"
#include "RandGen.h"
#include "WzAes.h"
-// define it if you don't want to use speed-optimized version of Pbkdf2HmacSha1
+// define it if you don't want to use speed-optimized version of NSha1::Pbkdf2Hmac
// #define _NO_WZAES_OPTIMIZATIONS
namespace NCrypto {
@@ -33,69 +34,72 @@ STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
return S_OK;
}
-#ifndef _NO_WZAES_OPTIMIZATIONS
-
-static void BytesToBeUInt32s(const Byte *src, UInt32 *dest, unsigned destSize)
+void CBaseCoder::Init2()
{
- for (unsigned i = 0; i < destSize; i++)
- dest[i] =
- ((UInt32)(src[i * 4 + 0]) << 24) |
- ((UInt32)(src[i * 4 + 1]) << 16) |
- ((UInt32)(src[i * 4 + 2]) << 8) |
- ((UInt32)(src[i * 4 + 3]));
-}
+ const unsigned dkSizeMax32 = (2 * kAesKeySizeMax + kPwdVerifSize + 3) / 4;
+ Byte dk[dkSizeMax32 * 4];
-#endif
-
-STDMETHODIMP CBaseCoder::Init()
-{
- UInt32 keySize = _key.GetKeySize();
- UInt32 keysTotalSize = 2 * keySize + kPwdVerifCodeSize;
- Byte buf[2 * kAesKeySizeMax + kPwdVerifCodeSize];
+ const unsigned keySize = _key.GetKeySize();
+ const unsigned dkSize = 2 * keySize + kPwdVerifSize;
// for (unsigned ii = 0; ii < 1000; ii++)
{
#ifdef _NO_WZAES_OPTIMIZATIONS
NSha1::Pbkdf2Hmac(
- _key.Password, _key.Password.Size(),
- _key.Salt, _key.GetSaltSize(),
- kNumKeyGenIterations,
- buf, keysTotalSize);
+ _key.Password, _key.Password.Size(),
+ _key.Salt, _key.GetSaltSize(),
+ kNumKeyGenIterations,
+ dk, dkSize);
#else
- UInt32 buf32[(2 * kAesKeySizeMax + kPwdVerifCodeSize + 3) / 4];
- UInt32 key32SizeTotal = (keysTotalSize + 3) / 4;
- UInt32 salt[kSaltSizeMax * 4];
- UInt32 saltSizeInWords = _key.GetSaltSize() / 4;
- BytesToBeUInt32s(_key.Salt, salt, saltSizeInWords);
+ UInt32 dk32[dkSizeMax32];
+ const unsigned dkSize32 = (dkSize + 3) / 4;
+ UInt32 salt[kSaltSizeMax / 4];
+ unsigned numSaltWords = _key.GetNumSaltWords();
+
+ for (unsigned i = 0; i < numSaltWords; i++)
+ {
+ const Byte *src = _key.Salt + i * 4;
+ salt[i] = GetBe32(src);
+ }
+
NSha1::Pbkdf2Hmac32(
- _key.Password, _key.Password.Size(),
- salt, saltSizeInWords,
- kNumKeyGenIterations,
- buf32, key32SizeTotal);
- for (UInt32 j = 0; j < keysTotalSize; j++)
- buf[j] = (Byte)(buf32[j / 4] >> (24 - 8 * (j & 3)));
+ _key.Password, _key.Password.Size(),
+ salt, numSaltWords,
+ kNumKeyGenIterations,
+ dk32, dkSize32);
+
+ /*
+ for (unsigned j = 0; j < dkSize; j++)
+ dk[j] = (Byte)(dk32[j / 4] >> (24 - 8 * (j & 3)));
+ */
+ for (unsigned j = 0; j < dkSize32; j++)
+ SetBe32(dk + j * 4, dk32[j]);
#endif
}
- _hmac.SetKey(buf + keySize, keySize);
- memcpy(_key.PwdVerifComputed, buf + 2 * keySize, kPwdVerifCodeSize);
+ _hmac.SetKey(dk + keySize, keySize);
+ memcpy(_key.PwdVerifComputed, dk + 2 * keySize, kPwdVerifSize);
- Aes_SetKey_Enc(_aes.aes + _aes.offset + 8, buf, keySize);
+ Aes_SetKey_Enc(_aes.aes + _aes.offset + 8, dk, keySize);
AesCtr2_Init(&_aes);
+}
+
+STDMETHODIMP CBaseCoder::Init()
+{
return S_OK;
}
HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream)
{
- UInt32 saltSize = _key.GetSaltSize();
+ unsigned saltSize = _key.GetSaltSize();
g_RandomGenerator.Generate(_key.Salt, saltSize);
- Init();
+ Init2();
RINOK(WriteStream(outStream, _key.Salt, saltSize));
- return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifCodeSize);
+ return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifSize);
}
HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream)
@@ -105,6 +109,7 @@ HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream)
return WriteStream(outStream, mac, kMacSize);
}
+/*
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size != 1)
@@ -112,32 +117,34 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
_key.Init();
return SetKeyMode(data[0]) ? S_OK : E_INVALIDARG;
}
+*/
HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)
{
- UInt32 saltSize = _key.GetSaltSize();
- UInt32 extraSize = saltSize + kPwdVerifCodeSize;
- Byte temp[kSaltSizeMax + kPwdVerifCodeSize];
+ unsigned saltSize = _key.GetSaltSize();
+ unsigned extraSize = saltSize + kPwdVerifSize;
+ Byte temp[kSaltSizeMax + kPwdVerifSize];
RINOK(ReadStream_FAIL(inStream, temp, extraSize));
- UInt32 i;
+ unsigned i;
for (i = 0; i < saltSize; i++)
_key.Salt[i] = temp[i];
- for (i = 0; i < kPwdVerifCodeSize; i++)
+ for (i = 0; i < kPwdVerifSize; i++)
_pwdVerifFromArchive[i] = temp[saltSize + i];
return S_OK;
}
-static bool CompareArrays(const Byte *p1, const Byte *p2, UInt32 size)
+static inline bool CompareArrays(const Byte *p1, const Byte *p2, unsigned size)
{
- for (UInt32 i = 0; i < size; i++)
+ for (unsigned i = 0; i < size; i++)
if (p1[i] != p2[i])
return false;
return true;
}
-bool CDecoder::CheckPasswordVerifyCode()
+bool CDecoder::Init_and_CheckPassword()
{
- return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifCodeSize);
+ Init2();
+ return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifSize);
}
HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK)
@@ -165,12 +172,15 @@ void AesCtr2_Init(CAesCtr2 *p)
p->pos = AES_BLOCK_SIZE;
}
+/* (size != 16 * N) is allowed only for last call */
+
void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)
{
unsigned pos = p->pos;
UInt32 *buf32 = p->aes + p->offset;
if (size == 0)
return;
+
if (pos != AES_BLOCK_SIZE)
{
const Byte *buf = (const Byte *)buf32;
@@ -178,6 +188,7 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)
*data++ ^= buf[pos++];
while (--size != 0 && pos != AES_BLOCK_SIZE);
}
+
if (size >= 16)
{
SizeT size2 = size >> 4;
@@ -187,6 +198,7 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)
size -= size2;
pos = AES_BLOCK_SIZE;
}
+
if (size != 0)
{
unsigned j;
@@ -200,9 +212,12 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)
*data++ ^= buf[pos++];
while (--size != 0);
}
+
p->pos = pos;
}
+/* (size != 16 * N) is allowed only for last Filter() call */
+
STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)
{
AesCtr2_Code(&_aes, data, size);
diff --git a/CPP/7zip/Crypto/WzAes.h b/CPP/7zip/Crypto/WzAes.h
index 980be8b3..41f9949e 100644
--- a/CPP/7zip/Crypto/WzAes.h
+++ b/CPP/7zip/Crypto/WzAes.h
@@ -1,7 +1,7 @@
// Crypto/WzAes.h
/*
This code implements Brian Gladman's scheme
-specified in password Based File Encryption Utility:
+specified in "A Password Based File Encryption Utility":
- AES encryption (128,192,256-bit) in Counter (CTR) mode.
- HMAC-SHA1 authentication for encrypted data (10 bytes)
- Keys are derived by PPKDF2(RFC2898)-HMAC-SHA1 from ASCII password and
@@ -25,13 +25,24 @@ specified in password Based File Encryption Utility:
namespace NCrypto {
namespace NWzAes {
-const unsigned kSaltSizeMax = 16;
-const unsigned kMacSize = 10;
+/* ICompressFilter::Init() does nothing for this filter.
+
+ Call to init:
+ Encoder:
+ CryptoSetPassword();
+ WriteHeader();
+ Decoder:
+ [CryptoSetPassword();]
+ ReadHeader();
+ [CryptoSetPassword();] Init_and_CheckPassword();
+ [CryptoSetPassword();] Init_and_CheckPassword();
+*/
const UInt32 kPasswordSizeMax = 99; // 128;
-// Password Verification Code Size
-const unsigned kPwdVerifCodeSize = 2;
+const unsigned kSaltSizeMax = 16;
+const unsigned kPwdVerifSize = 2;
+const unsigned kMacSize = 10;
enum EKeySizeMode
{
@@ -40,20 +51,19 @@ enum EKeySizeMode
kKeySizeMode_AES256 = 3
};
-class CKeyInfo
+struct CKeyInfo
{
-public:
EKeySizeMode KeySizeMode;
Byte Salt[kSaltSizeMax];
- Byte PwdVerifComputed[kPwdVerifCodeSize];
+ Byte PwdVerifComputed[kPwdVerifSize];
CByteBuffer Password;
- UInt32 GetKeySize() const { return (8 * (KeySizeMode & 3) + 8); }
- UInt32 GetSaltSize() const { return (4 * (KeySizeMode & 3) + 4); }
+ unsigned GetKeySize() const { return (8 * KeySizeMode + 8); }
+ unsigned GetSaltSize() const { return (4 * KeySizeMode + 4); }
+ unsigned GetNumSaltWords() const { return (KeySizeMode + 1); }
- CKeyInfo() { Init(); }
- void Init() { KeySizeMode = kKeySizeMode_AES256; }
+ CKeyInfo(): KeySizeMode(kKeySizeMode_AES256) {}
};
struct CAesCtr2
@@ -75,16 +85,19 @@ class CBaseCoder:
protected:
CKeyInfo _key;
NSha1::CHmac _hmac;
- Byte _pwdVerifFromArchive[kPwdVerifCodeSize];
CAesCtr2 _aes;
+ void Init2();
public:
+ MY_UNKNOWN_IMP1(ICryptoSetPassword)
+
+ STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
+
STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) = 0;
- STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
+ unsigned GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifSize; }
+ unsigned GetAddPackSize() const { return GetHeaderSize() + kMacSize; }
- UInt32 GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifCodeSize; }
bool SetKeyMode(unsigned mode)
{
if (mode < kKeySizeMode_AES128 || mode > kKeySizeMode_AES256)
@@ -98,24 +111,22 @@ class CEncoder:
public CBaseCoder
{
public:
- MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
HRESULT WriteHeader(ISequentialOutStream *outStream);
HRESULT WriteFooter(ISequentialOutStream *outStream);
};
class CDecoder:
- public CBaseCoder,
- public ICompressSetDecoderProperties2
+ public CBaseCoder
+ // public ICompressSetDecoderProperties2
{
+ Byte _pwdVerifFromArchive[kPwdVerifSize];
public:
- MY_UNKNOWN_IMP2(
- ICryptoSetPassword,
- ICompressSetDecoderProperties2)
+ // ICompressSetDecoderProperties2
+ // STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
- STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
HRESULT ReadHeader(ISequentialInStream *inStream);
- bool CheckPasswordVerifyCode();
+ bool Init_and_CheckPassword();
HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK);
};
diff --git a/CPP/7zip/Crypto/ZipCrypto.cpp b/CPP/7zip/Crypto/ZipCrypto.cpp
index baaaf98e..77aff83b 100644
--- a/CPP/7zip/Crypto/ZipCrypto.cpp
+++ b/CPP/7zip/Crypto/ZipCrypto.cpp
@@ -12,23 +12,27 @@
namespace NCrypto {
namespace NZip {
-void CCipher::UpdateKeys(Byte b)
-{
- Keys[0] = CRC_UPDATE_BYTE(Keys[0], b);
- Keys[1] = (Keys[1] + (Keys[0] & 0xFF)) * 0x8088405 + 1;
- Keys[2] = CRC_UPDATE_BYTE(Keys[2], (Byte)(Keys[1] >> 24));
-}
+#define UPDATE_KEYS(b) { \
+ Key0 = CRC_UPDATE_BYTE(Key0, b); \
+ Key1 = (Key1 + (Key0 & 0xFF)) * 0x8088405 + 1; \
+ Key2 = CRC_UPDATE_BYTE(Key2, (Byte)(Key1 >> 24)); } \
+
+#define DECRYPT_BYTE_1 UInt32 temp = Key2 | 2;
+#define DECRYPT_BYTE_2 ((Byte)((temp * (temp ^ 1)) >> 8))
-STDMETHODIMP CCipher::CryptoSetPassword(const Byte *password, UInt32 passwordLen)
+STDMETHODIMP CCipher::CryptoSetPassword(const Byte *data, UInt32 size)
{
- Keys[0] = 0x12345678;
- Keys[1] = 0x23456789;
- Keys[2] = 0x34567890;
- UInt32 i;
- for (i = 0; i < passwordLen; i++)
- UpdateKeys(password[i]);
- for (i = 0; i < 3; i++)
- Keys2[i] = Keys[i];
+ UInt32 Key0 = 0x12345678;
+ UInt32 Key1 = 0x23456789;
+ UInt32 Key2 = 0x34567890;
+
+ for (UInt32 i = 0; i < size; i++)
+ UPDATE_KEYS(data[i]);
+
+ KeyMem0 = Key0;
+ KeyMem1 = Key1;
+ KeyMem2 = Key2;
+
return S_OK;
}
@@ -37,18 +41,18 @@ STDMETHODIMP CCipher::Init()
return S_OK;
}
-Byte CCipher::DecryptByteSpec()
-{
- UInt32 temp = Keys[2] | 2;
- return (Byte)((temp * (temp ^ 1)) >> 8);
-}
-
-HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream, UInt32 crc)
+HRESULT CEncoder::WriteHeader_Check16(ISequentialOutStream *outStream, UInt16 crc)
{
Byte h[kHeaderSize];
- g_RandomGenerator.Generate(h, kHeaderSize - 2);
- h[kHeaderSize - 1] = (Byte)(crc >> 24);
- h[kHeaderSize - 2] = (Byte)(crc >> 16);
+
+ /* PKZIP before 2.0 used 2 byte CRC check.
+ PKZIP 2.0+ used 1 byte CRC check. It's more secure.
+ We also use 1 byte CRC. */
+
+ g_RandomGenerator.Generate(h, kHeaderSize - 1);
+ // h[kHeaderSize - 2] = (Byte)(crc);
+ h[kHeaderSize - 1] = (Byte)(crc >> 8);
+
RestoreKeys();
Filter(h, kHeaderSize);
return WriteStream(outStream, h, kHeaderSize);
@@ -56,32 +60,54 @@ HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream, UInt32 crc)
STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)
{
+ UInt32 Key0 = this->Key0;
+ UInt32 Key1 = this->Key1;
+ UInt32 Key2 = this->Key2;
+
for (UInt32 i = 0; i < size; i++)
{
Byte b = data[i];
- data[i] = (Byte)(b ^ DecryptByteSpec());;
- UpdateKeys(b);
+ DECRYPT_BYTE_1
+ data[i] = (Byte)(b ^ DECRYPT_BYTE_2);
+ UPDATE_KEYS(b);
}
+
+ this->Key0 = Key0;
+ this->Key1 = Key1;
+ this->Key2 = Key2;
+
return size;
}
HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)
{
- Byte h[kHeaderSize];
- RINOK(ReadStream_FAIL(inStream, h, kHeaderSize));
+ return ReadStream_FAIL(inStream, _header, kHeaderSize);
+}
+
+void CDecoder::Init_BeforeDecode()
+{
RestoreKeys();
- Filter(h, kHeaderSize);
- return S_OK;
+ Filter(_header, kHeaderSize);
}
STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
{
+ UInt32 Key0 = this->Key0;
+ UInt32 Key1 = this->Key1;
+ UInt32 Key2 = this->Key2;
+
for (UInt32 i = 0; i < size; i++)
{
- Byte c = (Byte)(data[i] ^ DecryptByteSpec());
- UpdateKeys(c);
- data[i] = c;
+ DECRYPT_BYTE_1
+ Byte b = (Byte)(data[i] ^ DECRYPT_BYTE_2);
+ UPDATE_KEYS(b);
+ data[i] = b;
}
+
+ this->Key0 = Key0;
+ this->Key1 = Key1;
+ this->Key2 = Key2;
+
return size;
}
diff --git a/CPP/7zip/Crypto/ZipCrypto.h b/CPP/7zip/Crypto/ZipCrypto.h
index 51b9e301..b23d4216 100644
--- a/CPP/7zip/Crypto/ZipCrypto.h
+++ b/CPP/7zip/Crypto/ZipCrypto.h
@@ -13,24 +13,41 @@ namespace NZip {
const unsigned kHeaderSize = 12;
+/* ICompressFilter::Init() does nothing for this filter.
+ Call to init:
+ Encoder:
+ CryptoSetPassword();
+ WriteHeader();
+ Decoder:
+ [CryptoSetPassword();]
+ ReadHeader();
+ [CryptoSetPassword();] Init_and_GetCrcByte();
+ [CryptoSetPassword();] Init_and_GetCrcByte();
+*/
+
class CCipher:
public ICompressFilter,
public ICryptoSetPassword,
public CMyUnknownImp
{
- UInt32 Keys[3];
- UInt32 Keys2[3];
-
protected:
- void UpdateKeys(Byte b);
- Byte DecryptByteSpec();
+ UInt32 Key0;
+ UInt32 Key1;
+ UInt32 Key2;
+
+ UInt32 KeyMem0;
+ UInt32 KeyMem1;
+ UInt32 KeyMem2;
+
void RestoreKeys()
{
- for (int i = 0; i < 3; i++)
- Keys[i] = Keys2[i];
+ Key0 = KeyMem0;
+ Key1 = KeyMem1;
+ Key2 = KeyMem2;
}
public:
+ MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD(Init)();
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
};
@@ -38,17 +55,17 @@ public:
class CEncoder: public CCipher
{
public:
- MY_UNKNOWN_IMP1(ICryptoSetPassword)
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
- HRESULT WriteHeader(ISequentialOutStream *outStream, UInt32 crc);
+ HRESULT WriteHeader_Check16(ISequentialOutStream *outStream, UInt16 crc);
};
class CDecoder: public CCipher
{
public:
- MY_UNKNOWN_IMP1(ICryptoSetPassword)
+ Byte _header[kHeaderSize];
STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
HRESULT ReadHeader(ISequentialInStream *inStream);
+ void Init_BeforeDecode();
};
}}
diff --git a/CPP/7zip/Crypto/ZipStrong.cpp b/CPP/7zip/Crypto/ZipStrong.cpp
index a8765c26..c5e368b9 100644
--- a/CPP/7zip/Crypto/ZipStrong.cpp
+++ b/CPP/7zip/Crypto/ZipStrong.cpp
@@ -7,8 +7,7 @@
#include "../Common/StreamUtils.h"
-#include "MyAes.h"
-#include "Sha1.h"
+#include "Sha1Cls.h"
#include "ZipStrong.h"
namespace NCrypto {
@@ -57,25 +56,22 @@ STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
return S_OK;
}
-HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UInt64 /* unpackSize */)
+STDMETHODIMP CBaseCoder::Init()
+{
+ return S_OK;
+}
+
+HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize)
{
Byte temp[4];
RINOK(ReadStream_FALSE(inStream, temp, 2));
_ivSize = GetUi16(temp);
if (_ivSize == 0)
{
- return E_NOTIMPL;
-
- /* we don't know how to decode that case:
- From Appnote: If IVSize is 0,then IV = CRC32 + Uncompressed File Size (as a 64 bit little-endian, unsigned integer value).
- But it doesn't work. If you know solution, please write about it to 7-Zip developers. */
-
- /*
memset(_iv, 0, 16);
- // unpackSize += crc;
SetUi32(_iv + 0, crc);
SetUi64(_iv + 4, unpackSize);
- */
+ _ivSize = 12;
}
else if (_ivSize == 16)
{
@@ -96,7 +92,7 @@ HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 /* crc */, UI
return ReadStream_FALSE(inStream, _bufAligned, _remSize);
}
-HRESULT CDecoder::CheckPassword(bool &passwOK)
+HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
{
passwOK = false;
if (_remSize < 16)
@@ -146,7 +142,7 @@ HRESULT CDecoder::CheckPassword(bool &passwOK)
Byte fileKey[32];
NSha1::CContext sha;
sha.Init();
- sha.Update(_iv, 16);
+ sha.Update(_iv, _ivSize);
sha.Update(p, rdSize - 16); // we don't use last 16 bytes (PAD bytes)
DeriveKey(sha, fileKey);
@@ -161,8 +157,6 @@ HRESULT CDecoder::CheckPassword(bool &passwOK)
if (GetUi32(validData + validSize) != CrcCalc(validData, validSize))
return S_OK;
passwOK = true;
- /* 9.31: The BUG in 9.24-9.30 was fixed.
- We don't need to call CAesCbcCoder::Init() to reset IV for data. */
return S_OK;
}
diff --git a/CPP/7zip/Crypto/ZipStrong.h b/CPP/7zip/Crypto/ZipStrong.h
index e3a43000..c5809e7b 100644
--- a/CPP/7zip/Crypto/ZipStrong.h
+++ b/CPP/7zip/Crypto/ZipStrong.h
@@ -12,10 +12,20 @@
namespace NCrypto {
namespace NZipStrong {
+/* ICompressFilter::Init() does nothing for this filter.
+ Call to init:
+ Decoder:
+ [CryptoSetPassword();]
+ ReadHeader();
+ [CryptoSetPassword();] Init_and_CheckPassword();
+ [CryptoSetPassword();] Init_and_CheckPassword();
+*/
+
struct CKeyInfo
{
Byte MasterKey[32];
UInt32 KeySize;
+
void SetPassword(const Byte *data, UInt32 size);
};
@@ -28,6 +38,7 @@ protected:
CByteBuffer _buf;
Byte *_bufAligned;
public:
+ STDMETHOD(Init)();
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
};
@@ -39,7 +50,7 @@ class CDecoder: public CBaseCoder
public:
MY_UNKNOWN_IMP1(ICryptoSetPassword)
HRESULT ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize);
- HRESULT CheckPassword(bool &passwOK);
+ HRESULT Init_and_CheckPassword(bool &passwOK);
};
}}
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
index 8ded1f96..64214e80 100644
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -3,18 +3,23 @@
00 IProgress.h
05 IProgress
+ // 050002 IProgress2
01 IFolderArchive.h
// 05 IArchiveFolder // old
// 06 IInFolderArchive // old
07 IFileExtractCallback.h::IFolderArchiveExtractCallback
+ 08 IFileExtractCallback.h::IFolderArchiveExtractCallback2
// 0A IOutFolderArchive
0B IFolderArchiveUpdateCallback
0C Agent.h::IArchiveFolderInternal
0D IArchiveFolder
0E IInFolderArchive
0F IOutFolderArchive
+ 10 IFolderArchiveUpdateCallback2
+ 11 IFolderScanProgress
+
20 IFileExtractCallback.h::IGetProp
30 IFileExtractCallback.h::IFolderExtractToStreamCallback
@@ -25,7 +30,7 @@
03 IInStream
04 IOutStream
06 IStreamGetSize
- 07 IOutStreamFlush
+ 07 IOutStreamFinish
08 IStreamGetProps
09 IStreamGetProps2
@@ -41,12 +46,20 @@
23 ICompressWriteCoderProperties
24 ICompressGetInStreamProcessedSize
25 ICompressSetCoderMt
+ 26 ICompressSetFinishMode
+
30 ICompressGetSubStreamSize
31 ICompressSetInStream
32 ICompressSetOutStream
- 33 ICompressSetInStreamSize
+// 33 ICompressSetInStreamSize
34 ICompressSetOutStreamSize
35 ICompressSetBufSize
+ 36 ICompressInitEncoder
+ 37 ICompressSetInStream2
+// 38 ICompressSetOutStream2
+// 39 SetInStreamSize2
+// 3A SetOutStreamSize2
+
40 ICompressFilter
60 ICompressCodecsInfo
61 ISetCompressCodecsInfo
@@ -72,7 +85,10 @@
05 IArchiveAllowTail
10 IArchiveOpenCallback
+
20 IArchiveExtractCallback
+ 21 IArchiveExtractCallbackMessage
+
30 IArchiveOpenVolumeCallback
40 IInArchiveGetStream
50 IArchiveOpenSetSubArchiveName
@@ -83,6 +99,8 @@
80 IArchiveUpdateCallback
82 IArchiveUpdateCallback2
+ 83 IArchiveUpdateCallbackFile
+
A0 IOutArchive
@@ -112,6 +130,7 @@
14 IFolderCalcItemFullSize
15 IFolderCompare
16 IFolderGetItemName
+ 17 IFolderAltStreams
09 IFolder.h :: FOLDER_MANAGER_INTERFACE
@@ -180,12 +199,11 @@ Handler GUIDs:
EE Tar
EF GZip
-{23170F69-40C1-278A-1000-000100030000} CAgentArchiveHandle
{23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu
-{23170F69-40C1-278B- old codecs clsids
-
-{23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions
+// {23170F69-40C1-278A-1000-000100030000} // CAgentArchiveHandler
+// {23170F69-40C1-278B- old codecs clsids
+// {23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions
{23170F69-40C1-2790-id} Codec Decoders
{23170F69-40C1-2791-id} Codec Encoders
diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h
index 74ee0e45..75db9399 100644
--- a/CPP/7zip/ICoder.h
+++ b/CPP/7zip/ICoder.h
@@ -10,6 +10,15 @@
CODER_INTERFACE(ICompressProgressInfo, 0x04)
{
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;
+
+ /* (inSize) can be NULL, if unknown
+ (outSize) can be NULL, if unknown
+
+ returns:
+ S_OK
+ E_ABORT : Break by user
+ another error codes
+ */
};
CODER_INTERFACE(ICompressCoder, 0x05)
@@ -21,11 +30,75 @@ CODER_INTERFACE(ICompressCoder, 0x05)
CODER_INTERFACE(ICompressCoder2, 0x18)
{
- STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams,
- ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams,
+ STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
+ ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,
ICompressProgressInfo *progress) PURE;
};
+/*
+ ICompressCoder::Code
+ ICompressCoder2::Code
+
+ returns:
+ S_OK : OK
+ S_FALSE : data error (for decoders)
+ E_OUTOFMEMORY : memory allocation error
+ another error code : some error. For example, it can be error code received from inStream or outStream function.
+
+ Parameters:
+ (inStream != NULL)
+ (outStream != NULL)
+
+ if (inSize != NULL)
+ {
+ Encoders in 7-Zip ignore (inSize).
+ Decoder can use (*inSize) to check that stream was decoded correctly.
+ Some decoder in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode)
+ }
+
+ If it's required to limit the reading from input stream (inStream), it can
+ be done with ISequentialInStream implementation.
+
+ if (outSize != NULL)
+ {
+ Encoders in 7-Zip ignore (outSize).
+ Decoder unpacks no more than (*outSize) bytes.
+ }
+
+ (progress == NULL) is allowed.
+
+
+ Decoding with Code() function
+ -----------------------------
+
+ You can request some interfaces before decoding
+ - ICompressSetDecoderProperties2
+ - ICompressSetFinishMode
+
+ If you need to decode full stream:
+ {
+ 1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1);
+ 2) call the Code() function with specified (inSize) and (outSize), if these sizes are known.
+ }
+
+ If you need to decode only part of stream:
+ {
+ 1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0);
+ 2) Call the Code() function with specified (inSize = NULL) and specified (outSize).
+ }
+
+ Encoding with Code() function
+ -----------------------------
+
+ You can request some interfaces :
+ - ICompressSetCoderProperties - use it before encoding to set properties
+ - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties.
+
+ ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1)
+ The rules are similar to ICompressCoder rules
+*/
+
+
namespace NCoderPropID
{
enum EEnum
@@ -64,6 +137,12 @@ CODER_INTERFACE(ICompressSetCoderProperties, 0x21)
CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)
{
+ /* returns:
+ S_OK
+ E_NOTIMP : unsupported properties
+ E_INVALIDARG : incorrect (or unsupported) properties
+ E_OUTOFMEMORY : memory allocation error
+ */
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;
};
@@ -82,9 +161,34 @@ CODER_INTERFACE(ICompressSetCoderMt, 0x25)
STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;
};
+CODER_INTERFACE(ICompressSetFinishMode, 0x26)
+{
+ STDMETHOD(SetFinishMode)(UInt32 finishMode) PURE;
+
+ /* finishMode:
+ 0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined.
+ 1 : full decoding. The stream must be finished at the end of decoding. */
+};
+
+
CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)
{
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;
+
+ /* returns:
+ S_OK : (*value) contains the size or estimated size (can be incorrect size)
+ S_FALSE : size is undefined
+ E_NOTIMP : the feature is not implemented
+
+ Let's (read_size) is size of data that was already read by ISequentialInStream::Read().
+ The caller should call GetSubStreamSize() after each Read() and check sizes:
+ if (start_of_subStream + *value < read_size)
+ {
+ // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream:
+ start_of_subStream += *value;
+ subStream++;
+ }
+ */
};
CODER_INTERFACE(ICompressSetInStream, 0x31)
@@ -99,14 +203,21 @@ CODER_INTERFACE(ICompressSetOutStream, 0x32)
STDMETHOD(ReleaseOutStream)() PURE;
};
+/*
CODER_INTERFACE(ICompressSetInStreamSize, 0x33)
{
STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;
};
+*/
CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)
{
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;
+
+ /* That function initializes decoder structures.
+ Call this function only for stream version of decoder.
+ if (outSize == NULL), then output size is unknown
+ if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */
};
CODER_INTERFACE(ICompressSetBufSize, 0x35)
@@ -115,25 +226,62 @@ CODER_INTERFACE(ICompressSetBufSize, 0x35)
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE;
};
+CODER_INTERFACE(ICompressInitEncoder, 0x36)
+{
+ STDMETHOD(InitEncoder)() PURE;
+
+ /* That function initializes encoder structures.
+ Call this function only for stream version of encoder. */
+};
+
+CODER_INTERFACE(ICompressSetInStream2, 0x37)
+{
+ STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream) PURE;
+ STDMETHOD(ReleaseInStream2)(UInt32 streamIndex) PURE;
+};
+
+/*
+CODER_INTERFACE(ICompressSetOutStream2, 0x38)
+{
+ STDMETHOD(SetOutStream2)(UInt32 streamIndex, ISequentialOutStream *outStream) PURE;
+ STDMETHOD(ReleaseOutStream2)(UInt32 streamIndex) PURE;
+};
+
+CODER_INTERFACE(ICompressSetInStreamSize2, 0x39)
+{
+ STDMETHOD(SetInStreamSize2)(UInt32 streamIndex, const UInt64 *inSize) PURE;
+};
+*/
+
+
+/*
+ ICompressFilter
+ Filter() converts as most as possible bytes
+ returns: (outSize):
+ if (outSize <= size) : Filter have converted outSize bytes
+ if (outSize > size) : Filter have not converted anything.
+ and it needs at least outSize bytes to convert one block
+ (it's for crypto block algorithms).
+*/
+
+#define INTERFACE_ICompressFilter(x) \
+ STDMETHOD(Init)() x; \
+ STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) x; \
+
CODER_INTERFACE(ICompressFilter, 0x40)
{
- STDMETHOD(Init)() PURE;
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;
- // Filter converts as most as possible bytes
- // Filter return outSize (UInt32)
- // if (outSize <= size): Filter have converted outSize bytes
- // if (outSize > size): Filter have not converted anything.
- // and it needs at least outSize bytes to convert one block
- // (it's for crypto block algorithms).
+ INTERFACE_ICompressFilter(PURE);
};
+
CODER_INTERFACE(ICompressCodecsInfo, 0x60)
{
- STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE;
+ STDMETHOD(GetNumMethods)(UInt32 *numMethods) PURE;
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE;
STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE;
};
+
CODER_INTERFACE(ISetCompressCodecsInfo, 0x61)
{
STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE;
@@ -155,6 +303,10 @@ CODER_INTERFACE(ICryptoResetSalt, 0x88)
CODER_INTERFACE(ICryptoResetInitVector, 0x8C)
{
STDMETHOD(ResetInitVector)() PURE;
+
+ /* Call ResetInitVector() only for encoding.
+ Call ResetInitVector() before encoding and before WriteCoderProperties().
+ Crypto encoder can create random IV in that function. */
};
CODER_INTERFACE(ICryptoSetPassword, 0x90)
@@ -167,8 +319,7 @@ CODER_INTERFACE(ICryptoSetCRC, 0xA0)
STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;
};
-//////////////////////
-// It's for DLL file
+
namespace NMethodPropID
{
enum EEnum
@@ -177,8 +328,8 @@ namespace NMethodPropID
kName,
kDecoder,
kEncoder,
- kInStreams,
- kOutStreams,
+ kPackStreams,
+ kUnpackStreams,
kDescription,
kDecoderIsAssigned,
kEncoderIsAssigned,
@@ -186,12 +337,16 @@ namespace NMethodPropID
};
}
+
+#define INTERFACE_IHasher(x) \
+ STDMETHOD_(void, Init)() throw() x; \
+ STDMETHOD_(void, Update)(const void *data, UInt32 size) throw() x; \
+ STDMETHOD_(void, Final)(Byte *digest) throw() x; \
+ STDMETHOD_(UInt32, GetDigestSize)() throw() x; \
+
CODER_INTERFACE(IHasher, 0xC0)
{
- STDMETHOD_(void, Init)() PURE;
- STDMETHOD_(void, Update)(const void *data, UInt32 size) PURE;
- STDMETHOD_(void, Final)(Byte *digest) PURE;
- STDMETHOD_(UInt32, GetDigestSize)() PURE;
+ INTERFACE_IHasher(PURE)
};
CODER_INTERFACE(IHashers, 0xC1)
@@ -205,7 +360,12 @@ extern "C"
{
typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods);
typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject);
+ typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject);
+
typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers);
+
+ typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo);
}
#endif
diff --git a/CPP/7zip/IDecl.h b/CPP/7zip/IDecl.h
index 8316eb3a..077ef0ee 100644
--- a/CPP/7zip/IDecl.h
+++ b/CPP/7zip/IDecl.h
@@ -5,10 +5,23 @@
#include "../Common/MyUnknown.h"
+#define k_7zip_GUID_Data1 0x23170F69
+#define k_7zip_GUID_Data2 0x40C1
+
+#define k_7zip_GUID_Data3_Common 0x278A
+
+#define k_7zip_GUID_Data3_Decoder 0x2790
+#define k_7zip_GUID_Data3_Encoder 0x2791
+#define k_7zip_GUID_Data3_Hasher 0x2792
+
+
#define DECL_INTERFACE_SUB(i, base, groupId, subId) \
-DEFINE_GUID(IID_ ## i, \
-0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \
-struct i: public base
+ DEFINE_GUID(IID_ ## i, \
+ k_7zip_GUID_Data1, \
+ k_7zip_GUID_Data2, \
+ k_7zip_GUID_Data3_Common, \
+ 0, 0, 0, (groupId), 0, (subId), 0, 0); \
+ struct i: public base
#define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId)
diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h
index a270e693..59c55aea 100644
--- a/CPP/7zip/IProgress.h
+++ b/CPP/7zip/IProgress.h
@@ -1,4 +1,4 @@
-// Interface/IProgress.h
+// IProgress.h
#ifndef __IPROGRESS_H
#define __IPROGRESS_H
@@ -17,17 +17,4 @@ DECL_INTERFACE(IProgress, 0, 5)
INTERFACE_IProgress(PURE)
};
-/*
-// {23170F69-40C1-278A-0000-000000050002}
-DEFINE_GUID(IID_IProgress2,
-0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02);
-MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002")
-IProgress2: public IUnknown
-{
-public:
- STDMETHOD(SetTotal)(const UInt64 *total) PURE;
- STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE;
-};
-*/
-
#endif
diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h
index c3a290b9..70cb3620 100644
--- a/CPP/7zip/IStream.h
+++ b/CPP/7zip/IStream.h
@@ -95,9 +95,9 @@ STREAM_INTERFACE(IStreamGetSize, 0x06)
STDMETHOD(GetSize)(UInt64 *size) PURE;
};
-STREAM_INTERFACE(IOutStreamFlush, 0x07)
+STREAM_INTERFACE(IOutStreamFinish, 0x07)
{
- STDMETHOD(Flush)() PURE;
+ STDMETHOD(OutStreamFinish)() PURE;
};
diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h
index 952333a8..8f52a126 100644
--- a/CPP/7zip/MyVersion.h
+++ b/CPP/7zip/MyVersion.h
@@ -1,6 +1,2 @@
-#include "..\..\C\7zVersion.h"
-
-#undef MY_COPYRIGHT
-#undef MY_VERSION_COPYRIGHT_DATE
-#define MY_COPYRIGHT "Copyright (c) 1999-2014 Igor Pavlov"
-#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE
+#define USE_COPYRIGHT_CR
+#include "../../C/7zVersion.h"
diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
index 82a7462b..3f3acb2d 100644
--- a/CPP/7zip/PropID.h
+++ b/CPP/7zip/PropID.h
@@ -100,13 +100,15 @@ enum
kpidHardLink,
kpidINode,
kpidStreamId,
+ kpidReadOnly,
+ kpidOutName,
kpid_NUM_DEFINED,
kpidUserDefined = 0x10000
};
-extern Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE
+extern const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE
const UInt32 kpv_ErrorFlags_IsNotArc = 1 << 0;
const UInt32 kpv_ErrorFlags_HeadersError = 1 << 1;
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
index d8221754..557282eb 100644
--- a/CPP/7zip/UI/Agent/Agent.cpp
+++ b/CPP/7zip/UI/Agent/Agent.cpp
@@ -2,12 +2,20 @@
#include "StdAfx.h"
+#include <wchar.h>
+
#include "../../../../C/Sort.h"
#include "../../../Common/ComTry.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
#include "../../../Windows/PropVariantConv.h"
+#ifndef _7ZIP_ST
+#include "../../../Windows/Synchronization.h"
+#endif
+
#include "../Common/ArchiveExtractCallback.h"
#include "../FileManager/RegistryUtils.h"
@@ -15,43 +23,109 @@
using namespace NWindows;
+CCodecs *g_CodecsObj;
+
+#ifdef EXTERNAL_CODECS
+ CExternalCodecs g_ExternalCodecs;
+ CCodecs::CReleaser g_CodecsReleaser;
+#else
+ CMyComPtr<IUnknown> g_CodecsRef;
+#endif
+
+#ifndef _7ZIP_ST
+static NSynchronization::CCriticalSection g_CriticalSection;
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+#define MT_LOCK
+#endif
+
+void FreeGlobalCodecs()
+{
+ MT_LOCK
+
+ #ifdef EXTERNAL_CODECS
+ if (g_CodecsObj)
+ {
+ g_CodecsObj->CloseLibs();
+ }
+ g_CodecsReleaser.Set(NULL);
+ g_CodecsObj = NULL;
+ g_ExternalCodecs.ClearAndRelease();
+ #else
+ g_CodecsRef.Release();
+ #endif
+}
+
+HRESULT LoadGlobalCodecs()
+{
+ MT_LOCK
+
+ if (g_CodecsObj)
+ return S_OK;
+
+ g_CodecsObj = new CCodecs;
+
+ #ifdef EXTERNAL_CODECS
+ g_ExternalCodecs.GetCodecs = g_CodecsObj;
+ g_ExternalCodecs.GetHashers = g_CodecsObj;
+ g_CodecsReleaser.Set(g_CodecsObj);
+ #else
+ g_CodecsRef.Release();
+ g_CodecsRef = g_CodecsObj;
+ #endif
+
+ RINOK(g_CodecsObj->Load());
+ if (g_CodecsObj->Formats.IsEmpty())
+ {
+ FreeGlobalCodecs();
+ return E_NOTIMPL;
+ }
+
+ #ifdef EXTERNAL_CODECS
+ RINOK(g_ExternalCodecs.Load());
+ #endif
+
+ return S_OK;
+}
+
STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)
{
*agentFolder = this;
return S_OK;
}
-void CAgentFolder::LoadFolder(unsigned proxyFolderIndex)
+void CAgentFolder::LoadFolder(unsigned proxyDirIndex)
{
- unsigned i;
CProxyItem item;
- item.ProxyFolderIndex = proxyFolderIndex;
- if (_proxyArchive2)
+ item.DirIndex = proxyDirIndex;
+
+ if (_proxy2)
{
- const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex];
- for (i = 0; i < folder.SubFiles.Size(); i++)
+ const CProxyDir2 &dir = _proxy2->Dirs[proxyDirIndex];
+ FOR_VECTOR (i, dir.Items)
{
item.Index = i;
_items.Add(item);
- const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]];
- int subFolderIndex = file.FolderIndex;
- if (subFolderIndex >= 0)
- LoadFolder(subFolderIndex);
- subFolderIndex = file.AltStreamsFolderIndex;
- if (subFolderIndex >= 0)
- LoadFolder(subFolderIndex);
+ const CProxyFile2 &file = _proxy2->Files[dir.Items[i]];
+ if (file.DirIndex >= 0)
+ LoadFolder(file.DirIndex);
+ if (_loadAltStreams && file.AltDirIndex >= 0)
+ LoadFolder(file.AltDirIndex);
}
return;
}
- const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex];
- for (i = 0; i < folder.Folders.Size(); i++)
+
+ const CProxyDir &dir = _proxy->Dirs[proxyDirIndex];
+ unsigned i;
+ for (i = 0; i < dir.SubDirs.Size(); i++)
{
item.Index = i;
_items.Add(item);
- LoadFolder(folder.Folders[i]);
+ LoadFolder(dir.SubDirs[i]);
}
- unsigned start = folder.Folders.Size();
- for (i = 0; i < folder.Files.Size(); i++)
+
+ unsigned start = dir.SubDirs.Size();
+ for (i = 0; i < dir.SubFiles.Size(); i++)
{
item.Index = start + i;
_items.Add(item);
@@ -64,7 +138,14 @@ STDMETHODIMP CAgentFolder::LoadItems()
return E_FAIL;
_items.Clear();
if (_flatMode)
- LoadFolder(_proxyFolderItem);
+ {
+ LoadFolder(_proxyDirIndex);
+ if (_proxy2 && _loadAltStreams)
+ {
+ if (_proxyDirIndex == k_Proxy2_RootDirIndex)
+ LoadFolder(k_Proxy2_AltRootDirIndex);
+ }
+ }
return S_OK;
}
@@ -72,37 +153,37 @@ STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems)
{
if (_flatMode)
*numItems = _items.Size();
- else if (_proxyArchive2)
- *numItems = _proxyArchive2->Folders[_proxyFolderItem].SubFiles.Size();
+ else if (_proxy2)
+ *numItems = _proxy2->Dirs[_proxyDirIndex].Items.Size();
else
{
- const CProxyFolder *folder = &_proxyArchive->Folders[_proxyFolderItem];
- *numItems = folder->Folders.Size() + folder ->Files.Size();
+ const CProxyDir *dir = &_proxy->Dirs[_proxyDirIndex];
+ *numItems = dir->SubDirs.Size() + dir->SubFiles.Size();
}
return S_OK;
}
-#define SET_realIndex_AND_folder \
- UInt32 realIndex; const CProxyFolder *folder; \
- if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \
- else { folder = &_proxyArchive->Folders[_proxyFolderItem]; realIndex = index; }
+#define SET_realIndex_AND_dir \
+ unsigned realIndex; const CProxyDir *dir; \
+ if (_flatMode) { const CProxyItem &item = _items[index]; dir = &_proxy->Dirs[item.DirIndex]; realIndex = item.Index; } \
+ else { dir = &_proxy->Dirs[_proxyDirIndex]; realIndex = index; }
-#define SET_realIndex_AND_folder_2 \
- UInt32 realIndex; const CProxyFolder2 *folder; \
- if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \
- else { folder = &_proxyArchive2->Folders[_proxyFolderItem]; realIndex = index; }
+#define SET_realIndex_AND_dir_2 \
+ unsigned realIndex; const CProxyDir2 *dir; \
+ if (_flatMode) { const CProxyItem &item = _items[index]; dir = &_proxy2->Dirs[item.DirIndex]; realIndex = item.Index; } \
+ else { dir = &_proxy2->Dirs[_proxyDirIndex]; realIndex = index; }
UString CAgentFolder::GetName(UInt32 index) const
{
- if (_proxyArchive2)
+ if (_proxy2)
{
- SET_realIndex_AND_folder_2
- return _proxyArchive2->Files[folder->SubFiles[realIndex]].Name;
+ SET_realIndex_AND_dir_2
+ return _proxy2->Files[dir->Items[realIndex]].Name;
}
- SET_realIndex_AND_folder
- if (realIndex < (UInt32)folder->Folders.Size())
- return _proxyArchive->Folders[folder->Folders[realIndex]].Name;
- return folder->Files[realIndex - folder->Folders.Size()].Name;
+ SET_realIndex_AND_dir
+ if (realIndex < dir->SubDirs.Size())
+ return _proxy->Dirs[dir->SubDirs[realIndex]].Name;
+ return _proxy->Files[dir->SubFiles[realIndex - dir->SubDirs.Size()]].Name;
}
void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const
@@ -112,97 +193,101 @@ void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const
prefix.Empty();
return;
}
+
const CProxyItem &item = _items[index];
- unsigned proxyIndex = item.ProxyFolderIndex;
- unsigned totalLen;
- if (_proxyArchive2)
+ unsigned proxyIndex = item.DirIndex;
+
+ if (_proxy2)
{
+ // that code is unused. 7-Zip gets prefix via GetItemPrefix() .
+
unsigned len = 0;
- while (proxyIndex != _proxyFolderItem)
+ while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs)
{
- const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex];
- len += file.NameSize + 1;
- proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream);
+ const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[proxyIndex].ArcIndex];
+ len += file.NameLen + 1;
+ proxyIndex = (file.Parent < 0) ? 0 : _proxy2->Files[file.Parent].GetDirIndex(file.IsAltStream);
}
- totalLen = len;
- wchar_t *p = prefix.GetBuffer(len);
- proxyIndex = item.ProxyFolderIndex;
- while (proxyIndex != _proxyFolderItem)
+ wchar_t *p = prefix.GetBuf_SetEnd(len) + len;
+ proxyIndex = item.DirIndex;
+ while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs)
{
- const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex];
- MyStringCopy(p + len - file.NameSize - 1, file.Name);
- p[--len] = WCHAR_PATH_SEPARATOR;
- len -= file.NameSize;
- proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream);
+ const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[proxyIndex].ArcIndex];
+ p--;
+ *p = WCHAR_PATH_SEPARATOR;
+ p -= file.NameLen;
+ wmemcpy(p, file.Name, file.NameLen);
+ proxyIndex = (file.Parent < 0) ? 0 : _proxy2->Files[file.Parent].GetDirIndex(file.IsAltStream);
}
}
else
{
unsigned len = 0;
- while (proxyIndex != _proxyFolderItem)
+ while (proxyIndex != _proxyDirIndex)
{
- const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex];
- len += folder->Name.Len() + 1;
- proxyIndex = folder->Parent;
+ const CProxyDir *dir = &_proxy->Dirs[proxyIndex];
+ len += dir->NameLen + 1;
+ proxyIndex = dir->ParentDir;
}
- totalLen = len;
- wchar_t *p = prefix.GetBuffer(len);
- proxyIndex = item.ProxyFolderIndex;
- while (proxyIndex != _proxyFolderItem)
+ wchar_t *p = prefix.GetBuf_SetEnd(len) + len;
+ proxyIndex = item.DirIndex;
+ while (proxyIndex != _proxyDirIndex)
{
- const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex];
- MyStringCopy(p + len - folder->Name.Len() - 1, (const wchar_t *)folder->Name);
- p[--len] = WCHAR_PATH_SEPARATOR;
- len -= folder->Name.Len();
- proxyIndex = folder->Parent;
+ const CProxyDir *dir = &_proxy->Dirs[proxyIndex];
+ p--;
+ *p = WCHAR_PATH_SEPARATOR;
+ p -= dir->NameLen;
+ wmemcpy(p, dir->Name, dir->NameLen);
+ proxyIndex = dir->ParentDir;
}
}
- prefix.ReleaseBuffer(totalLen);
}
-UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const
+UString CAgentFolder::GetFullPrefix(UInt32 index) const
{
- UString prefix;
- GetPrefix(index, prefix);
- if (_proxyArchive2)
- return _proxyArchive2->GetFullPathPrefix(_proxyFolderItem) + prefix;
+ int foldIndex = _proxyDirIndex;
+
+ if (_flatMode)
+ foldIndex = _items[index].DirIndex;
+
+ if (_proxy2)
+ return _proxy2->Dirs[foldIndex].PathPrefix;
else
- return _proxyArchive->GetFullPathPrefix(_proxyFolderItem) + prefix;
+ return _proxy->GetDirPath_as_Prefix(foldIndex);
}
STDMETHODIMP_(UInt64) CAgentFolder::GetItemSize(UInt32 index)
{
unsigned arcIndex;
- if (_proxyArchive2)
+ if (_proxy2)
{
- SET_realIndex_AND_folder_2
- arcIndex = folder->SubFiles[realIndex];
- const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ SET_realIndex_AND_dir_2
+ arcIndex = dir->Items[realIndex];
+ const CProxyFile2 &item = _proxy2->Files[arcIndex];
if (item.IsDir())
{
- const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex];
+ const CProxyDir2 &itemFolder = _proxy2->Dirs[item.DirIndex];
if (!_flatMode)
return itemFolder.Size;
}
}
else
{
- SET_realIndex_AND_folder
- if (realIndex < (UInt32)folder->Folders.Size())
+ SET_realIndex_AND_dir
+ if (realIndex < dir->SubDirs.Size())
{
- const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
+ const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
if (!_flatMode)
return item.Size;
- if (!item.IsLeaf)
+ if (!item.IsLeaf())
return 0;
- arcIndex = item.Index;
+ arcIndex = item.ArcIndex;
}
else
{
- const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()];
- arcIndex = item.Index;
+ arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
}
}
NCOM::CPropVariant prop;
@@ -227,11 +312,19 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT
prop = prefix;
}
}
- else if (_proxyArchive2)
+ else if (_proxy2)
{
- SET_realIndex_AND_folder_2
- unsigned arcIndex = folder->SubFiles[realIndex];
- const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ SET_realIndex_AND_dir_2
+ unsigned arcIndex = dir->Items[realIndex];
+ const CProxyFile2 &item = _proxy2->Files[arcIndex];
+ /*
+ if (propID == kpidNumAltStreams)
+ {
+ if (item.AltDirIndex >= 0)
+ prop = _proxy2->Dirs[item.AltDirIndex].Items.Size();
+ }
+ else
+ */
if (!item.IsDir())
{
switch (propID)
@@ -243,7 +336,7 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT
}
else
{
- const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex];
+ const CProxyDir2 &itemFolder = _proxy2->Dirs[item.DirIndex];
if (!_flatMode && propID == kpidSize)
prop = itemFolder.Size;
else if (!_flatMode && propID == kpidPackSize)
@@ -251,7 +344,7 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT
else switch (propID)
{
case kpidIsDir: prop = true; break;
- case kpidNumSubDirs: prop = itemFolder.NumSubFolders; break;
+ case kpidNumSubDirs: prop = itemFolder.NumSubDirs; break;
case kpidNumSubFiles: prop = itemFolder.NumSubFiles; break;
case kpidName: prop = item.Name; break;
case kpidCRC:
@@ -274,10 +367,10 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT
}
else
{
- SET_realIndex_AND_folder
- if (realIndex < (UInt32)folder->Folders.Size())
+ SET_realIndex_AND_dir
+ if (realIndex < dir->SubDirs.Size())
{
- const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
+ const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
if (!_flatMode && propID == kpidSize)
prop = item.Size;
else if (!_flatMode && propID == kpidPackSize)
@@ -286,33 +379,33 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT
switch (propID)
{
case kpidIsDir: prop = true; break;
- case kpidNumSubDirs: prop = item.NumSubFolders; break;
+ case kpidNumSubDirs: prop = item.NumSubDirs; break;
case kpidNumSubFiles: prop = item.NumSubFiles; break;
case kpidName: prop = item.Name; break;
case kpidCRC:
{
- if (item.IsLeaf)
+ if (item.IsLeaf())
{
- RINOK(_agentSpec->GetArchive()->GetProperty(item.Index, propID, value));
+ RINOK(_agentSpec->GetArchive()->GetProperty(item.ArcIndex, propID, value));
}
if (item.CrcIsDefined && value->vt == VT_EMPTY)
prop = item.Crc;
break;
}
default:
- if (item.IsLeaf)
- return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
+ if (item.IsLeaf())
+ return _agentSpec->GetArchive()->GetProperty(item.ArcIndex, propID, value);
}
}
else
{
- const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()];
+ unsigned arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
switch (propID)
{
case kpidIsDir: prop = false; break;
- case kpidName: prop = item.Name; break;
+ case kpidName: prop = _proxy->Files[arcIndex].Name; break;
default:
- return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
+ return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value);
}
}
}
@@ -334,30 +427,30 @@ static UInt64 GetUInt64Prop(IInArchive *archive, UInt32 index, PROPID propID)
STDMETHODIMP CAgentFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len)
{
- if (_proxyArchive2)
+ if (_proxy2)
{
- SET_realIndex_AND_folder_2
- unsigned arcIndex = folder->SubFiles[realIndex];
- const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ SET_realIndex_AND_dir_2
+ unsigned arcIndex = dir->Items[realIndex];
+ const CProxyFile2 &item = _proxy2->Files[arcIndex];
*name = item.Name;
- *len = item.NameSize;
+ *len = item.NameLen;
return S_OK;
}
else
{
- SET_realIndex_AND_folder
- if (realIndex < (UInt32)folder->Folders.Size())
+ SET_realIndex_AND_dir
+ if (realIndex < dir->SubDirs.Size())
{
- const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
+ const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
*name = item.Name;
- *len = item.Name.Len();
+ *len = item.NameLen;
return S_OK;
}
else
{
- const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()];
+ const CProxyFile &item = _proxy->Files[dir->SubFiles[realIndex - dir->SubDirs.Size()]];
*name = item.Name;
- *len = item.Name.Len();
+ *len = item.NameLen;
return S_OK;
}
}
@@ -369,26 +462,21 @@ STDMETHODIMP CAgentFolder::GetItemPrefix(UInt32 index, const wchar_t **name, uns
*len = 0;
if (!_flatMode)
return S_OK;
- if (_proxyArchive2)
- {
- SET_realIndex_AND_folder_2
- unsigned arcIndex = folder->SubFiles[realIndex];
- const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
- if (item.Parent >= 0)
+ if (_proxy2)
+ {
+ const CProxyItem &item = _items[index];
+ const UString &s = _proxy2->Dirs[item.DirIndex].PathPrefix;
+ unsigned baseLen = _proxy2->Dirs[_proxyDirIndex].PathPrefix.Len();
+ if (baseLen <= s.Len())
{
- const CProxyFile2 &item2 = _proxyArchive2->Files[item.Parent];
- int foldInd = item2.GetFolderIndex(item.IsAltStream);
- if (foldInd >= 0)
- {
- const UString &s = _proxyArchive2->Folders[foldInd].PathPrefix;
- unsigned baseLen = _proxyArchive2->Folders[_proxyFolderItem].PathPrefix.Len();
- if (baseLen <= s.Len())
- {
- *name = (const wchar_t *)s + baseLen;
- *len = s.Len() - baseLen;
- }
- }
+ *name = (const wchar_t *)s + baseLen;
+ *len = s.Len() - baseLen;
+ }
+ else
+ {
+ return E_FAIL;
+ // throw 111l;
}
}
return S_OK;
@@ -437,21 +525,21 @@ static const wchar_t *GetExtension(const wchar_t *name)
int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw)
{
- UInt32 realIndex1, realIndex2;
- const CProxyFolder2 *folder1, *folder2;
+ unsigned realIndex1, realIndex2;
+ const CProxyDir2 *dir1, *dir2;
if (_flatMode)
{
const CProxyItem &item1 = _items[index1];
const CProxyItem &item2 = _items[index2];
- folder1 = &_proxyArchive2->Folders[item1.ProxyFolderIndex];
- folder2 = &_proxyArchive2->Folders[item2.ProxyFolderIndex];
+ dir1 = &_proxy2->Dirs[item1.DirIndex];
+ dir2 = &_proxy2->Dirs[item2.DirIndex];
realIndex1 = item1.Index;
realIndex2 = item2.Index;
}
else
{
- folder2 = folder1 = &_proxyArchive2->Folders[_proxyFolderItem];
+ dir2 = dir1 = &_proxy2->Dirs[_proxyDirIndex];
realIndex1 = index1;
realIndex2 = index2;
}
@@ -459,10 +547,10 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int
UInt32 arcIndex1;
UInt32 arcIndex2;
bool isDir1, isDir2;
- arcIndex1 = folder1->SubFiles[realIndex1];
- arcIndex2 = folder2->SubFiles[realIndex2];
- const CProxyFile2 &prox1 = _proxyArchive2->Files[arcIndex1];
- const CProxyFile2 &prox2 = _proxyArchive2->Files[arcIndex2];
+ arcIndex1 = dir1->Items[realIndex1];
+ arcIndex2 = dir2->Items[realIndex2];
+ const CProxyFile2 &prox1 = _proxy2->Files[arcIndex1];
+ const CProxyFile2 &prox2 = _proxy2->Files[arcIndex2];
if (propID == kpidName)
{
@@ -473,14 +561,9 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int
{
if (!_flatMode)
return 0;
- if (prox1.Parent < 0) return prox2.Parent < 0 ? 0 : -1;
- if (prox2.Parent < 0) return 1;
-
- const CProxyFile2 &proxPar1 = _proxyArchive2->Files[prox1.Parent];
- const CProxyFile2 &proxPar2 = _proxyArchive2->Files[prox2.Parent];
return CompareFileNames_ForFolderList(
- _proxyArchive2->Folders[proxPar1.GetFolderIndex(prox1.IsAltStream)].PathPrefix,
- _proxyArchive2->Folders[proxPar2.GetFolderIndex(prox2.IsAltStream)].PathPrefix);
+ _proxy2->Dirs[_items[index1].DirIndex].PathPrefix,
+ _proxy2->Dirs[_items[index2].DirIndex].PathPrefix);
}
if (propID == kpidExtension)
@@ -500,17 +583,17 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int
return isDir1 ? -1 : 1;
}
- const CProxyFolder2 *proxFolder1 = NULL;
- const CProxyFolder2 *proxFolder2 = NULL;
- if (isDir1) proxFolder1 = &_proxyArchive2->Folders[prox1.FolderIndex];
- if (isDir2) proxFolder2 = &_proxyArchive2->Folders[prox2.FolderIndex];
+ const CProxyDir2 *proxFolder1 = NULL;
+ const CProxyDir2 *proxFolder2 = NULL;
+ if (isDir1) proxFolder1 = &_proxy2->Dirs[prox1.DirIndex];
+ if (isDir2) proxFolder2 = &_proxy2->Dirs[prox2.DirIndex];
if (propID == kpidNumSubDirs)
{
UInt32 n1 = 0;
UInt32 n2 = 0;
- if (isDir1) n1 = proxFolder1->NumSubFolders;
- if (isDir2) n2 = proxFolder2->NumSubFolders;
+ if (isDir1) n1 = proxFolder1->NumSubDirs;
+ if (isDir2) n2 = proxFolder2->NumSubDirs;
return MyCompare(n1, n2);
}
@@ -585,27 +668,29 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int
STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw)
{
- COM_TRY_BEGIN
- if (_proxyArchive2)
+ try {
+ if (_proxy2)
return CompareItems2(index1, index2, propID, propIsRaw);
- UInt32 realIndex1, realIndex2;
- const CProxyFolder *folder1, *folder2;
+ unsigned realIndex1, realIndex2;
+ const CProxyDir *dir1, *dir2;
+
if (_flatMode)
{
const CProxyItem &item1 = _items[index1];
const CProxyItem &item2 = _items[index2];
- folder1 = &_proxyArchive->Folders[item1.ProxyFolderIndex];
- folder2 = &_proxyArchive->Folders[item2.ProxyFolderIndex];
+ dir1 = &_proxy->Dirs[item1.DirIndex];
+ dir2 = &_proxy->Dirs[item2.DirIndex];
realIndex1 = item1.Index;
realIndex2 = item2.Index;
}
else
{
- folder2 = folder1 = &_proxyArchive->Folders[_proxyFolderItem];
+ dir2 = dir1 = &_proxy->Dirs[_proxyDirIndex];
realIndex1 = index1;
realIndex2 = index2;
}
+
if (propID == kpidPrefix)
{
if (!_flatMode)
@@ -615,109 +700,116 @@ STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PR
GetPrefix(index2, prefix2);
return CompareFileNames_ForFolderList(prefix1, prefix2);
}
- const CProxyFile *prox1;
- const CProxyFile *prox2;
- const CProxyFolder *proxFolder1 = NULL;
- const CProxyFolder *proxFolder2 = NULL;
- bool isDir1, isDir2;
- if (realIndex1 < (UInt32)folder1->Folders.Size())
+
+ UInt32 arcIndex1;
+ UInt32 arcIndex2;
+
+ const CProxyDir *proxFolder1 = NULL;
+ const CProxyDir *proxFolder2 = NULL;
+
+ if (realIndex1 < dir1->SubDirs.Size())
{
- isDir1 = true;
- prox1 = proxFolder1 = &_proxyArchive->Folders[folder1->Folders[realIndex1]];
+ proxFolder1 = &_proxy->Dirs[dir1->SubDirs[realIndex1]];
+ arcIndex1 = proxFolder1->ArcIndex;
}
else
- {
- isDir1 = false;
- prox1 = &folder1->Files[realIndex1 - folder1->Folders.Size()];
- }
+ arcIndex1 = dir1->SubFiles[realIndex1 - dir1->SubDirs.Size()];
- if (realIndex2 < (UInt32)folder2->Folders.Size())
+ if (realIndex2 < dir2->SubDirs.Size())
{
- isDir2 = true;
- prox2 = proxFolder2 = &_proxyArchive->Folders[folder2->Folders[realIndex2]];
+ proxFolder2 = &_proxy->Dirs[dir2->SubDirs[realIndex2]];
+ arcIndex2 = proxFolder2->ArcIndex;
}
else
- {
- isDir2 = false;
- prox2 = &folder2->Files[realIndex2 - folder2->Folders.Size()];
- }
+ arcIndex2 = dir2->SubFiles[realIndex2 - dir2->SubDirs.Size()];
if (propID == kpidName)
- {
- return CompareFileNames_ForFolderList(prox1->Name, prox2->Name);
- }
+ return CompareFileNames_ForFolderList(
+ proxFolder1 ? proxFolder1->Name : _proxy->Files[arcIndex1].Name,
+ proxFolder2 ? proxFolder2->Name : _proxy->Files[arcIndex2].Name);
+
if (propID == kpidExtension)
- {
- return CompareFileNames_ForFolderList(
- GetExtension(prox1->Name),
- GetExtension(prox2->Name));
- }
+ return CompareFileNames_ForFolderList(
+ GetExtension(proxFolder1 ? proxFolder1->Name : _proxy->Files[arcIndex1].Name),
+ GetExtension(proxFolder2 ? proxFolder2->Name : _proxy->Files[arcIndex2].Name));
if (propID == kpidIsDir)
{
- if (isDir1 == isDir2)
- return 0;
- return isDir1 ? -1 : 1;
+ if (proxFolder1)
+ return proxFolder2 ? 0 : -1;
+ return proxFolder2 ? 1 : 0;
}
+
if (propID == kpidNumSubDirs)
{
UInt32 n1 = 0;
UInt32 n2 = 0;
- if (isDir1) n1 = proxFolder1->NumSubFolders;
- if (isDir2) n2 = proxFolder2->NumSubFolders;
+ if (proxFolder1) n1 = proxFolder1->NumSubDirs;
+ if (proxFolder2) n2 = proxFolder2->NumSubDirs;
return MyCompare(n1, n2);
}
+
if (propID == kpidNumSubFiles)
{
UInt32 n1 = 0;
UInt32 n2 = 0;
- if (isDir1) n1 = proxFolder1->NumSubFiles;
- if (isDir2) n2 = proxFolder2->NumSubFiles;
+ if (proxFolder1) n1 = proxFolder1->NumSubFiles;
+ if (proxFolder2) n2 = proxFolder2->NumSubFiles;
return MyCompare(n1, n2);
}
+
if (propID == kpidSize)
{
UInt64 n1, n2;
- if (isDir1)
+ if (proxFolder1)
n1 = _flatMode ? 0 : proxFolder1->Size;
else
- n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidSize);
- if (isDir2)
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidSize);
+ if (proxFolder2)
n2 = _flatMode ? 0 : proxFolder2->Size;
else
- n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidSize);
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidSize);
return MyCompare(n1, n2);
}
+
if (propID == kpidPackSize)
{
UInt64 n1, n2;
- if (isDir1)
+ if (proxFolder1)
n1 = _flatMode ? 0 : proxFolder1->PackSize;
else
- n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidPackSize);
- if (isDir2)
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidPackSize);
+ if (proxFolder2)
n2 = _flatMode ? 0 : proxFolder2->PackSize;
else
- n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidPackSize);
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidPackSize);
return MyCompare(n1, n2);
}
if (propID == kpidCRC)
{
UInt64 n1, n2;
- if (!isDir1 || proxFolder1->IsLeaf)
- n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidCRC);
- else
+ if (proxFolder1 && !proxFolder1->IsLeaf())
n1 = proxFolder1->Crc;
- if (!isDir2 || proxFolder2->IsLeaf)
- n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidCRC);
else
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidCRC);
+ if (proxFolder2 && !proxFolder2->IsLeaf())
n2 = proxFolder2->Crc;
+ else
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidCRC);
return MyCompare(n1, n2);
}
if (propIsRaw)
- return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), prox1->Index, prox2->Index, propID);
+ {
+ bool isVirt1 = (proxFolder1 && !proxFolder1->IsLeaf());
+ bool isVirt2 = (proxFolder2 && !proxFolder2->IsLeaf());
+ if (isVirt1)
+ return isVirt2 ? 0 : -1;
+ if (isVirt2)
+ return 1;
+ return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID);
+ }
NCOM::CPropVariant prop1, prop2;
// Name must be first property
@@ -733,21 +825,20 @@ STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PR
}
return prop1.Compare(prop2);
- COM_TRY_END
+ } catch(...) { return 0; }
}
-HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder)
+HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder)
{
+ /*
CMyComPtr<IFolderFolder> parentFolder;
- if (_proxyArchive2)
+ if (_proxy2)
{
- parentFolder = NULL; // Change it;
- const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex];
- int par = _proxyArchive2->GetParentFolderOfFile(folder.ArcIndex);
- if (par != (int)_proxyFolderItem)
+ const CProxyDir2 &dir = _proxy2->Dirs[proxyDirIndex];
+ int par = _proxy2->GetParentFolderOfFile(dir.ArcIndex);
+ if (par != (int)_proxyDirIndex)
{
- // return E_FAIL;
RINOK(BindToFolder_Internal(par, &parentFolder));
}
else
@@ -755,17 +846,18 @@ HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFo
}
else
{
- const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex];
- if (folder.Parent != (int)_proxyFolderItem)
+ const CProxyDir &dir = _proxy->Dirs[proxyDirIndex];
+ if (dir.Parent != (int)_proxyDirIndex)
{
- RINOK(BindToFolder_Internal(folder.Parent, &parentFolder));
+ RINOK(BindToFolder_Internal(dir.Parent, &parentFolder));
}
else
parentFolder = this;
}
+ */
CAgentFolder *folderSpec = new CAgentFolder;
CMyComPtr<IFolderFolder> agentFolder = folderSpec;
- folderSpec->Init(_proxyArchive, _proxyArchive2, proxyFolderIndex, parentFolder, _agentSpec);
+ folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec);
*resultFolder = agentFolder.Detach();
return S_OK;
}
@@ -773,51 +865,229 @@ HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFo
STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
{
COM_TRY_BEGIN
- if (_proxyArchive2)
+ if (_proxy2)
{
- SET_realIndex_AND_folder_2
- unsigned arcIndex = folder->SubFiles[realIndex];
- const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ SET_realIndex_AND_dir_2
+ unsigned arcIndex = dir->Items[realIndex];
+ const CProxyFile2 &item = _proxy2->Files[arcIndex];
if (!item.IsDir())
return E_INVALIDARG;
- return BindToFolder_Internal(item.FolderIndex, resultFolder);
+ return BindToFolder_Internal(item.DirIndex, resultFolder);
}
- SET_realIndex_AND_folder
- if (realIndex >= (UInt32)folder->Folders.Size())
+ SET_realIndex_AND_dir
+ if (realIndex >= (UInt32)dir->SubDirs.Size())
return E_INVALIDARG;
- return BindToFolder_Internal(folder->Folders[realIndex], resultFolder);
+ return BindToFolder_Internal(dir->SubDirs[realIndex], resultFolder);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
{
COM_TRY_BEGIN
- if (_proxyArchive2)
+ if (_proxy2)
{
- const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem];
- FOR_VECTOR (i, folder.SubFiles)
- {
- const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]];
- if (file.FolderIndex >= 0)
- if (StringsAreEqualNoCase(file.Name, name))
- return BindToFolder_Internal(file.FolderIndex, resultFolder);
- }
- return E_INVALIDARG;
+ int index = _proxy2->FindItem(_proxyDirIndex, name, true);
+ if (index < 0)
+ return E_INVALIDARG;
+ return BindToFolder_Internal(_proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]].DirIndex, resultFolder);
}
- int index = _proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name);
+ int index = _proxy->FindSubDir(_proxyDirIndex, name);
if (index < 0)
return E_INVALIDARG;
return BindToFolder_Internal(index, resultFolder);
COM_TRY_END
}
+
+
+// ---------- IFolderAltStreams ----------
+
+HRESULT CAgentFolder::BindToAltStreams_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder)
+{
+ *resultFolder = NULL;
+ if (!_proxy2)
+ return S_OK;
+
+ /*
+ CMyComPtr<IFolderFolder> parentFolder;
+
+ int par = _proxy2->GetParentFolderOfFile(_proxy2->Dirs[proxyDirIndex].ArcIndex);
+ if (par != (int)_proxyDirIndex)
+ {
+ RINOK(BindToFolder_Internal(par, &parentFolder));
+ if (!parentFolder)
+ return S_OK;
+ }
+ else
+ parentFolder = this;
+ */
+
+ CAgentFolder *folderSpec = new CAgentFolder;
+ CMyComPtr<IFolderFolder> agentFolder = folderSpec;
+ folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec);
+ *resultFolder = agentFolder.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::BindToAltStreams(UInt32 index, IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+
+ *resultFolder = NULL;
+
+ if (!_proxy2)
+ return S_OK;
+
+ if (_proxy2->IsAltDir(_proxyDirIndex))
+ return S_OK;
+
+ {
+ if (index == (UInt32)(Int32)-1)
+ {
+ unsigned altDirIndex;
+ // IFolderFolder *parentFolder;
+
+ if (_proxyDirIndex == k_Proxy2_RootDirIndex)
+ {
+ altDirIndex = k_Proxy2_AltRootDirIndex;
+ // parentFolder = this; // we want to use Root dir as parent for alt root
+ }
+ else
+ {
+ unsigned arcIndex = _proxy2->Dirs[_proxyDirIndex].ArcIndex;
+ const CProxyFile2 &item = _proxy2->Files[arcIndex];
+ if (item.AltDirIndex < 0)
+ return S_OK;
+ altDirIndex = item.AltDirIndex;
+ // parentFolder = _parentFolder;
+ }
+
+ CAgentFolder *folderSpec = new CAgentFolder;
+ CMyComPtr<IFolderFolder> agentFolder = folderSpec;
+ folderSpec->Init(_proxy, _proxy2, altDirIndex, /* parentFolder, */ _agentSpec);
+ *resultFolder = agentFolder.Detach();
+ return S_OK;
+ }
+
+ SET_realIndex_AND_dir_2
+ unsigned arcIndex = dir->Items[realIndex];
+ const CProxyFile2 &item = _proxy2->Files[arcIndex];
+ if (item.AltDirIndex < 0)
+ return S_OK;
+ return BindToAltStreams_Internal(item.AltDirIndex, resultFolder);
+ }
+
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::BindToAltStreams(const wchar_t *name, IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+
+ *resultFolder = NULL;
+
+ if (!_proxy2)
+ return S_OK;
+
+ if (_proxy2->IsAltDir(_proxyDirIndex))
+ return S_OK;
+
+ if (name[0] == 0)
+ return BindToAltStreams((UInt32)(Int32)-1, resultFolder);
+
+ {
+ const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex];
+ FOR_VECTOR (i, dir.Items)
+ {
+ const CProxyFile2 &file = _proxy2->Files[dir.Items[i]];
+ if (file.AltDirIndex >= 0)
+ if (CompareFileNames(file.Name, name) == 0)
+ return BindToAltStreams_Internal(file.AltDirIndex, resultFolder);
+ }
+ return E_INVALIDARG;
+ }
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::AreAltStreamsSupported(UInt32 index, Int32 *isSupported)
+{
+ *isSupported = BoolToInt(false);
+
+ if (!_proxy2)
+ return S_OK;
+
+ if (_proxy2->IsAltDir(_proxyDirIndex))
+ return S_OK;
+
+ unsigned arcIndex;
+
+ if (index == (UInt32)(Int32)-1)
+ {
+ if (_proxyDirIndex == k_Proxy2_RootDirIndex)
+ {
+ *isSupported = BoolToInt(true);
+ return S_OK;
+ }
+ arcIndex = _proxy2->Dirs[_proxyDirIndex].ArcIndex;
+ }
+ else
+ {
+ SET_realIndex_AND_dir_2
+ arcIndex = dir->Items[realIndex];
+ }
+
+ if (_proxy2->Files[arcIndex].AltDirIndex >= 0)
+ *isSupported = BoolToInt(true);
+ return S_OK;
+}
+
+
STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder)
{
- // COM_TRY_BEGIN
+ COM_TRY_BEGIN
+ /*
CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
*resultFolder = parentFolder.Detach();
+ */
+ *resultFolder = NULL;
+
+ unsigned proxyDirIndex;
+
+ if (_proxy2)
+ {
+ if (_proxyDirIndex == k_Proxy2_RootDirIndex)
+ return S_OK;
+ if (_proxyDirIndex == k_Proxy2_AltRootDirIndex)
+ proxyDirIndex = k_Proxy2_RootDirIndex;
+ else
+ {
+ const CProxyDir2 &fold = _proxy2->Dirs[_proxyDirIndex];
+ const CProxyFile2 &file = _proxy2->Files[fold.ArcIndex];
+ int parentIndex = file.Parent;
+ if (parentIndex < 0)
+ proxyDirIndex = k_Proxy2_RootDirIndex;
+ else
+ {
+ const CProxyFile2 &file = _proxy2->Files[parentIndex];
+ proxyDirIndex = file.DirIndex;
+ }
+ }
+ }
+ else
+ {
+ int parent = _proxy->Dirs[_proxyDirIndex].ParentDir;
+ if (parent < 0)
+ return S_OK;
+ proxyDirIndex = parent;
+ }
+
+ CAgentFolder *folderSpec = new CAgentFolder;
+ CMyComPtr<IFolderFolder> agentFolder = folderSpec;
+ folderSpec->Init(_proxy, _proxy2, proxyDirIndex, /* parentFolder, */ _agentSpec);
+ *resultFolder = agentFolder.Detach();
+
return S_OK;
- // COM_TRY_END
+ COM_TRY_END
}
STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream)
@@ -827,33 +1097,37 @@ STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream)
if (!getStream)
return S_OK;
- UInt32 indexInArchive;
- if (_proxyArchive2)
+ UInt32 arcIndex;
+ if (_proxy2)
{
- SET_realIndex_AND_folder_2
- indexInArchive = folder->SubFiles[realIndex];
+ SET_realIndex_AND_dir_2
+ arcIndex = dir->Items[realIndex];
}
else
{
- SET_realIndex_AND_folder
+ SET_realIndex_AND_dir
- if (realIndex < (UInt32)folder->Folders.Size())
- {
- const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
- if (!item.IsLeaf)
- return S_OK;
- indexInArchive = item.Index;
- }
- else
- indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index;
+ if (realIndex < dir->SubDirs.Size())
+ {
+ const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
+ if (!item.IsLeaf())
+ return S_OK;
+ arcIndex = item.ArcIndex;
+ }
+ else
+ arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
}
- return getStream->GetStream(indexInArchive, stream);
+ return getStream->GetStream(arcIndex, stream);
}
+// static const unsigned k_FirstOptionalProp = 2;
+
static const PROPID kProps[] =
{
kpidNumSubDirs,
kpidNumSubFiles,
+
+ // kpidNumAltStreams,
kpidPrefix
};
@@ -872,9 +1146,13 @@ STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps)
if (!_flatMode)
(*numProps)--;
/*
- bool thereIsPathProp = _proxyArchive2 ?
- _agentSpec->_proxyArchive2->ThereIsPathProp :
- _agentSpec->_proxyArchive->ThereIsPathProp;
+ if (!_agentSpec->ThereIsAltStreamProp)
+ (*numProps)--;
+ */
+ /*
+ bool thereIsPathProp = _proxy2 ?
+ _agentSpec->_proxy2->ThereIsPathProp :
+ _agentSpec->_proxy->ThereIsPathProp;
*/
// if there is kpidPath, we change kpidPath to kpidName
@@ -892,9 +1170,9 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro
_agentSpec->GetArchive()->GetNumberOfProperties(&numProps);
/*
- bool thereIsPathProp = _proxyArchive2 ?
- _agentSpec->_proxyArchive2->ThereIsPathProp :
- _agentSpec->_proxyArchive->ThereIsPathProp;
+ bool thereIsPathProp = _proxy2 ?
+ _agentSpec->_proxy2->ThereIsPathProp :
+ _agentSpec->_proxy->ThereIsPathProp;
*/
if (!_agentSpec->ThereIsPathProp)
@@ -917,7 +1195,15 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro
}
else
{
- *propID = kProps[index - numProps];
+ index -= numProps;
+ /*
+ if (index >= k_FirstOptionalProp)
+ {
+ if (!_agentSpec->ThereIsAltStreamProp)
+ index++;
+ }
+ */
+ *propID = kProps[index];
*varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID];
*name = 0;
}
@@ -940,44 +1226,47 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
- if (_proxyArchive2)
+ if (propID == kpidReadOnly)
+ prop = _agentSpec->IsThereReadOnlyArc();
+ else if (_proxy2)
{
- const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem];
+ const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex];
if (propID == kpidName)
{
- if (folder.ArcIndex >= 0)
- prop = _proxyArchive2->Files[folder.ArcIndex].Name;
+ if (dir.ArcIndex >= 0)
+ prop = _proxy2->Files[dir.ArcIndex].Name;
}
else if (propID == kpidPath)
{
- prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem);
+ bool isAltStreamFolder = false;
+ prop = _proxy2->GetDirPath_as_Prefix(_proxyDirIndex, isAltStreamFolder);
}
else switch (propID)
{
- case kpidSize: prop = folder.Size; break;
- case kpidPackSize: prop = folder.PackSize; break;
- case kpidNumSubDirs: prop = folder.NumSubFolders; break;
- case kpidNumSubFiles: prop = folder.NumSubFiles; break;
- // case kpidName: prop = folder.Name; break;
- // case kpidPath: prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem); break;
+ case kpidSize: prop = dir.Size; break;
+ case kpidPackSize: prop = dir.PackSize; break;
+ case kpidNumSubDirs: prop = dir.NumSubDirs; break;
+ case kpidNumSubFiles: prop = dir.NumSubFiles; break;
+ // case kpidName: prop = dir.Name; break;
+ // case kpidPath: prop = _proxy2->GetFullPathPrefix(_proxyDirIndex); break;
case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break;
- case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break;
+ case kpidCRC: if (dir.CrcIsDefined) prop = dir.Crc; break;
}
}
else
{
- const CProxyFolder &folder = _proxyArchive->Folders[_proxyFolderItem];
+ const CProxyDir &dir = _proxy->Dirs[_proxyDirIndex];
switch (propID)
{
- case kpidSize: prop = folder.Size; break;
- case kpidPackSize: prop = folder.PackSize; break;
- case kpidNumSubDirs: prop = folder.NumSubFolders; break;
- case kpidNumSubFiles: prop = folder.NumSubFiles; break;
- case kpidName: prop = folder.Name; break;
- case kpidPath: prop = _proxyArchive->GetFullPathPrefix(_proxyFolderItem); break;
+ case kpidSize: prop = dir.Size; break;
+ case kpidPackSize: prop = dir.PackSize; break;
+ case kpidNumSubDirs: prop = dir.NumSubDirs; break;
+ case kpidNumSubFiles: prop = dir.NumSubFiles; break;
+ case kpidName: prop = dir.Name; break;
+ case kpidPath: prop = _proxy->GetDirPath_as_Prefix(_proxyDirIndex); break;
case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break;
- case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break;
+ case kpidCRC: if (dir.CrcIsDefined) prop = dir.Crc; break;
}
}
prop.Detach(value);
@@ -1022,31 +1311,28 @@ STDMETHODIMP CAgentFolder::GetRawProp(UInt32 index, PROPID propID, const void **
if (rawProps)
{
unsigned arcIndex;
- if (_proxyArchive2)
+ if (_proxy2)
{
- SET_realIndex_AND_folder_2
- arcIndex = folder->SubFiles[realIndex];
+ SET_realIndex_AND_dir_2
+ arcIndex = dir->Items[realIndex];
}
else
{
- SET_realIndex_AND_folder
- if (realIndex < (UInt32)folder->Folders.Size())
+ SET_realIndex_AND_dir
+ if (realIndex < dir->SubDirs.Size())
{
- const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
- if (!item.IsLeaf)
+ const CProxyDir &item = _proxy->Dirs[dir->SubDirs[realIndex]];
+ if (!item.IsLeaf())
{
*data = NULL;
*dataSize = 0;
*propType = 0;
return S_OK;
}
- arcIndex = item.Index;
+ arcIndex = item.ArcIndex;
}
else
- {
- const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()];
- arcIndex = item.Index;
- }
+ arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
}
return rawProps->GetRawProp(arcIndex, propID, data, dataSize, propType);
}
@@ -1077,30 +1363,30 @@ int CAgentFolder::GetRealIndex(unsigned index) const
{
if (!_flatMode)
{
- if (_proxyArchive2)
- return _proxyArchive2->GetRealIndex(_proxyFolderItem, index);
+ if (_proxy2)
+ return _proxy2->GetRealIndex(_proxyDirIndex, index);
else
- return _proxyArchive->GetRealIndex(_proxyFolderItem, index);
+ return _proxy->GetRealIndex(_proxyDirIndex, index);
}
{
const CProxyItem &item = _items[index];
- if (_proxyArchive2)
+ if (_proxy2)
{
- const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex];
- return folder->SubFiles[item.Index];
+ const CProxyDir2 *dir = &_proxy2->Dirs[item.DirIndex];
+ return dir->Items[item.Index];
}
else
{
- const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex];
+ const CProxyDir *dir = &_proxy->Dirs[item.DirIndex];
unsigned realIndex = item.Index;
- if (realIndex < folder->Folders.Size())
+ if (realIndex < dir->SubDirs.Size())
{
- const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]];
- if (!f.IsLeaf)
+ const CProxyDir &f = _proxy->Dirs[dir->SubDirs[realIndex]];
+ if (!f.IsLeaf())
return -1;
- return f.Index;
+ return f.ArcIndex;
}
- return folder->Files[realIndex - folder->Folders.Size()].Index;
+ return dir->SubFiles[realIndex - dir->SubDirs.Size()];
}
}
}
@@ -1109,43 +1395,46 @@ void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool i
{
if (!_flatMode)
{
- if (_proxyArchive2)
- _proxyArchive2->GetRealIndices(_proxyFolderItem, indices, numItems, includeAltStreams, realIndices);
+ if (_proxy2)
+ _proxy2->GetRealIndices(_proxyDirIndex, indices, numItems, includeAltStreams, realIndices);
else
- _proxyArchive->GetRealIndices(_proxyFolderItem, indices, numItems, realIndices);
+ _proxy->GetRealIndices(_proxyDirIndex, indices, numItems, realIndices);
return;
}
+
realIndices.Clear();
+
for (UInt32 i = 0; i < numItems; i++)
{
const CProxyItem &item = _items[indices[i]];
- if (_proxyArchive2)
+ if (_proxy2)
{
- const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex];
- _proxyArchive2->AddRealIndices_of_ArcItem(folder->SubFiles[item.Index], includeAltStreams, realIndices);
+ const CProxyDir2 *dir = &_proxy2->Dirs[item.DirIndex];
+ _proxy2->AddRealIndices_of_ArcItem(dir->Items[item.Index], includeAltStreams, realIndices);
continue;
}
UInt32 arcIndex;
{
- const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex];
+ const CProxyDir *dir = &_proxy->Dirs[item.DirIndex];
unsigned realIndex = item.Index;
- if (realIndex < folder->Folders.Size())
+ if (realIndex < dir->SubDirs.Size())
{
if (includeFolderSubItemsInFlatMode)
{
- _proxyArchive->AddRealIndices(folder->Folders[realIndex], realIndices);
+ _proxy->AddRealIndices(dir->SubDirs[realIndex], realIndices);
continue;
}
- const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]];
- if (!f.IsLeaf)
+ const CProxyDir &f = _proxy->Dirs[dir->SubDirs[realIndex]];
+ if (!f.IsLeaf())
continue;
- arcIndex = f.Index;
+ arcIndex = f.ArcIndex;
}
else
- arcIndex = folder->Files[realIndex - folder->Folders.Size()].Index;
+ arcIndex = dir->SubFiles[realIndex - dir->SubDirs.Size()];
}
realIndices.Add(arcIndex);
}
+
HeapSort(&realIndices.Front(), realIndices.Size());
}
@@ -1163,10 +1452,11 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UStringVector pathParts;
- if (_proxyArchive2)
- _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts);
+ bool isAltStreamFolder = false;
+ if (_proxy2)
+ _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder);
else
- _proxyArchive->GetPathParts(_proxyFolderItem, pathParts);
+ _proxy->GetDirPathParts(_proxyDirIndex, pathParts);
/*
if (_flatMode)
@@ -1177,7 +1467,14 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
FString pathU;
if (path)
+ {
pathU = us2fs(path);
+ if (!pathU.IsEmpty())
+ {
+ NFile::NName::NormalizeDirPathPrefix(pathU);
+ NFile::NDir::CreateComplexDir(pathU);
+ }
+ }
CExtractNtOptions extractNtOptions;
extractNtOptions.AltStreams.Val = IntToBool(includeAltStreams); // change it!!!
@@ -1191,12 +1488,12 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
extractCallback2,
false, // stdOutMode
IntToBool(testMode),
- path ? pathU : FTEXT(""),
- pathParts,
+ pathU,
+ pathParts, isAltStreamFolder,
(UInt64)(Int64)-1);
- if (_proxyArchive2)
- extractCallbackSpec->SetBaseParentFolderIndex(_proxyArchive2->Folders[_proxyFolderItem].ArcIndex);
+ if (_proxy2)
+ extractCallbackSpec->SetBaseParentFolderIndex(_proxy2->Dirs[_proxyDirIndex].ArcIndex);
CUIntVector realIndices;
GetRealIndices(indices, numItems, IntToBool(includeAltStreams),
@@ -1224,19 +1521,19 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
// CAgent
CAgent::CAgent():
- _proxyArchive(NULL),
- _proxyArchive2(NULL),
- _isDeviceFile(false),
- _codecs(0)
+ _proxy(NULL),
+ _proxy2(NULL),
+ _isDeviceFile(false),
+ _updatePathPrefix_is_AltFolder(false)
{
}
CAgent::~CAgent()
{
- if (_proxyArchive)
- delete _proxyArchive;
- if (_proxyArchive2)
- delete _proxyArchive2;
+ if (_proxy)
+ delete _proxy;
+ if (_proxy2)
+ delete _proxy2;
}
bool CAgent::CanUpdate() const
@@ -1274,13 +1571,10 @@ STDMETHODIMP CAgent::Open(
}
CArcInfoEx archiverInfo0, archiverInfo1;
- _compressCodecsInfo.Release();
- _codecs = new CCodecs;
- _compressCodecsInfo = _codecs;
- RINOK(_codecs->Load());
+ RINOK(LoadGlobalCodecs());
CObjectVector<COpenType> types;
- if (!ParseOpenTypes(*_codecs, arcFormat, types))
+ if (!ParseOpenTypes(*g_CodecsObj, arcFormat, types))
return S_FALSE;
/*
@@ -1296,7 +1590,7 @@ STDMETHODIMP CAgent::Open(
COpenOptions options;
options.props = NULL;
- options.codecs = _codecs;
+ options.codecs = g_CodecsObj;
options.types = &types;
CIntVector exl;
options.excludedFormats = &exl;
@@ -1326,15 +1620,15 @@ STDMETHODIMP CAgent::Open(
STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback)
{
COM_TRY_BEGIN
- if (_proxyArchive2)
+ if (_proxy2)
{
- delete _proxyArchive2;
- _proxyArchive2 = NULL;
+ delete _proxy2;
+ _proxy2 = NULL;
}
- if (_proxyArchive)
+ if (_proxy)
{
- delete _proxyArchive;
- _proxyArchive = NULL;
+ delete _proxy;
+ _proxy = NULL;
}
CObjectVector<COpenType> incl;
@@ -1342,7 +1636,7 @@ STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback)
COpenOptions options;
options.props = NULL;
- options.codecs = _codecs;
+ options.codecs = g_CodecsObj;
options.types = &incl;
options.excludedFormats = &exl;
options.stdInMode = false;
@@ -1370,20 +1664,22 @@ STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)
HRESULT CAgent::ReadItems()
{
- if (_proxyArchive || _proxyArchive2)
+ if (_proxy || _proxy2)
return S_OK;
const CArc &arc = GetArc();
bool useProxy2 = (arc.GetRawProps && arc.IsTree);
+
// useProxy2 = false;
if (useProxy2)
- _proxyArchive2 = new CProxyArchive2();
+ _proxy2 = new CProxyArc2();
else
- _proxyArchive = new CProxyArchive();
+ _proxy = new CProxyArc();
{
ThereIsPathProp = false;
+ // ThereIsAltStreamProp = false;
UInt32 numProps;
arc.Archive->GetNumberOfProperties(&numProps);
for (UInt32 i = 0; i < numProps; i++)
@@ -1393,16 +1689,17 @@ HRESULT CAgent::ReadItems()
VARTYPE varType;
RINOK(arc.Archive->GetPropertyInfo(i, &name, &propID, &varType));
if (propID == kpidPath)
- {
ThereIsPathProp = true;
- break;
- }
+ /*
+ if (propID == kpidIsAltStream)
+ ThereIsAltStreamProp = true;
+ */
}
}
- if (_proxyArchive2)
- return _proxyArchive2->Load(GetArc(), NULL);
- return _proxyArchive->Load(GetArc(), NULL);
+ if (_proxy2)
+ return _proxy2->Load(GetArc(), NULL);
+ return _proxy->Load(GetArc(), NULL);
}
STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)
@@ -1411,7 +1708,7 @@ STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)
RINOK(ReadItems());
CAgentFolder *folderSpec = new CAgentFolder;
CMyComPtr<IFolderFolder> rootFolder = folderSpec;
- folderSpec->Init(_proxyArchive, _proxyArchive2, 0, NULL, this);
+ folderSpec->Init(_proxy, _proxy2, k_Proxy_RootDirIndex, /* NULL, */ this);
*resultFolder = rootFolder.Detach();
return S_OK;
COM_TRY_END
@@ -1441,7 +1738,7 @@ STDMETHODIMP CAgent::Extract(
false, // stdOutMode
IntToBool(testMode),
us2fs(path),
- UStringVector(),
+ UStringVector(), false,
(UInt64)(Int64)-1);
#ifdef SUPPORT_LINKS
@@ -1497,7 +1794,7 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value)
break;
case kpidErrorType:
if (_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
- prop = _codecs->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name;
+ prop = g_CodecsObj->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name;
break;
}
}
@@ -1508,7 +1805,7 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value)
{
case kpidType: prop = GetTypeOfArc(arc); break;
case kpidPath: prop = arc.Path; break;
- case kpidErrorType: if (arc.ErrorInfo.ErrorFormatIndex >= 0) prop = _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; break;
+ case kpidErrorType: if (arc.ErrorInfo.ErrorFormatIndex >= 0) prop = g_CodecsObj->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; break;
case kpidErrorFlags:
{
UInt32 flags = arc.ErrorInfo.GetErrorFlags();
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h
index e06f8576..2c505b84 100644
--- a/CPP/7zip/UI/Agent/Agent.h
+++ b/CPP/7zip/UI/Agent/Agent.h
@@ -18,6 +18,10 @@
#include "AgentProxy.h"
#include "IFolderArchive.h"
+extern CCodecs *g_CodecsObj;
+HRESULT LoadGlobalCodecs();
+void FreeGlobalCodecs();
+
class CAgentFolder;
DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC)
@@ -27,7 +31,7 @@ DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC)
struct CProxyItem
{
- unsigned ProxyFolderIndex;
+ unsigned DirIndex;
unsigned Index;
};
@@ -44,6 +48,7 @@ enum AGENT_OP
class CAgentFolder:
public IFolderFolder,
+ public IFolderAltStreams,
public IFolderProperties,
public IArchiveGetRawProps,
public IGetFolderArcProps,
@@ -59,10 +64,11 @@ class CAgentFolder:
#endif
public CMyUnknownImp
{
- void LoadFolder(unsigned proxyFolderIndex);
+ void LoadFolder(unsigned proxyDirIndex);
public:
MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
+ MY_QUERYINTERFACE_ENTRY(IFolderAltStreams)
MY_QUERYINTERFACE_ENTRY(IFolderProperties)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps)
@@ -79,7 +85,8 @@ public:
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
- HRESULT BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder);
+ HRESULT BindToFolder_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder);
+ HRESULT BindToAltStreams_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder);
int GetRealIndex(unsigned index) const;
void GetRealIndices(const UInt32 *indices, UInt32 numItems,
bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const;
@@ -87,6 +94,7 @@ public:
// INTERFACE_FolderSetReplaceAltStreamCharsMode(;)
INTERFACE_FolderFolder(;)
+ INTERFACE_FolderAltStreams(;)
INTERFACE_FolderProperties(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IFolderGetItemName(;)
@@ -108,48 +116,57 @@ public:
STDMETHOD(SetFlatMode)(Int32 flatMode);
#endif
- CAgentFolder(): _proxyFolderItem(0), _flatMode(0) /* , _replaceAltStreamCharsMode(0) */ {}
-
- void Init(const CProxyArchive *proxyArc, const CProxyArchive2 *proxyArc2,
- unsigned proxyFolderItem,
- IFolderFolder *parentFolder,
+ CAgentFolder():
+ _proxyDirIndex(0),
+ _isAltStreamFolder(false),
+ _flatMode(false),
+ _loadAltStreams(false) // _loadAltStreams alt streams works in flat mode, but we don't use it now
+ /* , _replaceAltStreamCharsMode(0) */
+ {}
+
+ void Init(const CProxyArc *proxy, const CProxyArc2 *proxy2,
+ unsigned proxyDirIndex,
+ /* IFolderFolder *parentFolder, */
CAgent *agent)
{
- _proxyArchive = proxyArc;
- _proxyArchive2 = proxyArc2;
- _proxyFolderItem = proxyFolderItem;
- _parentFolder = parentFolder;
+ _proxy = proxy;
+ _proxy2 = proxy2;
+ _proxyDirIndex = proxyDirIndex;
+ _isAltStreamFolder = false;
+ if (_proxy2)
+ _isAltStreamFolder = _proxy2->IsAltDir(proxyDirIndex);
+ // _parentFolder = parentFolder;
_agent = (IInFolderArchive *)agent;
_agentSpec = agent;
}
- void GetPathParts(UStringVector &pathParts);
+ void GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder);
HRESULT CommonUpdateOperation(
AGENT_OP operation,
bool moveMode,
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
const UInt32 *indices, UInt32 numItems,
- IFolderArchiveUpdateCallback *updateCallback100);
+ IProgress *progress);
void GetPrefix(UInt32 index, UString &prefix) const;
UString GetName(UInt32 index) const;
- UString GetFullPathPrefixPlusPrefix(UInt32 index) const;
+ UString GetFullPrefix(UInt32 index) const; // relative too root folder of archive
public:
- const CProxyArchive *_proxyArchive;
- const CProxyArchive2 *_proxyArchive2;
- // const CProxyFolder *_proxyFolderItem;
- unsigned _proxyFolderItem;
- CMyComPtr<IFolderFolder> _parentFolder;
+ const CProxyArc *_proxy;
+ const CProxyArc2 *_proxy2;
+ unsigned _proxyDirIndex;
+ bool _isAltStreamFolder;
+ // CMyComPtr<IFolderFolder> _parentFolder;
CMyComPtr<IInFolderArchive> _agent;
CAgent *_agentSpec;
CRecordVector<CProxyItem> _items;
bool _flatMode;
+ bool _loadAltStreams; // in Flat mode
// Int32 _replaceAltStreamCharsMode;
-private:
};
class CAgent:
@@ -193,29 +210,28 @@ public:
IFolderArchiveUpdateCallback *updateCallback100);
// ISetProperties
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
- CCodecs *_codecs;
- CMyComPtr<ICompressCodecsInfo> _compressCodecsInfo;
-
CAgent();
~CAgent();
private:
HRESULT ReadItems();
public:
- CProxyArchive *_proxyArchive;
- CProxyArchive2 *_proxyArchive2;
+ CProxyArc *_proxy;
+ CProxyArc2 *_proxy2;
CArchiveLink _archiveLink;
bool ThereIsPathProp;
+ // bool ThereIsAltStreamProp;
UString ArchiveType;
FStringVector _names;
FString _folderPrefix;
- UString _archiveNamePrefix;
+ bool _updatePathPrefix_is_AltFolder;
+ UString _updatePathPrefix;
CAgentFolder *_agentFolder;
UString _archiveFilePath;
@@ -230,11 +246,22 @@ public:
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
bool CanUpdate() const;
+ bool IsThereReadOnlyArc() const
+ {
+ FOR_VECTOR (i, _archiveLink.Arcs)
+ {
+ const CArc &arc = _archiveLink.Arcs[i];
+ if (!g_CodecsObj->Formats[arc.FormatIndex].UpdateEnabled || arc.IsReadOnly)
+ return true;
+ }
+ return false;
+ }
+
UString GetTypeOfArc(const CArc &arc) const
{
if (arc.FormatIndex < 0)
return L"Parser";
- return _codecs->GetFormatNamePtr(arc.FormatIndex);
+ return g_CodecsObj->GetFormatNamePtr(arc.FormatIndex);
}
UString GetErrorMessage() const
@@ -246,25 +273,29 @@ public:
UString s2;
if (arc.ErrorInfo.ErrorFormatIndex >= 0)
- s2 = L"Can not open the file as [" + _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name + L"] archive";
+ {
+ s2.AddAscii("Can not open the file as [");
+ s2 += g_CodecsObj->Formats[arc.ErrorInfo.ErrorFormatIndex].Name;
+ s2.AddAscii("] archive");
+ }
if (!arc.ErrorInfo.ErrorMessage.IsEmpty())
{
if (!s2.IsEmpty())
- s2 += L"\n";
- s2 += L"\n[";
+ s2.Add_LF();
+ s2.AddAscii("\n[");
s2 += GetTypeOfArc(arc);
- s2 += L"]: ";
+ s2.AddAscii("]: ");
s2 += arc.ErrorInfo.ErrorMessage;
}
if (!s2.IsEmpty())
{
if (!s.IsEmpty())
- s += L"--------------------\n";
+ s.AddAscii("--------------------\n");
s += arc.Path;
- s += L"\n";
+ s.Add_LF();
s += s2;
- s += L"\n";
+ s.Add_LF();
}
}
return s;
@@ -274,23 +305,20 @@ public:
};
+
#ifdef NEW_FOLDER_INTERFACE
+
class CArchiveFolderManager:
public IFolderManager,
public CMyUnknownImp
{
+ void LoadFormats();
+ int FindFormat(const UString &type);
public:
MY_UNKNOWN_IMP1(IFolderManager)
-
INTERFACE_IFolderManager(;)
-
- CArchiveFolderManager(): _codecs(0) {}
-private:
- void LoadFormats();
- int FindFormat(const UString &type);
- CCodecs *_codecs;
- CMyComPtr<ICompressCodecsInfo> _compressCodecsInfo;
};
+
#endif
#endif
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
index 3fd25670..3fed8cba 100644
--- a/CPP/7zip/UI/Agent/AgentOut.cpp
+++ b/CPP/7zip/UI/Agent/AgentOut.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/Wildcard.h"
+
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/TimeUtils.h"
@@ -18,29 +20,33 @@ using namespace NCOM;
STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder)
{
- _archiveNamePrefix.Empty();
- if (folder == NULL)
- {
- _agentFolder = NULL;
+ _updatePathPrefix.Empty();
+ _updatePathPrefix_is_AltFolder = false;
+ _agentFolder = NULL;
+
+ if (!folder)
return S_OK;
- }
{
- CMyComPtr<IFolderFolder> archiveFolder = folder;
- CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;
- RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
- RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder));
+ CMyComPtr<IArchiveFolderInternal> afi;
+ RINOK(folder->QueryInterface(IID_IArchiveFolderInternal, (void **)&afi));
+ if (afi)
+ {
+ RINOK(afi->GetAgentFolder(&_agentFolder));
+ }
+ if (!_agentFolder)
+ return E_FAIL;
}
- if (_proxyArchive2)
- _archiveNamePrefix = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem);
+ if (_proxy2)
+ _updatePathPrefix = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, _updatePathPrefix_is_AltFolder);
else
- _archiveNamePrefix = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem);
+ _updatePathPrefix = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
return S_OK;
}
STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
- const wchar_t **names, UInt32 numNames)
+ const wchar_t * const *names, UInt32 numNames)
{
_folderPrefix = us2fs(folderPrefix);
_names.ClearAndReserve(numNames);
@@ -50,54 +56,57 @@ STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
}
static HRESULT EnumerateArchiveItems(CAgent *agent,
- const CProxyFolder &item,
+ const CProxyDir &item,
const UString &prefix,
CObjectVector<CArcItem> &arcItems)
{
unsigned i;
- for (i = 0; i < item.Files.Size(); i++)
+
+ for (i = 0; i < item.SubFiles.Size(); i++)
{
- const CProxyFile &fileItem = item.Files[i];
+ unsigned arcIndex = item.SubFiles[i];
+ const CProxyFile &fileItem = agent->_proxy->Files[arcIndex];
CArcItem ai;
- RINOK(agent->GetArc().GetItemMTime(fileItem.Index, ai.MTime, ai.MTimeDefined));
- RINOK(agent->GetArc().GetItemSize(fileItem.Index, ai.Size, ai.SizeDefined));
+ RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined));
+ RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined));
ai.IsDir = false;
ai.Name = prefix + fileItem.Name;
ai.Censored = true; // test it
- ai.IndexInServer = fileItem.Index;
+ ai.IndexInServer = arcIndex;
arcItems.Add(ai);
}
- for (i = 0; i < item.Folders.Size(); i++)
+
+ for (i = 0; i < item.SubDirs.Size(); i++)
{
- const CProxyFolder &dirItem = agent->_proxyArchive->Folders[item.Folders[i]];
+ const CProxyDir &dirItem = agent->_proxy->Dirs[item.SubDirs[i]];
UString fullName = prefix + dirItem.Name;
- if (dirItem.IsLeaf)
+ if (dirItem.IsLeaf())
{
CArcItem ai;
- RINOK(agent->GetArc().GetItemMTime(dirItem.Index, ai.MTime, ai.MTimeDefined));
+ RINOK(agent->GetArc().GetItemMTime(dirItem.ArcIndex, ai.MTime, ai.MTimeDefined));
ai.IsDir = true;
ai.SizeDefined = false;
ai.Name = fullName;
ai.Censored = true; // test it
- ai.IndexInServer = dirItem.Index;
+ ai.IndexInServer = dirItem.ArcIndex;
arcItems.Add(ai);
}
- RINOK(EnumerateArchiveItems(agent, dirItem, fullName + UString(WCHAR_PATH_SEPARATOR), arcItems));
+ RINOK(EnumerateArchiveItems(agent, dirItem, fullName + WCHAR_PATH_SEPARATOR, arcItems));
}
+
return S_OK;
}
static HRESULT EnumerateArchiveItems2(const CAgent *agent,
- const CProxyArchive2 *proxyArchive2,
- unsigned folderIndex,
+ unsigned dirIndex,
const UString &prefix,
CObjectVector<CArcItem> &arcItems)
{
- const CProxyFolder2 &folder = proxyArchive2->Folders[folderIndex];
- FOR_VECTOR (i, folder.SubFiles)
+ const CProxyDir2 &dir = agent->_proxy2->Dirs[dirIndex];
+ FOR_VECTOR (i, dir.Items)
{
- unsigned arcIndex = folder.SubFiles[i];
- const CProxyFile2 &file = proxyArchive2->Files[arcIndex];
+ unsigned arcIndex = dir.Items[i];
+ const CProxyFile2 &file = agent->_proxy2->Files[arcIndex];
CArcItem ai;
ai.IndexInServer = arcIndex;
ai.Name = prefix + file.Name;
@@ -105,15 +114,22 @@ static HRESULT EnumerateArchiveItems2(const CAgent *agent,
RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined));
ai.IsDir = file.IsDir();
ai.SizeDefined = false;
+ ai.IsAltStream = file.IsAltStream;
if (!ai.IsDir)
{
RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined));
ai.IsDir = false;
}
arcItems.Add(ai);
+
+ if (file.AltDirIndex >= 0)
+ {
+ RINOK(EnumerateArchiveItems2(agent, file.AltDirIndex, ai.Name + L':', arcItems));
+ }
+
if (ai.IsDir)
{
- RINOK(EnumerateArchiveItems2(agent, proxyArchive2, file.FolderIndex, ai.Name + UString(WCHAR_PATH_SEPARATOR), arcItems));
+ RINOK(EnumerateArchiveItems2(agent, file.DirIndex, ai.Name + WCHAR_PATH_SEPARATOR, arcItems));
}
}
return S_OK;
@@ -126,10 +142,10 @@ struct CAgUpCallbackImp: public IUpdateProduceCallback
CAgUpCallbackImp(const CObjectVector<CArcItem> *a,
IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {}
- HRESULT ShowDeleteFile(int arcIndex);
+ HRESULT ShowDeleteFile(unsigned arcIndex);
};
-HRESULT CAgUpCallbackImp::ShowDeleteFile(int arcIndex)
+HRESULT CAgUpCallbackImp::ShowDeleteFile(unsigned arcIndex)
{
return _callback->DeleteOperation((*_arcItems)[arcIndex].Name);
}
@@ -140,11 +156,40 @@ static void SetInArchiveInterfaces(CAgent *agent, CArchiveUpdateCallback *upd)
if (agent->_archiveLink.Arcs.IsEmpty())
return;
const CArc &arc = agent->GetArc();
+ upd->Arc = &arc;
upd->Archive = arc.Archive;
- upd->GetRawProps = arc.GetRawProps;
- upd->GetRootProps = arc.GetRootProps;
}
+struct CDirItemsCallback_AgentOut: public IDirItemsCallback
+{
+ CMyComPtr<IFolderScanProgress> FolderScanProgress;
+ IFolderArchiveUpdateCallback *FolderArchiveUpdateCallback;
+ HRESULT ErrorCode;
+
+ CDirItemsCallback_AgentOut(): ErrorCode(S_OK), FolderArchiveUpdateCallback(NULL) {}
+
+ HRESULT ScanError(const FString &name, DWORD systemError)
+ {
+ HRESULT hres = HRESULT_FROM_WIN32(systemError);
+ if (FolderArchiveUpdateCallback)
+ return FolderScanProgress->ScanError(fs2us(name), hres);
+ ErrorCode = hres;
+ return ErrorCode;
+ }
+
+ HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir)
+ {
+ if (FolderScanProgress)
+ return FolderScanProgress->ScanProgress(st.NumDirs, st.NumFiles + st.NumAltStreams,
+ st.GetTotalBytes(), fs2us(path), BoolToInt(isDir));
+
+ if (FolderArchiveUpdateCallback)
+ return FolderArchiveUpdateCallback->SetNumFiles(st.NumFiles);
+
+ return S_OK;
+ }
+};
+
STDMETHODIMP CAgent::DoOperation(
FStringVector *requestedPaths,
FStringVector *processedPaths,
@@ -157,22 +202,43 @@ STDMETHODIMP CAgent::DoOperation(
{
if (!CanUpdate())
return E_NOTIMPL;
+
NUpdateArchive::CActionSet actionSet;
- unsigned i;
- for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
- actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
+ {
+ for (unsigned i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
+ actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
+ }
+ CDirItemsCallback_AgentOut enumCallback;
+ if (updateCallback100)
+ {
+ enumCallback.FolderArchiveUpdateCallback = updateCallback100;
+ updateCallback100->QueryInterface(IID_IFolderScanProgress, (void **)&enumCallback.FolderScanProgress);
+ }
+
CDirItems dirItems;
+ dirItems.Callback = &enumCallback;
{
FString folderPrefix = _folderPrefix;
NFile::NName::NormalizeDirPathPrefix(folderPrefix);
- dirItems.EnumerateItems2(folderPrefix, _archiveNamePrefix, _names, requestedPaths);
- if (dirItems.ErrorCodes.Size() > 0)
- return dirItems.ErrorCodes.Front();
+
+ RINOK(dirItems.EnumerateItems2(folderPrefix, _updatePathPrefix, _names, requestedPaths));
+
+ if (_updatePathPrefix_is_AltFolder)
+ {
+ FOR_VECTOR(i, dirItems.Items)
+ {
+ CDirItem &item = dirItems.Items[i];
+ if (item.IsDir())
+ return E_NOTIMPL;
+ item.IsAltStream = true;
+ }
+ }
}
CMyComPtr<IOutArchive> outArchive;
+
if (GetArchive())
{
RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));
@@ -182,6 +248,7 @@ STDMETHODIMP CAgent::DoOperation(
if (formatIndex < 0)
return E_FAIL;
RINOK(codecs->CreateOutArchive(formatIndex, outArchive));
+
#ifdef EXTERNAL_CODECS
{
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
@@ -192,7 +259,6 @@ STDMETHODIMP CAgent::DoOperation(
}
}
#endif
-
}
NFileTimeType::EEnum fileTimeType;
@@ -215,13 +281,14 @@ STDMETHODIMP CAgent::DoOperation(
if (GetArchive())
{
RINOK(ReadItems());
- if (_proxyArchive2)
+ if (_proxy2)
{
- RINOK(EnumerateArchiveItems2(this, _proxyArchive2, 0, L"", arcItems));
+ RINOK(EnumerateArchiveItems2(this, k_Proxy2_RootDirIndex, L"", arcItems));
+ RINOK(EnumerateArchiveItems2(this, k_Proxy2_AltRootDirIndex, L":", arcItems));
}
else
{
- RINOK(EnumerateArchiveItems(this, _proxyArchive->Folders[0], L"", arcItems));
+ RINOK(EnumerateArchiveItems(this, _proxy->Dirs[0], L"", arcItems));
}
}
@@ -235,9 +302,11 @@ STDMETHODIMP CAgent::DoOperation(
}
UInt32 numFiles = 0;
- for (i = 0; i < updatePairs2.Size(); i++)
- if (updatePairs2[i].NewData)
- numFiles++;
+ {
+ FOR_VECTOR (i, updatePairs2)
+ if (updatePairs2[i].NewData)
+ numFiles++;
+ }
if (updateCallback100)
{
@@ -262,7 +331,7 @@ STDMETHODIMP CAgent::DoOperation(
{
unsigned num = dirItems.Items.Size();
processedItems.Alloc(num);
- for (i = 0; i < num; i++)
+ for (unsigned i = 0; i < num; i++)
processedItems[i] = 0;
updateCallbackSpec->ProcessedItemsStatuses = processedItems;
}
@@ -277,7 +346,7 @@ STDMETHODIMP CAgent::DoOperation(
else
{
CRecordVector<const wchar_t *> names;
- for(i = 0; i < m_PropNames.Size(); i++)
+ FOR_VECTOR (i, m_PropNames)
names.Add((const wchar_t *)m_PropNames[i]);
CPropVariant *propValues = new CPropVariant[m_PropValues.Size()];
@@ -311,9 +380,9 @@ STDMETHODIMP CAgent::DoOperation(
HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
if (res == S_OK && processedPaths)
{
- for (i = 0; i < dirItems.Items.Size(); i++)
+ FOR_VECTOR (i, dirItems.Items)
if (processedItems[i] != 0)
- processedPaths->Add(us2fs(dirItems.GetPhyPath(i)));
+ processedPaths->Add(dirItems.GetPhyPath(i));
}
return res;
}
@@ -324,7 +393,7 @@ STDMETHODIMP CAgent::DoOperation2(
ISequentialOutStream *outArchiveStream,
const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100)
{
- return DoOperation(requestedPaths, processedPaths, _codecs, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
+ return DoOperation(requestedPaths, processedPaths, g_CodecsObj, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
}
HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream,
@@ -357,11 +426,17 @@ STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
unsigned curIndex = 0;
UInt32 numItemsInArchive;
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
+
+ UString deletePath;
+
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
if (curIndex < realIndices.Size())
if (realIndices[curIndex] == i)
{
+ RINOK(GetArc().GetItemPath2(i, deletePath));
+ RINOK(updateCallback100->DeleteOperation(deletePath));
+
curIndex++;
continue;
}
@@ -410,10 +485,12 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
di.Attrib = FILE_ATTRIBUTE_DIRECTORY;
di.Size = 0;
- if (_proxyArchive2)
- di.Name = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName;
+ bool isAltStreamFolder = false;
+ if (_proxy2)
+ di.Name = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, isAltStreamFolder);
else
- di.Name = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName;
+ di.Name = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
+ di.Name += folderName;
FILETIME ft;
NTime::GetCurUtcFileTime(ft);
@@ -455,7 +532,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
int mainRealIndex = _agentFolder->GetRealIndex(indices[0]);
- UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]);
+ UString fullPrefix = _agentFolder->GetFullPrefix(indices[0]);
UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]);
UString newItemPath = fullPrefix + newItemName;
@@ -464,6 +541,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
unsigned curIndex = 0;
UInt32 numItemsInArchive;
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
+
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 up2;
@@ -477,7 +555,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
UString oldFullPath;
RINOK(GetArc().GetItemPath2(i, oldFullPath));
- if (MyStringCompareNoCase_N(oldFullPath, oldItemPath, oldItemPath.Len()) != 0)
+ if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath))
return E_INVALIDARG;
up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len()));
@@ -486,6 +564,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
}
updatePairs.Add(up2);
}
+
updateCallbackSpec->Callback = &updateCallbackAgent;
updateCallbackSpec->UpdatePairs = &updatePairs;
updateCallbackSpec->NewNames = &newNames;
@@ -553,7 +632,7 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
-STDMETHODIMP CAgent::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CAgent::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
m_PropNames.Clear();
m_PropValues.Clear();
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp
index 301d3a33..543cfbaa 100644
--- a/CPP/7zip/UI/Agent/AgentProxy.cpp
+++ b/CPP/7zip/UI/Agent/AgentProxy.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#include "../../../../C/Sort.h"
#include "../../../../C/CpuArch.h"
@@ -14,10 +16,10 @@
using namespace NWindows;
-int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const
+int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const
{
- const CRecordVector<unsigned> &subFolders = Folders[folderIndex].Folders;
- unsigned left = 0, right = subFolders.Size();
+ const CRecordVector<unsigned> &subDirs = Dirs[dirIndex].SubDirs;
+ unsigned left = 0, right = subDirs.Size();
for (;;)
{
if (left == right)
@@ -26,10 +28,10 @@ int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name
return -1;
}
unsigned mid = (left + right) / 2;
- unsigned folderIndex = subFolders[mid];
- int compare = CompareFileNames(name, Folders[folderIndex].Name);
+ unsigned dirIndex = subDirs[mid];
+ int compare = CompareFileNames(name, Dirs[dirIndex].Name);
if (compare == 0)
- return folderIndex;
+ return dirIndex;
if (compare < 0)
right = mid;
else
@@ -37,120 +39,117 @@ int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name
}
}
-int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name) const
+int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const
{
unsigned insertPos;
- return FindDirSubItemIndex(folderIndex, name, insertPos);
-}
-
-void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name)
-{
- CProxyFile &f = Files.AddNew();
- f.Index = index;
- f.Name = name;
+ return FindSubDir(dirIndex, name, insertPos);
}
-unsigned CProxyArchive::AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name)
+unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name)
{
unsigned insertPos;
- int subFolderIndex = FindDirSubItemIndex(folderIndex, name, insertPos);
- if (subFolderIndex >= 0)
+ int subDirIndex = FindSubDir(dirIndex, name, insertPos);
+ if (subDirIndex >= 0)
{
- CProxyFolder &item = Folders[subFolderIndex];
- if (leaf)
+ if (arcIndex >= 0)
{
- item.Index = index;
- item.IsLeaf = true;
+ CProxyDir &item = Dirs[subDirIndex];
+ if (item.ArcIndex < 0)
+ item.ArcIndex = arcIndex;
}
- return subFolderIndex;
+ return subDirIndex;
}
- subFolderIndex = Folders.Size();
- Folders[folderIndex].Folders.Insert(insertPos, subFolderIndex);
- CProxyFolder &item = Folders.AddNew();
- item.Name = name;
- item.Index = index;
- item.Parent = folderIndex;
- item.IsLeaf = leaf;
- return subFolderIndex;
+ subDirIndex = Dirs.Size();
+ Dirs[dirIndex].SubDirs.Insert(insertPos, subDirIndex);
+ CProxyDir &item = Dirs.AddNew();
+
+ item.NameLen = name.Len();
+ item.Name = new wchar_t[item.NameLen + 1];
+ MyStringCopy((wchar_t *)item.Name, name);
+
+ item.ArcIndex = arcIndex;
+ item.ParentDir = dirIndex;
+ return subDirIndex;
}
-void CProxyFolder::Clear()
+void CProxyDir::Clear()
{
- Folders.Clear();
- Files.Clear();
+ SubDirs.Clear();
+ SubFiles.Clear();
}
-void CProxyArchive::GetPathParts(int folderIndex, UStringVector &pathParts) const
+void CProxyArc::GetDirPathParts(int dirIndex, UStringVector &pathParts) const
{
pathParts.Clear();
- while (folderIndex >= 0)
+ while (dirIndex >= 0)
{
- const CProxyFolder &folder = Folders[folderIndex];
- folderIndex = folder.Parent;
- if (folderIndex < 0)
+ const CProxyDir &dir = Dirs[dirIndex];
+ dirIndex = dir.ParentDir;
+ if (dirIndex < 0)
break;
- pathParts.Insert(0, folder.Name);
+ pathParts.Insert(0, dir.Name);
}
}
-UString CProxyArchive::GetFullPathPrefix(int folderIndex) const
+UString CProxyArc::GetDirPath_as_Prefix(int dirIndex) const
{
- UString result;
- while (folderIndex >= 0)
+ UString s;
+ while (dirIndex >= 0)
{
- const CProxyFolder &folder = Folders[folderIndex];
- folderIndex = folder.Parent;
- if (folderIndex < 0)
+ const CProxyDir &dir = Dirs[dirIndex];
+ dirIndex = dir.ParentDir;
+ if (dirIndex < 0)
break;
- result = folder.Name + UString(WCHAR_PATH_SEPARATOR) + result;
+ s.InsertAtFront(WCHAR_PATH_SEPARATOR);
+ s.Insert(0, dir.Name);
}
- return result;
+ return s;
}
-void CProxyArchive::AddRealIndices(unsigned folderIndex, CUIntVector &realIndices) const
+void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const
{
- const CProxyFolder &folder = Folders[folderIndex];
- if (folder.IsLeaf)
- realIndices.Add(folder.Index);
+ const CProxyDir &dir = Dirs[dirIndex];
+ if (dir.IsLeaf())
+ realIndices.Add(dir.ArcIndex);
unsigned i;
- for (i = 0; i < folder.Folders.Size(); i++)
- AddRealIndices(folder.Folders[i], realIndices);
- for (i = 0; i < folder.Files.Size(); i++)
- realIndices.Add(folder.Files[i].Index);
+ for (i = 0; i < dir.SubDirs.Size(); i++)
+ AddRealIndices(dir.SubDirs[i], realIndices);
+ for (i = 0; i < dir.SubFiles.Size(); i++)
+ realIndices.Add(dir.SubFiles[i]);
}
-int CProxyArchive::GetRealIndex(unsigned folderIndex, unsigned index) const
+int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const
{
- const CProxyFolder &folder = Folders[folderIndex];
- unsigned numDirItems = folder.Folders.Size();
+ const CProxyDir &dir = Dirs[dirIndex];
+ unsigned numDirItems = dir.SubDirs.Size();
if (index < numDirItems)
{
- const CProxyFolder &f = Folders[folder.Folders[index]];
- if (f.IsLeaf)
- return f.Index;
+ const CProxyDir &f = Dirs[dir.SubDirs[index]];
+ if (f.IsLeaf())
+ return f.ArcIndex;
return -1;
}
- return folder.Files[index - numDirItems].Index;
+ return dir.SubFiles[index - numDirItems];
}
-void CProxyArchive::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
+void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
{
- const CProxyFolder &folder = Folders[folderIndex];
+ const CProxyDir &dir = Dirs[dirIndex];
realIndices.Clear();
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
- unsigned numDirItems = folder.Folders.Size();
+ unsigned numDirItems = dir.SubDirs.Size();
if (index < numDirItems)
- AddRealIndices(folder.Folders[index], realIndices);
+ AddRealIndices(dir.SubDirs[index], realIndices);
else
- realIndices.Add(folder.Files[index - numDirItems].Index);
+ realIndices.Add(dir.SubFiles[index - numDirItems]);
}
HeapSort(&realIndices.Front(), realIndices.Size());
}
///////////////////////////////////////////////
-// CProxyArchive
+// CProxyArc
static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size)
{
@@ -161,79 +160,131 @@ static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &si
return ConvertPropVariantToUInt64(prop, size);
}
-void CProxyArchive::CalculateSizes(unsigned folderIndex, IInArchive *archive)
+void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive)
{
- CProxyFolder &folder = Folders[folderIndex];
- folder.Size = folder.PackSize = 0;
- folder.NumSubFolders = folder.Folders.Size();
- folder.NumSubFiles = folder.Files.Size();
- folder.CrcIsDefined = true;
- folder.Crc = 0;
+ CProxyDir &dir = Dirs[dirIndex];
+ dir.Size = dir.PackSize = 0;
+ dir.NumSubDirs = dir.SubDirs.Size();
+ dir.NumSubFiles = dir.SubFiles.Size();
+ dir.CrcIsDefined = true;
+ dir.Crc = 0;
+
unsigned i;
- for (i = 0; i < folder.Files.Size(); i++)
+
+ for (i = 0; i < dir.SubFiles.Size(); i++)
{
- UInt32 index = folder.Files[i].Index;
+ UInt32 index = (UInt32)dir.SubFiles[i];
UInt64 size, packSize;
bool sizeDefined = GetSize(archive, index, kpidSize, size);
- folder.Size += size;
+ dir.Size += size;
GetSize(archive, index, kpidPackSize, packSize);
- folder.PackSize += packSize;
+ dir.PackSize += packSize;
{
NCOM::CPropVariant prop;
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
{
if (prop.vt == VT_UI4)
- folder.Crc += prop.ulVal;
+ dir.Crc += prop.ulVal;
else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
- folder.CrcIsDefined = false;
+ dir.CrcIsDefined = false;
}
else
- folder.CrcIsDefined = false;
+ dir.CrcIsDefined = false;
}
}
- for (i = 0; i < folder.Folders.Size(); i++)
+
+ for (i = 0; i < dir.SubDirs.Size(); i++)
{
- unsigned subFolderIndex = folder.Folders[i];
- CProxyFolder &f = Folders[subFolderIndex];
- CalculateSizes(subFolderIndex, archive);
- folder.Size += f.Size;
- folder.PackSize += f.PackSize;
- folder.NumSubFiles += f.NumSubFiles;
- folder.NumSubFolders += f.NumSubFolders;
- folder.Crc += f.Crc;
+ unsigned subDirIndex = dir.SubDirs[i];
+ CalculateSizes(subDirIndex, archive);
+ CProxyDir &f = Dirs[subDirIndex];
+ dir.Size += f.Size;
+ dir.PackSize += f.PackSize;
+ dir.NumSubFiles += f.NumSubFiles;
+ dir.NumSubDirs += f.NumSubDirs;
+ dir.Crc += f.Crc;
if (!f.CrcIsDefined)
- folder.CrcIsDefined = false;
+ dir.CrcIsDefined = false;
}
}
-HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
+HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress)
{
- /*
- DWORD tickCount = GetTickCount();
- for (int ttt = 0; ttt < 1000; ttt++) {
- */
+ // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
- Folders.Clear();
- Folders.AddNew();
+ Files.Free();
+ Dirs.Clear();
+
+ Dirs.AddNew();
IInArchive *archive = arc.Archive;
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
+
if (progress)
RINOK(progress->SetTotal(numItems));
- UString filePath;
- UString fileName;
+
+ Files.Alloc(numItems);
+
+ UString path;
+ UString name;
+ NCOM::CPropVariant prop;
+
for (UInt32 i = 0; i < numItems; i++)
{
- if (progress && (i & 0xFFFFF) == 0)
+ if (progress && (i & 0xFFFF) == 0)
{
UInt64 currentItemIndex = i;
RINOK(progress->SetCompleted(&currentItemIndex));
}
- RINOK(arc.GetItemPath(i, filePath));
+
+ const wchar_t *s = NULL;
+ unsigned len = 0;
+ bool isPtrName = false;
+
+ #ifdef MY_CPU_LE
+ if (arc.GetRawProps)
+ {
+ const void *p;
+ UInt32 size;
+ UInt32 propType;
+ if (arc.GetRawProps->GetRawProp(i, kpidPath, &p, &size, &propType) == S_OK
+ && propType == NPropDataType::kUtf16z
+ && size > 2)
+ {
+ // is (size <= 2), it's empty name, and we call default arc.GetItemPath();
+ len = size / 2 - 1;
+ s = (const wchar_t *)p;
+ isPtrName = true;
+ }
+ }
+ if (!s)
+ #endif
+ {
+ prop.Clear();
+ RINOK(arc.Archive->GetProperty(i, kpidPath, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ s = prop.bstrVal;
+ len = ::SysStringLen(prop.bstrVal);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ if (len == 0)
+ {
+ RINOK(arc.GetDefaultItemPath(i, path));
+ len = path.Len();
+ s = path;
+ }
+
+ /*
+ RINOK(arc.GetItemPath(i, path));
+ len = path.Len();
+ s = path;
+ */
+ }
+
unsigned curItem = 0;
- unsigned len = filePath.Len();
- fileName.Empty();
/*
if (arc.Ask_Deleted)
@@ -245,16 +296,16 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
}
*/
+ unsigned namePos = 0;
for (unsigned j = 0; j < len; j++)
{
- wchar_t c = filePath[j];
+ wchar_t c = s[j];
if (c == WCHAR_PATH_SEPARATOR || c == L'/')
{
- curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, fileName);
- fileName.Empty();
+ name.SetFrom(s + namePos, j - namePos);
+ curItem = AddDir(curItem, -1, name);
+ namePos = j + 1;
}
- else
- fileName += c;
}
/*
@@ -270,21 +321,35 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
}
*/
- bool isFolder;
- RINOK(Archive_IsItem_Folder(archive, i, isFolder));
- if (isFolder)
- AddDirSubItem(curItem, i, true, fileName);
+ bool isDir;
+ RINOK(Archive_IsItem_Dir(archive, i, isDir));
+
+ CProxyFile &f = Files[i];
+
+ f.NameLen = len - namePos;
+ s += namePos;
+
+ if (isPtrName)
+ f.Name = s;
+ else
+ {
+ f.Name = new wchar_t[f.NameLen + 1];
+ f.NeedDeleteName = true;
+ MyStringCopy((wchar_t *)f.Name, s);
+ }
+
+ if (isDir)
+ {
+ name = s;
+ AddDir(curItem, (int)i, name);
+ }
else
- Folders[curItem].AddFileSubItem(i, fileName);
+ Dirs[curItem].SubFiles.Add(i);
}
+
CalculateSizes(0, archive);
- /*
- }
- char s[128];
- sprintf(s, "load archive %7d ms", GetTickCount() - tickCount);
- OutputDebugStringA(s);
- */
+ // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
return S_OK;
}
@@ -293,151 +358,162 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
// ---------- for Tree-mode archive ----------
-void CProxyArchive2::GetPathParts(int folderIndex, UStringVector &pathParts) const
+void CProxyArc2::GetDirPathParts(int dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const
{
pathParts.Clear();
- while (folderIndex > 0)
+
+ isAltStreamDir = false;
+
+ if (dirIndex == k_Proxy2_RootDirIndex)
+ return;
+ if (dirIndex == k_Proxy2_AltRootDirIndex)
+ {
+ isAltStreamDir = true;
+ return;
+ }
+
+ while (dirIndex >= k_Proxy2_NumRootDirs)
{
- const CProxyFolder2 &folder = Folders[folderIndex];
- const CProxyFile2 &file = Files[folder.ArcIndex];
+ const CProxyDir2 &dir = Dirs[dirIndex];
+ const CProxyFile2 &file = Files[dir.ArcIndex];
+ if (pathParts.IsEmpty() && dirIndex == file.AltDirIndex)
+ isAltStreamDir = true;
pathParts.Insert(0, file.Name);
int par = file.Parent;
if (par < 0)
break;
- folderIndex = Files[par].FolderIndex;
+ dirIndex = Files[par].DirIndex;
}
}
-UString CProxyArchive2::GetFullPathPrefix(unsigned folderIndex) const
+bool CProxyArc2::IsAltDir(unsigned dirIndex) const
+{
+ if (dirIndex == k_Proxy2_RootDirIndex)
+ return false;
+ if (dirIndex == k_Proxy2_AltRootDirIndex)
+ return true;
+ const CProxyDir2 &dir = Dirs[dirIndex];
+ const CProxyFile2 &file = Files[dir.ArcIndex];
+ return ((int)dirIndex == file.AltDirIndex);
+}
+
+UString CProxyArc2::GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const
{
- return Folders[folderIndex].PathPrefix;
- /*
- UString result;
- while (folderIndex > 0)
+ isAltStreamDir = false;
+ const CProxyDir2 &dir = Dirs[dirIndex];
+ if (dirIndex == k_Proxy2_AltRootDirIndex)
+ isAltStreamDir = true;
+ else if (dirIndex >= k_Proxy2_NumRootDirs)
{
- const CProxyFile2 &file = Files[Folders[folderIndex].ArcIndex];
- result = (UString)(file.Name) + (UString)WCHAR_PATH_SEPARATOR + result;
- if (file.Parent < 0)
- break;
- folderIndex = Files[file.Parent].FolderIndex;
+ const CProxyFile2 &file = Files[dir.ArcIndex];
+ isAltStreamDir = ((int)dirIndex == file.AltDirIndex);
}
- return result;
- */
+ return dir.PathPrefix;
}
-void CProxyArchive2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const
+void CProxyArc2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const
{
realIndices.Add(arcIndex);
const CProxyFile2 &file = Files[arcIndex];
- if (file.FolderIndex >= 0)
- AddRealIndices_of_Folder(file.FolderIndex, includeAltStreams, realIndices);
- if (includeAltStreams && file.AltStreamsFolderIndex >= 0)
- AddRealIndices_of_Folder(file.AltStreamsFolderIndex, includeAltStreams, realIndices);
+ if (file.DirIndex >= 0)
+ AddRealIndices_of_Dir(file.DirIndex, includeAltStreams, realIndices);
+ if (includeAltStreams && file.AltDirIndex >= 0)
+ AddRealIndices_of_Dir(file.AltDirIndex, includeAltStreams, realIndices);
}
-void CProxyArchive2::AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const
+void CProxyArc2::AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const
{
- const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles;
+ const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
FOR_VECTOR (i, subFiles)
{
AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices);
}
}
-unsigned CProxyArchive2::GetRealIndex(unsigned folderIndex, unsigned index) const
+unsigned CProxyArc2::GetRealIndex(unsigned dirIndex, unsigned index) const
{
- return Folders[folderIndex].SubFiles[index];
+ return Dirs[dirIndex].Items[index];
}
-void CProxyArchive2::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const
+void CProxyArc2::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const
{
- const CProxyFolder2 &folder = Folders[folderIndex];
+ const CProxyDir2 &dir = Dirs[dirIndex];
realIndices.Clear();
for (UInt32 i = 0; i < numItems; i++)
{
- AddRealIndices_of_ArcItem(folder.SubFiles[indices[i]], includeAltStreams, realIndices);
+ AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices);
}
HeapSort(&realIndices.Front(), realIndices.Size());
}
-void CProxyArchive2::CalculateSizes(unsigned folderIndex, IInArchive *archive)
+void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive)
{
- CProxyFolder2 &folder = Folders[folderIndex];
- folder.Size = folder.PackSize = 0;
- folder.NumSubFolders = 0; // folder.Folders.Size();
- folder.NumSubFiles = 0; // folder.Files.Size();
- folder.CrcIsDefined = true;
- folder.Crc = 0;
- FOR_VECTOR (i, folder.SubFiles)
+ CProxyDir2 &dir = Dirs[dirIndex];
+ dir.Size = dir.PackSize = 0;
+ dir.NumSubDirs = 0; // dir.SubDirs.Size();
+ dir.NumSubFiles = 0; // dir.Files.Size();
+ dir.CrcIsDefined = true;
+ dir.Crc = 0;
+
+ FOR_VECTOR (i, dir.Items)
{
- UInt32 index = folder.SubFiles[i];
+ UInt32 index = dir.Items[i];
UInt64 size, packSize;
bool sizeDefined = GetSize(archive, index, kpidSize, size);
- folder.Size += size;
+ dir.Size += size;
GetSize(archive, index, kpidPackSize, packSize);
- folder.PackSize += packSize;
+ dir.PackSize += packSize;
{
NCOM::CPropVariant prop;
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
{
if (prop.vt == VT_UI4)
- folder.Crc += prop.ulVal;
+ dir.Crc += prop.ulVal;
else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
- folder.CrcIsDefined = false;
+ dir.CrcIsDefined = false;
}
else
- folder.CrcIsDefined = false;
+ dir.CrcIsDefined = false;
}
const CProxyFile2 &subFile = Files[index];
- if (subFile.FolderIndex < 0)
+ if (subFile.DirIndex < 0)
{
- folder.NumSubFiles++;
+ dir.NumSubFiles++;
}
else
{
- folder.NumSubFolders++;
- CProxyFolder2 &f = Folders[subFile.FolderIndex];
- f.PathPrefix = folder.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR;
- CalculateSizes(subFile.FolderIndex, archive);
- folder.Size += f.Size;
- folder.PackSize += f.PackSize;
- folder.NumSubFiles += f.NumSubFiles;
- folder.NumSubFolders += f.NumSubFolders;
- folder.Crc += f.Crc;
+ dir.NumSubDirs++;
+ CProxyDir2 &f = Dirs[subFile.DirIndex];
+ f.PathPrefix = dir.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR;
+ CalculateSizes(subFile.DirIndex, archive);
+ dir.Size += f.Size;
+ dir.PackSize += f.PackSize;
+ dir.NumSubFiles += f.NumSubFiles;
+ dir.NumSubDirs += f.NumSubDirs;
+ dir.Crc += f.Crc;
if (!f.CrcIsDefined)
- folder.CrcIsDefined = false;
+ dir.CrcIsDefined = false;
}
- if (subFile.AltStreamsFolderIndex < 0)
+ if (subFile.AltDirIndex < 0)
{
- // folder.NumSubFiles++;
+ // dir.NumSubFiles++;
}
else
{
- // folder.NumSubFolders++;
- CProxyFolder2 &f = Folders[subFile.AltStreamsFolderIndex];
- f.PathPrefix = folder.PathPrefix + subFile.Name + L":";
- CalculateSizes(subFile.AltStreamsFolderIndex, archive);
- /*
- folder.Size += f.Size;
- folder.PackSize += f.PackSize;
- folder.NumSubFiles += f.NumSubFiles;
- folder.NumSubFolders += f.NumSubFolders;
- folder.Crc += f.Crc;
- if (!f.CrcIsDefined)
- folder.CrcIsDefined = false;
- */
+ // dir.NumSubDirs++;
+ CProxyDir2 &f = Dirs[subFile.AltDirIndex];
+ f.PathPrefix = dir.PathPrefix + subFile.Name + L':';
+ CalculateSizes(subFile.AltDirIndex, archive);
}
-
-
}
}
-bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) const
+bool CProxyArc2::IsThere_SubDir(unsigned dirIndex, const UString &name) const
{
- const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles;
+ const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
FOR_VECTOR (i, subFiles)
{
const CProxyFile2 &file = Files[subFiles[i]];
@@ -448,14 +524,15 @@ bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) c
return false;
}
-HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
+HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress)
{
if (!arc.GetRawProps)
return E_FAIL;
- // DWORD tickCount = GetTickCount();
+ // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
- Folders.Clear();
+ Dirs.Clear();
+ Files.Free();
IInArchive *archive = arc.Archive;
@@ -464,9 +541,17 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
if (progress)
RINOK(progress->SetTotal(numItems));
UString fileName;
+
+
+ {
+ // Dirs[0] - root dir
+ /* CProxyDir2 &dir = */ Dirs.AddNew();
+ }
+
{
- CProxyFolder2 &folder = Folders.AddNew();
- folder.ArcIndex = -1;
+ // Dirs[1] - for alt streams of root dir
+ CProxyDir2 &dir = Dirs.AddNew();
+ dir.PathPrefix = L':';
}
Files.Alloc(numItems);
@@ -491,9 +576,9 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
{
file.Name = (const wchar_t *)p;
- file.NameSize = 0;
+ file.NameLen = 0;
if (size >= sizeof(wchar_t))
- file.NameSize = size / sizeof(wchar_t) - 1;
+ file.NameLen = size / sizeof(wchar_t) - 1;
}
else
#endif
@@ -507,11 +592,12 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
s = L"[Content]";
else
return E_FAIL;
- file.NameSize = MyStringLen(s);
- file.Name = new wchar_t[file.NameSize + 1];
+ file.NameLen = MyStringLen(s);
+ file.Name = new wchar_t[file.NameLen + 1];
file.NeedDeleteName = true;
MyStringCopy((wchar_t *)file.Name, s);
}
+
UInt32 parent = (UInt32)(Int32)-1;
UInt32 parentType = 0;
RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType));
@@ -528,14 +614,14 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
}
}
- bool isFolder;
- RINOK(Archive_IsItem_Folder(archive, i, isFolder));
+ bool isDir;
+ RINOK(Archive_IsItem_Dir(archive, i, isDir));
- if (isFolder)
+ if (isDir)
{
- file.FolderIndex = Folders.Size();
- CProxyFolder2 &folder = Folders.AddNew();
- folder.ArcIndex = i;
+ file.DirIndex = Dirs.Size();
+ CProxyDir2 &dir = Dirs.AddNew();
+ dir.ArcIndex = i;
}
if (arc.Ask_AltStream)
RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream));
@@ -544,34 +630,57 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
for (i = 0; i < numItems; i++)
{
CProxyFile2 &file = Files[i];
+ int dirIndex;
+
if (file.IsAltStream)
{
- if (file.Parent >= 0)
+ if (file.Parent < 0)
+ dirIndex = k_Proxy2_AltRootDirIndex;
+ else
{
- int &folderIndex = Files[file.Parent].AltStreamsFolderIndex;
- if (folderIndex < 0)
+ int &folderIndex2 = Files[file.Parent].AltDirIndex;
+ if (folderIndex2 < 0)
{
- folderIndex = Folders.Size();
- CProxyFolder2 &folder = Folders.AddNew();
- folder.ArcIndex = file.Parent; // do we need it ???
+ folderIndex2 = Dirs.Size();
+ CProxyDir2 &dir = Dirs.AddNew();
+ dir.ArcIndex = file.Parent;
}
- Folders[folderIndex].SubFiles.Add(i);
+ dirIndex = folderIndex2;
}
}
else
{
- int folderIndex = GetParentFolderOfFile(i);
- if (folderIndex < 0)
- return E_FAIL;
- Folders[folderIndex].SubFiles.Add(i);
+ if (file.Parent < 0)
+ dirIndex = k_Proxy2_RootDirIndex;
+ else
+ {
+ dirIndex = Files[file.Parent].DirIndex;
+ if (dirIndex < 0)
+ return E_FAIL;
+ }
}
+
+ Dirs[dirIndex].Items.Add(i);
}
- CalculateSizes(0, archive);
+
+ for (i = 0; i < k_Proxy2_NumRootDirs; i++)
+ CalculateSizes(i, archive);
+
+ // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
- /*
- char s[128];
- sprintf(s, "load archive %7d ms", GetTickCount() - tickCount);
- OutputDebugStringA(s);
- */
return S_OK;
}
+
+int CProxyArc2::FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const
+{
+ const CProxyDir2 &dir = Dirs[dirIndex];
+ FOR_VECTOR (i, dir.Items)
+ {
+ const CProxyFile2 &file = Files[dir.Items[i]];
+ if (foldersOnly && file.DirIndex < 0)
+ continue;
+ if (CompareFileNames(file.Name, name) == 0)
+ return i;
+ }
+ return -1;
+}
diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h
index 1755d444..49012676 100644
--- a/CPP/7zip/UI/Agent/AgentProxy.h
+++ b/CPP/7zip/UI/Agent/AgentProxy.h
@@ -7,46 +7,61 @@
struct CProxyFile
{
- UInt32 Index;
- UString Name;
+ const wchar_t *Name;
+ unsigned NameLen;
+ bool NeedDeleteName;
+
+ CProxyFile(): Name(NULL), NameLen(0), NeedDeleteName(false) {}
+ ~CProxyFile() { if (NeedDeleteName) delete [](wchar_t *)Name; }
};
-class CProxyFolder: public CProxyFile
+const unsigned k_Proxy_RootDirIndex = 0;
+
+struct CProxyDir
{
-public:
- int Parent;
- CRecordVector<unsigned> Folders;
- CObjectVector<CProxyFile> Files;
+ const wchar_t *Name;
+ unsigned NameLen;
+
+ int ArcIndex; // index in proxy->Files[] ; -1 if there is no item for that folder
+ int ParentDir; // index in proxy->Dirs[] ; -1 for root folder; ;
+ CRecordVector<unsigned> SubDirs;
+ CRecordVector<unsigned> SubFiles;
+
UInt64 Size;
UInt64 PackSize;
UInt32 Crc;
- UInt32 NumSubFolders;
+ UInt32 NumSubDirs;
UInt32 NumSubFiles;
- bool IsLeaf;
bool CrcIsDefined;
- CProxyFolder(): Parent(-1) {};
- void AddFileSubItem(UInt32 index, const UString &name);
+ CProxyDir(): Name(NULL), NameLen(0), ParentDir(-1) {};
+ ~CProxyDir() { delete [](wchar_t *)Name; }
+
void Clear();
+ bool IsLeaf() const { return ArcIndex >= 0; }
};
-class CProxyArchive
+class CProxyArc
{
- int FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const;
+ int FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const;
- void CalculateSizes(unsigned folderIndex, IInArchive *archive);
- unsigned AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name);
+ void CalculateSizes(unsigned dirIndex, IInArchive *archive);
+ unsigned AddDir(unsigned dirIndex, int arcIndex, const UString &name);
public:
- CObjectVector<CProxyFolder> Folders; // Folders[0] - isRoot
+ CObjectVector<CProxyDir> Dirs; // Dirs[0] - root
+ CObjArray<CProxyFile> Files; // all items from archive in same order
+
+ // returns index in Dirs[], or -1,
+ int FindSubDir(unsigned dirIndex, const wchar_t *name) const;
- int FindDirSubItemIndex(unsigned folderIndex, const UString &name) const;
- void GetPathParts(int folderIndex, UStringVector &pathParts) const;
- UString GetFullPathPrefix(int folderIndex) const;
+ void GetDirPathParts(int dirIndex, UStringVector &pathParts) const;
+ // returns full path of Dirs[dirIndex], including back slash
+ UString GetDirPath_as_Prefix(int dirIndex) const;
- // AddRealIndices DOES ADD also item represented by folderIndex (if it's Leaf)
- void AddRealIndices(unsigned folderIndex, CUIntVector &realIndices) const;
- int GetRealIndex(unsigned folderIndex, unsigned index) const;
- void GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const;
+ // AddRealIndices DOES ADD also item represented by dirIndex (if it's Leaf)
+ void AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const;
+ int GetRealIndex(unsigned dirIndex, unsigned index) const;
+ void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const;
HRESULT Load(const CArc &arc, IProgress *progress);
};
@@ -56,19 +71,25 @@ public:
struct CProxyFile2
{
- int FolderIndex; // >= 0 for dir. (index in ProxyArchive2->Folders)
- int AltStreamsFolderIndex; // >= 0 if there are alt streams. (index in ProxyArchive2->Folders)
- int Parent; // >= 0 if there is parent. (index in archive and in ProxyArchive2->Files)
+ int DirIndex; // >= 0 for dir. (index in ProxyArchive2->Dirs)
+ int AltDirIndex; // >= 0 if there are alt streams. (index in ProxyArchive2->Dirs)
+ int Parent; // >= 0 if there is parent. (index in archive and in ProxyArchive2->Files)
const wchar_t *Name;
- unsigned NameSize;
+ unsigned NameLen;
+ bool NeedDeleteName;
bool Ignore;
bool IsAltStream;
- bool NeedDeleteName;
- int GetFolderIndex(bool forAltStreams) const { return forAltStreams ? AltStreamsFolderIndex : FolderIndex; }
-
- bool IsDir() const { return FolderIndex >= 0; }
- CProxyFile2(): FolderIndex(-1), AltStreamsFolderIndex(-1), Name(NULL), Ignore(false), IsAltStream(false), NeedDeleteName(false) {}
+ int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; }
+
+ bool IsDir() const { return DirIndex >= 0; }
+ CProxyFile2():
+ DirIndex(-1), AltDirIndex(-1), Parent(-1),
+ Name(NULL), NameLen(0),
+ NeedDeleteName(false),
+ Ignore(false),
+ IsAltStream(false)
+ {}
~CProxyFile2()
{
if (NeedDeleteName)
@@ -76,53 +97,66 @@ struct CProxyFile2
}
};
-class CProxyFolder2
+struct CProxyDir2
{
-public:
- Int32 ArcIndex; // = -1 for Root folder
- CRecordVector<unsigned> SubFiles;
+ int ArcIndex; // = -1 for root folders, index in proxy->Files[]
+ CRecordVector<unsigned> Items;
UString PathPrefix;
UInt64 Size;
UInt64 PackSize;
bool CrcIsDefined;
UInt32 Crc;
- UInt32 NumSubFolders;
+ UInt32 NumSubDirs;
UInt32 NumSubFiles;
- CProxyFolder2(): ArcIndex(-1) {};
+ CProxyDir2(): ArcIndex(-1) {};
void AddFileSubItem(UInt32 index, const UString &name);
void Clear();
-
};
-class CProxyArchive2
+const unsigned k_Proxy2_RootDirIndex = k_Proxy_RootDirIndex;
+const unsigned k_Proxy2_AltRootDirIndex = 1;
+const unsigned k_Proxy2_NumRootDirs = 2;
+
+class CProxyArc2
{
- void CalculateSizes(unsigned folderIndex, IInArchive *archive);
- // AddRealIndices_of_Folder DOES NOT ADD item itself represented by folderIndex
- void AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const;
+ void CalculateSizes(unsigned dirIndex, IInArchive *archive);
+ // AddRealIndices_of_Dir DOES NOT ADD item itself represented by dirIndex
+ void AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const;
public:
- CObjectVector<CProxyFolder2> Folders; // Folders[0] - is root folder
- CObjArray<CProxyFile2> Files; // all aitems from archive in same order
+ CObjectVector<CProxyDir2> Dirs; // Dirs[0] - root folder
+ // Dirs[1] - for alt streams of root dir
+ CObjArray<CProxyFile2> Files; // all items from archive in same order
- bool IsThere_SubDir(unsigned folderIndex, const UString &name) const;
+ bool IsThere_SubDir(unsigned dirIndex, const UString &name) const;
- void GetPathParts(int folderIndex, UStringVector &pathParts) const;
- UString GetFullPathPrefix(unsigned folderIndex) const;
+ void GetDirPathParts(int dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const;
+ UString GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const;
+ bool IsAltDir(unsigned dirIndex) const;
// AddRealIndices_of_ArcItem DOES ADD item and subItems
void AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const;
- unsigned GetRealIndex(unsigned folderIndex, unsigned index) const;
- void GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const;
+ unsigned GetRealIndex(unsigned dirIndex, unsigned index) const;
+ void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const;
HRESULT Load(const CArc &arc, IProgress *progress);
- int GetParentFolderOfFile(UInt32 indexInArc) const
+ int GetParentDirOfFile(UInt32 arcIndex) const
{
- const CProxyFile2 &file = Files[indexInArc];
+ const CProxyFile2 &file = Files[arcIndex];
+
if (file.Parent < 0)
- return 0;
- return Files[file.Parent].FolderIndex;
+ return file.IsAltStream ?
+ k_Proxy2_AltRootDirIndex :
+ k_Proxy2_RootDirIndex;
+
+ const CProxyFile2 &parentFile = Files[file.Parent];
+ return file.IsAltStream ?
+ parentFile.AltDirIndex :
+ parentFile.DirIndex;
}
+
+ int FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const;
};
#endif
diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
index 81291f44..a20b4f24 100644
--- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp
+++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
@@ -28,9 +28,14 @@ STDMETHODIMP CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32
CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback;
RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2));
}
- NExtract::NPathMode::EEnum pathMode = _flatMode ?
- NExtract::NPathMode::kNoPaths :
- NExtract::NPathMode::kCurPaths;
+ NExtract::NPathMode::EEnum pathMode;
+ if (!_flatMode)
+ pathMode = NExtract::NPathMode::kCurPaths;
+ else
+ pathMode = (_proxy2 && _loadAltStreams) ?
+ NExtract::NPathMode::kNoPathsAlt :
+ NExtract::NPathMode::kNoPaths;
+
return Extract(indices, numItems,
includeAltStreams, replaceAltStreamCharsMode,
pathMode, NExtract::NOverwriteMode::kAsk,
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
index 13d94bdf..62d5b1f8 100644
--- a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
@@ -2,21 +2,19 @@
#include "StdAfx.h"
+#include "../../../Windows/DLL.h"
+
#include "Agent.h"
void CArchiveFolderManager::LoadFormats()
{
- if (!_codecs)
- {
- _compressCodecsInfo = _codecs = new CCodecs;
- _codecs->Load();
- }
+ LoadGlobalCodecs();
}
int CArchiveFolderManager::FindFormat(const UString &type)
{
- FOR_VECTOR (i, _codecs->Formats)
- if (type.IsEqualToNoCase(_codecs->Formats[i].Name))
+ FOR_VECTOR (i, g_CodecsObj->Formats)
+ if (type.IsEqualTo_NoCase(g_CodecsObj->Formats[i].Name))
return i;
return -1;
}
@@ -54,7 +52,7 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *ext
if (formatIndex < 0)
return E_INVALIDARG;
// Exts[0].Ext;
- return StringToBstr(_codecs.Formats[formatIndex].GetAllExtensions(), extensions);
+ return StringToBstr(g_CodecsObj.Formats[formatIndex].GetAllExtensions(), extensions);
}
*/
@@ -62,8 +60,7 @@ static void AddIconExt(const CCodecIcons &lib, UString &dest)
{
FOR_VECTOR (i, lib.IconPairs)
{
- if (!dest.IsEmpty())
- dest += L' ';
+ dest.Add_Space_if_NotEmpty();
dest += lib.IconPairs[i].Ext;
}
}
@@ -73,20 +70,30 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(BSTR *extensions)
LoadFormats();
*extensions = 0;
UString res;
- FOR_VECTOR (i, _codecs->Libs)
- AddIconExt(_codecs->Libs[i], res);
- AddIconExt(_codecs->InternalIcons, res);
+
+ #ifdef EXTERNAL_CODECS
+
+ FOR_VECTOR (i, g_CodecsObj->Libs)
+ AddIconExt(g_CodecsObj->Libs[i], res);
+
+ #endif
+
+ AddIconExt(g_CodecsObj->InternalIcons, res);
return StringToBstr(res, extensions);
}
STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex)
{
- LoadFormats();
*iconPath = 0;
*iconIndex = 0;
- FOR_VECTOR (i, _codecs->Libs)
+
+ LoadFormats();
+
+ #ifdef EXTERNAL_CODECS
+
+ FOR_VECTOR (i, g_CodecsObj->Libs)
{
- const CCodecLib &lib = _codecs->Libs[i];
+ const CCodecLib &lib = g_CodecsObj->Libs[i];
int ii;
if (lib.FindIconIndex(ext, ii))
{
@@ -94,8 +101,11 @@ STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPa
return StringToBstr(fs2us(lib.Path), iconPath);
}
}
+
+ #endif
+
int ii;
- if (_codecs->InternalIcons.FindIconIndex(ext, ii))
+ if (g_CodecsObj->InternalIcons.FindIconIndex(ext, ii))
{
FString path;
if (NWindows::NDLL::MyGetModuleFileName(path))
@@ -112,13 +122,13 @@ STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types)
{
LoadFormats();
UString typesStrings;
- FOR_VECTOR(i, _codecs.Formats)
+ FOR_VECTOR(i, g_CodecsObj.Formats)
{
- const CArcInfoEx &ai = _codecs.Formats[i];
+ const CArcInfoEx &ai = g_CodecsObj.Formats[i];
if (ai.AssociateExts.Size() == 0)
continue;
if (i != 0)
- typesStrings += L' ';
+ typesStrings.Add_Space();
typesStrings += ai.Name;
}
return StringToBstr(typesStrings, types);
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
index 003f6d98..325d6426 100644
--- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
@@ -1,4 +1,4 @@
-// FolderOut.cpp
+// ArchiveFolderOut.cpp
#include "StdAfx.h"
@@ -19,12 +19,12 @@ using namespace NWindows;
using namespace NFile;
using namespace NDir;
-void CAgentFolder::GetPathParts(UStringVector &pathParts)
+void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder)
{
- if (_proxyArchive2)
- _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts);
+ if (_proxy2)
+ _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder);
else
- _proxyArchive->GetPathParts(_proxyFolderItem, pathParts);
+ _proxy->GetDirPathParts(_proxyDirIndex, pathParts);
}
static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)
@@ -55,16 +55,25 @@ HRESULT CAgentFolder::CommonUpdateOperation(
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
const UInt32 *indices, UInt32 numItems,
- IFolderArchiveUpdateCallback *updateCallback100)
+ IProgress *progress)
{
if (!_agentSpec->CanUpdate())
return E_NOTIMPL;
- ////////////////////////////
- // Save FolderItem;
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
+ if (progress)
+ progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100);
+
+ try
+ {
+
+ RINOK(_agentSpec->SetFolder(this));
+
+ // ---------- Save FolderItem ----------
UStringVector pathParts;
- GetPathParts(pathParts);
+ bool isAltStreamFolder = false;
+ GetPathParts(pathParts, isAltStreamFolder);
FStringVector requestedPaths;
FStringVector processedPaths;
@@ -153,25 +162,96 @@ HRESULT CAgentFolder::CommonUpdateOperation(
}
}
-
{
CMyComPtr<IArchiveOpenCallback> openCallback;
if (updateCallback100)
- {
- RINOK(updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback));
- }
+ updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback);
RINOK(_agentSpec->ReOpen(openCallback));
}
- // Restore FolderItem;
+ // CAgent::ReOpen() deletes _proxy and _proxy2
+ _items.Clear();
+ _proxy = NULL;
+ _proxy2 = NULL;
+ _proxyDirIndex = k_Proxy_RootDirIndex;
+ _isAltStreamFolder = false;
+
+
+ // ---------- Restore FolderItem ----------
CMyComPtr<IFolderFolder> archiveFolder;
RINOK(_agentSpec->BindToRootFolder(&archiveFolder));
+
+ // CAgent::BindToRootFolder() changes _proxy and _proxy2
+ _proxy = _agentSpec->_proxy;
+ _proxy2 = _agentSpec->_proxy2;
+
+ if (_proxy)
+ {
+ FOR_VECTOR (i, pathParts)
+ {
+ int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]);
+ if (next < 0)
+ break;
+ _proxyDirIndex = next;
+ }
+ }
+
+ if (_proxy2)
+ {
+ if (pathParts.IsEmpty() && isAltStreamFolder)
+ {
+ _proxyDirIndex = k_Proxy2_AltRootDirIndex;
+ }
+ else FOR_VECTOR (i, pathParts)
+ {
+ bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder);
+ int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly);
+ if (index < 0)
+ break;
+
+ const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]];
+
+ if (dirOnly)
+ _proxyDirIndex = file.DirIndex;
+ else
+ {
+ if (file.AltDirIndex >= 0)
+ _proxyDirIndex = file.AltDirIndex;
+ break;
+ }
+ }
+ }
+
+ /*
+ if (pathParts.IsEmpty() && isAltStreamFolder)
+ {
+ CMyComPtr<IFolderAltStreams> folderAltStreams;
+ archiveFolder.QueryInterface(IID_IFolderAltStreams, &folderAltStreams);
+ if (folderAltStreams)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ folderAltStreams->BindToAltStreams((UInt32)(Int32)-1, &newFolder);
+ if (newFolder)
+ archiveFolder = newFolder;
+ }
+ }
+
FOR_VECTOR (i, pathParts)
{
CMyComPtr<IFolderFolder> newFolder;
- archiveFolder->BindToFolder(pathParts[i], &newFolder);
- if(!newFolder)
+
+ if (isAltStreamFolder && i == pathParts.Size() - 1)
+ {
+ CMyComPtr<IFolderAltStreams> folderAltStreams;
+ archiveFolder.QueryInterface(IID_IFolderAltStreams, &folderAltStreams);
+ if (folderAltStreams)
+ folderAltStreams->BindToAltStreams(pathParts[i], &newFolder);
+ }
+ else
+ archiveFolder->BindToFolder(pathParts[i], &newFolder);
+
+ if (!newFolder)
break;
archiveFolder = newFolder;
}
@@ -180,63 +260,56 @@ HRESULT CAgentFolder::CommonUpdateOperation(
RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
CAgentFolder *agentFolder;
RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));
- _proxyFolderItem = agentFolder->_proxyFolderItem;
- _proxyArchive = agentFolder->_proxyArchive;
- _proxyArchive2 = agentFolder->_proxyArchive2;
- _parentFolder = agentFolder->_parentFolder;
+ _proxyDirIndex = agentFolder->_proxyDirIndex;
+ // _parentFolder = agentFolder->_parentFolder;
+ */
+
+ if (_proxy2)
+ _isAltStreamFolder = _proxy2->IsAltDir(_proxyDirIndex);
return res;
+
+ }
+ catch(const UString &s)
+ {
+ if (updateCallback100)
+ {
+ UString s2 = L"Error: ";
+ s2 += s;
+ RINOK(updateCallback100->UpdateErrorMessage(s2));
+ return E_FAIL;
+ }
+ throw;
+ }
}
+
+
STDMETHODIMP CAgentFolder::CopyFrom(Int32 moveMode,
const wchar_t *fromFolderPath, // test it
- const wchar_t **itemsPaths,
+ const wchar_t * const *itemsPaths,
UInt32 numItems,
IProgress *progress)
{
COM_TRY_BEGIN
- CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
- if (progress)
- {
- RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100));
- }
- try
{
RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems));
- RINOK(_agentSpec->SetFolder(this));
return CommonUpdateOperation(AGENT_OP_Uni, (moveMode != 0), NULL,
&NUpdateArchive::k_ActionSet_Add,
- 0, 0, updateCallback100);
- }
- catch(const UString &s)
- {
- RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s));
- return E_FAIL;
+ NULL, 0, progress);
}
COM_TRY_END
}
-STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress * progress)
+STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress *progress)
{
COM_TRY_BEGIN
CUIntVector indices;
indices.Add(destIndex);
- CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
- if (progress)
- {
- RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100));
- }
- try
{
- RINOK(_agentSpec->SetFolder(this));
return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath,
&NUpdateArchive::k_ActionSet_Add,
- &indices.Front(), indices.Size(), updateCallback100);
- }
- catch(const UString &s)
- {
- RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s));
- return E_FAIL;
+ &indices.Front(), indices.Size(), progress);
}
COM_TRY_END
}
@@ -244,40 +317,30 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat
STDMETHODIMP CAgentFolder::Delete(const UInt32 *indices, UInt32 numItems, IProgress *progress)
{
COM_TRY_BEGIN
- RINOK(_agentSpec->SetFolder(this));
- CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
- if (progress)
- {
- CMyComPtr<IProgress> progressWrapper = progress;
- RINOK(progressWrapper.QueryInterface(
- IID_IFolderArchiveUpdateCallback, &updateCallback100));
- }
return CommonUpdateOperation(AGENT_OP_Delete, false, NULL,
- &NUpdateArchive::k_ActionSet_Delete, indices, numItems, updateCallback100);
+ &NUpdateArchive::k_ActionSet_Delete, indices, numItems, progress);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress)
{
COM_TRY_BEGIN
- if (_proxyArchive2)
+
+ if (_isAltStreamFolder)
+ return E_NOTIMPL;
+
+ if (_proxy2)
{
- if (_proxyArchive2->IsThere_SubDir(_proxyFolderItem, name))
+ if (_proxy2->IsThere_SubDir(_proxyDirIndex, name))
return ERROR_ALREADY_EXISTS;
}
else
{
- if (_proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name) >= 0)
+ if (_proxy->FindSubDir(_proxyDirIndex, name) >= 0)
return ERROR_ALREADY_EXISTS;
}
- RINOK(_agentSpec->SetFolder(this));
- CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
- if (progress)
- {
- CMyComPtr<IProgress> progressWrapper = progress;
- RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
- }
- return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, updateCallback100);
+
+ return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, progress);
COM_TRY_END
}
@@ -286,15 +349,8 @@ STDMETHODIMP CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgres
COM_TRY_BEGIN
CUIntVector indices;
indices.Add(index);
- RINOK(_agentSpec->SetFolder(this));
- CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
- if (progress)
- {
- CMyComPtr<IProgress> progressWrapper = progress;
- RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
- }
- return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL, &indices.Front(),
- indices.Size(), updateCallback100);
+ return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL,
+ &indices.Front(), indices.Size(), progress);
COM_TRY_END
}
diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h
index 0f87cb55..565e37b0 100644
--- a/CPP/7zip/UI/Agent/IFolderArchive.h
+++ b/CPP/7zip/UI/Agent/IFolderArchive.h
@@ -15,6 +15,15 @@
#define FOLDER_ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 0x01, x)
#define FOLDER_ARCHIVE_INTERFACE(i, x) FOLDER_ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
+/* ---------- IArchiveFolder ----------
+IArchiveFolder is implemented by CAgentFolder (Agent/Agent.h)
+IArchiveFolder is used by:
+ - FileManager/PanelCopy.cpp
+ CPanel::CopyTo(), if (options->testMode)
+ - FAR/PluginRead.cpp
+ CPlugin::ExtractFiles
+*/
+
#define INTERFACE_IArchiveFolder(x) \
STDMETHOD(Extract)(const UInt32 *indices, UInt32 numItems, \
Int32 includeAltStreams, \
@@ -29,6 +38,12 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x0D)
INTERFACE_IArchiveFolder(PURE)
};
+
+/* ---------- IInFolderArchive ----------
+IInFolderArchive is implemented by CAgent (Agent/Agent.h)
+IInFolderArchive Is used by FAR/Plugin
+*/
+
#define INTERFACE_IInFolderArchive(x) \
STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback) x; \
STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \
@@ -48,7 +63,7 @@ FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0E)
#define INTERFACE_IFolderArchiveUpdateCallback(x) \
STDMETHOD(CompressOperation)(const wchar_t *name) x; \
STDMETHOD(DeleteOperation)(const wchar_t *name) x; \
- STDMETHOD(OperationResult)(Int32 operationResult) x; \
+ STDMETHOD(OperationResult)(Int32 opRes) x; \
STDMETHOD(UpdateErrorMessage)(const wchar_t *message) x; \
STDMETHOD(SetNumFiles)(UInt64 numFiles) x; \
@@ -59,7 +74,7 @@ FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B)
#define INTERFACE_IOutFolderArchive(x) \
STDMETHOD(SetFolder)(IFolderFolder *folder) x; \
- STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \
+ STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t * const *names, UInt32 numNames) x; \
STDMETHOD(DeleteItems)(ISequentialOutStream *outArchiveStream, \
const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \
STDMETHOD(DoOperation)( \
@@ -79,4 +94,26 @@ FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0F)
INTERFACE_IOutFolderArchive(PURE)
};
+
+#define INTERFACE_IFolderArchiveUpdateCallback2(x) \
+ STDMETHOD(OpenFileError)(const wchar_t *path, HRESULT errorCode) x; \
+ STDMETHOD(ReadingFileError)(const wchar_t *path, HRESULT errorCode) x; \
+ STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 isEncrypted, const wchar_t *path) x; \
+ STDMETHOD(ReportUpdateOperation)(UInt32 notifyOp, const wchar_t *path, Int32 isDir) x; \
+
+FOLDER_ARCHIVE_INTERFACE(IFolderArchiveUpdateCallback2, 0x10)
+{
+ INTERFACE_IFolderArchiveUpdateCallback2(PURE)
+};
+
+
+#define INTERFACE_IFolderScanProgress(x) \
+ STDMETHOD(ScanError)(const wchar_t *path, HRESULT errorCode) x; \
+ STDMETHOD(ScanProgress)(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 isDir) x; \
+
+FOLDER_ARCHIVE_INTERFACE(IFolderScanProgress, 0x11)
+{
+ INTERFACE_IFolderScanProgress(PURE)
+};
+
#endif
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
index cfdacb2f..e2813c80 100644
--- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
@@ -14,14 +14,24 @@ void CUpdateCallbackAgent::SetCallback(IFolderArchiveUpdateCallback *callback)
{
Callback = callback;
_compressProgress.Release();
+ Callback2.Release();
if (Callback)
+ {
Callback.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
+ Callback.QueryInterface(IID_IFolderArchiveUpdateCallback2, &Callback2);
+ }
}
-HRESULT CUpdateCallbackAgent::SetNumFiles(UInt64 numFiles)
+HRESULT CUpdateCallbackAgent::SetNumItems(UInt64 numItems)
{
if (Callback)
- return Callback->SetNumFiles(numFiles);
+ return Callback->SetNumFiles(numItems);
+ return S_OK;
+}
+
+
+HRESULT CUpdateCallbackAgent::WriteSfx(const wchar_t * /* name */, UInt64 /* size */)
+{
return S_OK;
}
@@ -52,31 +62,65 @@ HRESULT CUpdateCallbackAgent::CheckBreak()
return S_OK;
}
-HRESULT CUpdateCallbackAgent::Finilize()
+/*
+HRESULT CUpdateCallbackAgent::Finalize()
{
return S_OK;
}
+*/
-HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemError)
+HRESULT CUpdateCallbackAgent::OpenFileError(const FString &path, DWORD systemError)
{
+ HRESULT hres = HRESULT_FROM_WIN32(systemError);
// if (systemError == ERROR_SHARING_VIOLATION)
{
+ if (Callback2)
+ {
+ RINOK(Callback2->OpenFileError(fs2us(path), hres));
+ return S_FALSE;
+ }
+
if (Callback)
{
UString s = L"WARNING: ";
s += NError::MyFormatMessage(systemError);
s += L": ";
- s += name;
+ s += fs2us(path);
RINOK(Callback->UpdateErrorMessage(s));
return S_FALSE;
}
}
// FailedFiles.Add(name);
- return systemError;
+ return hres;
+}
+
+HRESULT CUpdateCallbackAgent::ReadingFileError(const FString &path, DWORD systemError)
+{
+ HRESULT hres = HRESULT_FROM_WIN32(systemError);
+
+ // if (systemError == ERROR_SHARING_VIOLATION)
+ {
+ if (Callback2)
+ {
+ RINOK(Callback2->ReadingFileError(fs2us(path), hres));
+ }
+ else if (Callback)
+ {
+ UString s = L"ERROR: ";
+ s += NError::MyFormatMessage(systemError);
+ s += L": ";
+ s += fs2us(path);
+ RINOK(Callback->UpdateErrorMessage(s));
+ }
+ }
+ // FailedFiles.Add(name);
+ return hres;
}
-HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool /* isAnti */)
+HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool isDir, bool /* isAnti */, UInt32 mode)
{
+ if (Callback2)
+ return Callback2->ReportUpdateOperation(mode, name, BoolToInt(isDir));
if (Callback)
return Callback->CompressOperation(name);
return S_OK;
@@ -89,6 +133,50 @@ HRESULT CUpdateCallbackAgent::SetOperationResult(Int32 operationResult)
return S_OK;
}
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);
+
+HRESULT CUpdateCallbackAgent::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
+{
+ if (Callback2)
+ {
+ return Callback2->ReportExtractResult(opRes, isEncrypted, name);
+ }
+ /*
+ if (mode != NArchive::NExtract::NOperationResult::kOK)
+ {
+ Int32 encrypted = 0;
+ UString s;
+ SetExtractErrorMessage(mode, encrypted, name, s);
+ // ProgressDialog->Sync.AddError_Message(s);
+ }
+ */
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackAgent::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir)
+{
+ if (Callback2)
+ {
+ return Callback2->ReportUpdateOperation(op, name, BoolToInt(isDir));
+ }
+ return S_OK;
+}
+
+/*
+HRESULT CUpdateCallbackAgent::SetPassword(const UString &
+ #ifndef _NO_CRYPTO
+ password
+ #endif
+ )
+{
+ #ifndef _NO_CRYPTO
+ PasswordIsDefined = true;
+ Password = password;
+ #endif
+ return S_OK;
+}
+*/
+
HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
*password = NULL;
@@ -114,9 +202,7 @@ HRESULT CUpdateCallbackAgent::CryptoGetTextPassword(BSTR *password)
return getTextPassword->CryptoGetTextPassword(password);
}
-/*
-HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name)
+HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
{
return Callback->DeleteOperation(name);
}
-*/
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
index 3707a93c..4da7693c 100644
--- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
@@ -10,8 +10,10 @@
class CUpdateCallbackAgent: public IUpdateCallbackUI
{
INTERFACE_IUpdateCallbackUI(;)
+
CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
CMyComPtr<IFolderArchiveUpdateCallback> Callback;
+ CMyComPtr<IFolderArchiveUpdateCallback2> Callback2;
CMyComPtr<ICompressProgressInfo> _compressProgress;
public:
void SetCallback(IFolderArchiveUpdateCallback *callback);
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
index 0c7ae1c9..4df4b199 100644
--- a/CPP/7zip/UI/Client7z/Client7z.cpp
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -32,8 +32,14 @@ HINSTANCE g_hInstance = 0;
// Tou can find the list of all GUIDs in Guid.txt file.
// use another CLSIDs, if you want to support other formats (zip, rar, ...).
// {23170F69-40C1-278A-1000-000110070000}
+
DEFINE_GUID(CLSID_CFormat7z,
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);
+DEFINE_GUID(CLSID_CFormatXz,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0C, 0x00, 0x00);
+
+#define CLSID_Format CLSID_CFormat7z
+// #define CLSID_Format CLSID_CFormatXz
using namespace NWindows;
using namespace NFile;
@@ -326,7 +332,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,
{
// Create folders for file
- int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);
+ int slashPos = _filePath.ReverseFind_PathSepar();
if (slashPos >= 0)
CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos)));
}
@@ -662,7 +668,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu
ConvertUInt32ToString(index + 1, temp);
UString res = temp;
while (res.Len() < 2)
- res = UString(L'0') + res;
+ res.InsertAtFront(L'0');
UString fileName = VolName;
fileName += L'.';
fileName += res;
@@ -774,7 +780,7 @@ int MY_CDECL main(int numArgs, const char *args[])
}
CMyComPtr<IOutArchive> outArchive;
- if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK)
+ if (createObjectFunc(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK)
{
PrintError("Can not get class object");
return 1;
@@ -845,7 +851,7 @@ int MY_CDECL main(int numArgs, const char *args[])
}
CMyComPtr<IInArchive> archive;
- if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK)
+ if (createObjectFunc(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK)
{
PrintError("Can not get class object");
return 1;
@@ -867,7 +873,8 @@ int MY_CDECL main(int numArgs, const char *args[])
// openCallbackSpec->PasswordIsDefined = true;
// openCallbackSpec->Password = L"1";
- if (archive->Open(file, 0, openCallback) != S_OK)
+ const UInt64 scanSize = 1 << 23;
+ if (archive->Open(file, &scanSize, openCallback) != S_OK)
{
PrintError("Can not open file as archive", archiveName);
return 1;
diff --git a/CPP/7zip/UI/Client7z/resource.rc b/CPP/7zip/UI/Client7z/resource.rc
index 1bb4d4e3..a09bb044 100644
--- a/CPP/7zip/UI/Client7z/resource.rc
+++ b/CPP/7zip/UI/Client7z/resource.rc
@@ -1,3 +1,3 @@
-#include "../../../../C/7zVersion.rc"
+#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_APP("7-Zip client", "7zcl")
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index 0bfed8ab..99013946 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -59,17 +59,12 @@ static bool StringToUInt32(const wchar_t *s, UInt32 &v)
return *end == 0;
}
-static void AddNewLine(UString &s)
-{
- s += L'\n';
-}
-
CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u)
{
(*this) += MultiByteToUnicodeString(a);
if (u)
{
- AddNewLine(*this);
+ this->Add_LF();
(*this) += u;
}
}
@@ -82,37 +77,53 @@ enum Enum
kHelp1 = 0,
kHelp2,
kHelp3,
+
kDisableHeaders,
kDisablePercents,
- kArchiveType,
+ kShowTime,
+ kLogLevel,
+
+ kOutStream,
+ kErrStream,
+ kPercentStream,
+
kYes,
- #ifndef _NO_CRYPTO
- kPassword,
- #endif
+
+ kShowDialog,
+ kOverwrite,
+
+ kArchiveType,
+ kExcludedArcType,
+
kProperty,
kOutputDir,
kWorkingDir,
+
kInclude,
kExclude,
kArInclude,
kArExclude,
kNoArName,
+
kUpdate,
kVolume,
kRecursed,
+
+ kAffinity,
kSfx,
+ kEmail,
+ kHash,
+
kStdIn,
kStdOut,
- kOverwrite,
- kEmail,
- kShowDialog,
+
kLargePages,
kListfileCharSet,
kConsoleCharSet,
kTechMode,
+
kShareForWrite,
kCaseSensitive,
- kHash,
kArcNameMode,
kDisableWildcardParsing,
@@ -127,8 +138,11 @@ enum Enum
kWriteToAltStreamIfColon,
kDeleteAfterCompressing,
- kSetArcMTime,
- kExcludedArcType
+ kSetArcMTime
+
+ #ifndef _NO_CRYPTO
+ , kPassword
+ #endif
};
}
@@ -139,6 +153,8 @@ static const char *kRecursedPostCharSet = "0-";
static const char *k_ArcNameMode_PostCharSet = "sea";
+static const char *k_Stream_PostCharSet = "012";
+
static inline const EArcNameMode ParseArcNameMode(int postCharIndex)
{
switch (postCharIndex)
@@ -166,7 +182,7 @@ static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!
static const char *kOverwritePostCharSet = "asut";
-NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
+static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
{
NExtract::NOverwriteMode::kOverwrite,
NExtract::NOverwriteMode::kSkip,
@@ -179,37 +195,53 @@ static const CSwitchForm kSwitchForms[] =
{ "?" },
{ "h" },
{ "-help" },
+
{ "ba" },
{ "bd" },
- { "t", NSwitchType::kString, false, 1 },
+ { "bt" },
+ { "bb", NSwitchType::kString, false, 0 },
+
+ { "bso", NSwitchType::kChar, false, 1, k_Stream_PostCharSet },
+ { "bse", NSwitchType::kChar, false, 1, k_Stream_PostCharSet },
+ { "bsp", NSwitchType::kChar, false, 1, k_Stream_PostCharSet },
+
{ "y" },
- #ifndef _NO_CRYPTO
- { "p", NSwitchType::kString },
- #endif
+
+ { "ad" },
+ { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet},
+
+ { "t", NSwitchType::kString, false, 1 },
+ { "stx", NSwitchType::kString, true, 1 },
+
{ "m", NSwitchType::kString, true, 1 },
{ "o", NSwitchType::kString, false, 1 },
{ "w", NSwitchType::kString },
+
{ "i", NSwitchType::kString, true, kSomeCludePostStringMinSize},
{ "x", NSwitchType::kString, true, kSomeCludePostStringMinSize},
{ "ai", NSwitchType::kString, true, kSomeCludePostStringMinSize},
{ "ax", NSwitchType::kString, true, kSomeCludePostStringMinSize},
{ "an" },
+
{ "u", NSwitchType::kString, true, 1},
{ "v", NSwitchType::kString, true, 1},
{ "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet },
+
+ { "stm", NSwitchType::kString },
{ "sfx", NSwitchType::kString },
+ { "seml", NSwitchType::kString, false, 0},
+ { "scrc", NSwitchType::kString, true, 0 },
+
{ "si", NSwitchType::kString },
{ "so" },
- { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet},
- { "seml", NSwitchType::kString, false, 0},
- { "ad" },
+
{ "slp", NSwitchType::kMinus },
{ "scs", NSwitchType::kString },
{ "scc", NSwitchType::kString },
{ "slt" },
+
{ "ssw" },
{ "ssc", NSwitchType::kMinus },
- { "scrc", NSwitchType::kString, true, 0 },
{ "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet },
{ "spd" },
@@ -220,24 +252,24 @@ static const CSwitchForm kSwitchForms[] =
{ "snl", NSwitchType::kMinus },
{ "sni" },
{ "sns", NSwitchType::kMinus },
-
{ "snr" },
{ "snc" },
{ "sdel" },
- { "stl" },
- { "stx", NSwitchType::kString, true, 1 }
+ { "stl" }
+
+ #ifndef _NO_CRYPTO
+ , { "p", NSwitchType::kString }
+ #endif
};
static const wchar_t *kUniversalWildcard = L"*";
-static const int kMinNonSwitchWords = 1;
-static const int kCommandIndex = 0;
+static const unsigned kMinNonSwitchWords = 1;
+static const unsigned kCommandIndex = 0;
// static const char *kUserErrorMessage = "Incorrect command line";
static const char *kCannotFindListFile = "Cannot find listfile";
static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";
-// static const char *kIncorrectWildcardInListFile = "Incorrect wildcard in listfile";
-// static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line";
static const char *kTerminalOutError = "I won't write compressed data to a terminal";
static const char *kSameTerminalError = "I won't write data and program's messages to same terminal";
static const char *kEmptyFilePath = "Empty file path";
@@ -350,13 +382,13 @@ static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs,
{
UString val;
val += pair.OldName;
- AddNewLine(val);
+ val.Add_LF();
val += pair.NewName;
- AddNewLine(val);
+ val.Add_LF();
if (type == NRecursedType::kRecursed)
- val += L"-r";
+ val.AddAscii("-r");
else if (type == NRecursedType::kRecursed)
- val += L"-r0";
+ val.AddAscii("-r0");
throw CArcCmdLineException("Unsupported rename command:", val);
}
}
@@ -411,7 +443,7 @@ static void AddToCensorFromNonSwitchesStrings(
else if (renamePairs)
{
if (oldIndex == -1)
- oldIndex = startIndex;
+ oldIndex = i;
else
{
// NRecursedType::EEnum type is used for global wildcard (-i! switches)
@@ -461,7 +493,7 @@ static const char *ParseMapWithPaths(
if (pos2 < 0)
return k_IncorrectMapCommand;
- CEventSetEnd eventSetEnd((const wchar_t *)s + (pos2 + 1));
+ CEventSetEnd eventSetEnd((const wchar_t *)s + ((unsigned)pos2 + 1));
s.DeleteFrom(pos2);
UInt32 size;
if (!StringToUInt32(s.Ptr(pos + 1), size)
@@ -561,7 +593,7 @@ static void AddSwitchWildcardsToCensor(
#endif
else
{
- errorMessage = "Incorrect wildcarc type marker";
+ errorMessage = "Incorrect wildcard type marker";
break;
}
}
@@ -579,8 +611,10 @@ static void ConvertToLongName(const UString &prefix, UString &name)
return;
NFind::CFileInfo fi;
const FString path = us2fs(prefix + name);
+ #ifndef UNDER_CE
if (NFile::NName::IsDevicePath(path))
return;
+ #endif
if (fi.Find(path))
name = fs2us(fi.Name);
}
@@ -617,7 +651,7 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no
for (unsigned j = i + 1; j < node.SubNodes.Size();)
{
const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
- if (nextNode1.Name.IsEqualToNoCase(nextNode2.Name))
+ if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name))
{
nextNode1.IncludeItems += nextNode2.IncludeItems;
nextNode1.ExcludeItems += nextNode2.ExcludeItems;
@@ -685,9 +719,9 @@ static bool ParseUpdateCommandString2(const UString &command,
c = command[i];
if (c < '0' || c >= '0' + kNumUpdatePairActions)
return false;
- int actionPos = c - '0';
- actionSet.StateActions[statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos);
- if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)
+ unsigned actionPos = c - '0';
+ actionSet.StateActions[(unsigned)statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos);
+ if (kUpdatePairStateNotSupportedActions[(unsigned)statePos] == (int)actionPos)
return false;
i++;
}
@@ -817,6 +851,12 @@ static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr
CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {}
+static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res)
+{
+ if (sw.ThereIs)
+ res = sw.PostCharIndex;
+}
+
void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
CArcCmdLineOptions &options)
{
@@ -826,10 +866,40 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
options.IsInTerminal = MY_IS_TERMINAL(stdin);
options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);
options.IsStdErrTerminal = MY_IS_TERMINAL(stderr);
+
+ options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs;
+
options.StdInMode = parser[NKey::kStdIn].ThereIs;
options.StdOutMode = parser[NKey::kStdOut].ThereIs;
options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
- options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs;
+ options.TechMode = parser[NKey::kTechMode].ThereIs;
+ options.ShowTime = parser[NKey::kShowTime].ThereIs;
+
+ if (parser[NKey::kDisablePercents].ThereIs
+ || options.StdOutMode
+ || !options.IsStdOutTerminal)
+ options.Number_for_Percents = k_OutStream_disabled;
+
+ if (options.StdOutMode)
+ options.Number_for_Out = k_OutStream_disabled;
+
+ SetStreamMode(parser[NKey::kOutStream], options.Number_for_Out);
+ SetStreamMode(parser[NKey::kErrStream], options.Number_for_Errors);
+ SetStreamMode(parser[NKey::kPercentStream], options.Number_for_Percents);
+
+ if (parser[NKey::kLogLevel].ThereIs)
+ {
+ const UString &s = parser[NKey::kLogLevel].PostStrings[0];
+ if (s.IsEmpty())
+ options.LogLevel = 1;
+ else
+ {
+ UInt32 v;
+ if (!StringToUInt32(s, v))
+ throw CArcCmdLineException("Unsupported switch postfix -bb", s);
+ options.LogLevel = (unsigned)v;
+ }
+ }
if (parser[NKey::kCaseSensitive].ThereIs)
{
@@ -838,12 +908,37 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
options.CaseSensitive = g_CaseSensitive;
}
- #ifdef _WIN32
options.LargePages = false;
if (parser[NKey::kLargePages].ThereIs)
- {
options.LargePages = !parser[NKey::kLargePages].WithMinus;
+
+
+ #ifndef UNDER_CE
+
+ if (parser[NKey::kAffinity].ThereIs)
+ {
+ const UString &s = us2fs(parser[NKey::kAffinity].PostStrings[0]);
+ if (!s.IsEmpty())
+ {
+ UInt32 v = 0;
+ AString a;
+ a.SetFromWStr_if_Ascii(s);
+ if (!a.IsEmpty())
+ {
+ const char *end;
+ v = ConvertHexStringToUInt32(a, &end);
+ if (*end != 0)
+ a.Empty();
+ }
+ if (a.IsEmpty())
+ throw CArcCmdLineException("Unsupported switch postfix -stm", s);
+
+ #ifdef _WIN32
+ SetProcessAffinityMask(GetCurrentProcess(), v);
+ #endif
+ }
}
+
#endif
}
@@ -855,7 +950,7 @@ struct CCodePagePair
static const unsigned kNumByteOnlyCodePages = 3;
-static CCodePagePair g_CodePagePairs[] =
+static const CCodePagePair g_CodePagePairs[] =
{
{ "utf-8", CP_UTF8 },
{ "win", CP_ACP },
@@ -864,7 +959,7 @@ static CCodePagePair g_CodePagePairs[] =
{ "utf-16be", MY__CP_UTF16BE }
};
-static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex,
+static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned keyIndex,
bool byteOnlyCodePages, Int32 defaultVal)
{
if (!parser[keyIndex].ThereIs)
@@ -887,29 +982,26 @@ static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex
}
}
-void EnumerateDirItemsAndSort(
- bool storeAltStreams,
+HRESULT EnumerateDirItemsAndSort(
NWildcard::CCensor &censor,
NWildcard::ECensorPathMode censorPathMode,
const UString &addPathPrefix,
UStringVector &sortedPaths,
- UStringVector &sortedFullPaths)
+ UStringVector &sortedFullPaths,
+ CDirItemsStat &st,
+ IDirItemsCallback *callback)
{
- UStringVector paths;
+ FStringVector paths;
+
{
CDirItems dirItems;
+ dirItems.Callback = callback;
{
- dirItems.ScanAltStreams = storeAltStreams;
- HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems, NULL);
- if (res != S_OK || dirItems.ErrorPaths.Size() > 0)
- {
- UString errorPath;
- if (dirItems.ErrorPaths.Size() > 0)
- errorPath = fs2us(dirItems.ErrorPaths[0]);
- throw CArcCmdLineException(kCannotFindArchive,
- dirItems.ErrorPaths.Size() > 0 ? (const wchar_t *)errorPath : NULL);
- }
+ HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems);
+ st = dirItems.Stat;
+ RINOK(res);
}
+
FOR_VECTOR (i, dirItems.Items)
{
const CDirItem &dirItem = dirItems.Items[i];
@@ -924,24 +1016,29 @@ void EnumerateDirItemsAndSort(
UStringVector fullPaths;
unsigned i;
+
for (i = 0; i < paths.Size(); i++)
{
FString fullPath;
- NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath);
+ NFile::NDir::MyGetFullPathName(paths[i], fullPath);
fullPaths.Add(fs2us(fullPath));
}
+
CUIntVector indices;
SortFileNames(fullPaths, indices);
sortedPaths.ClearAndReserve(indices.Size());
sortedFullPaths.ClearAndReserve(indices.Size());
+
for (i = 0; i < indices.Size(); i++)
{
unsigned index = indices[i];
- sortedPaths.AddInReserved(paths[index]);
+ sortedPaths.AddInReserved(fs2us(paths[index]));
sortedFullPaths.AddInReserved(fullPaths[index]);
if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0)
throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]);
}
+
+ return S_OK;
}
static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp)
@@ -954,14 +1051,13 @@ static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID,
void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
{
const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
- int numNonSwitchStrings = nonSwitchStrings.Size();
+ unsigned numNonSwitchStrings = nonSwitchStrings.Size();
if (numNonSwitchStrings < kMinNonSwitchWords)
throw CArcCmdLineException("The command must be spcified");
if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]);
- options.TechMode = parser[NKey::kTechMode].ThereIs;
if (parser[NKey::kHash].ThereIs)
options.HashMethods = parser[NKey::kHash].PostStrings;
@@ -1012,7 +1108,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
AddSwitchWildcardsToCensor(options.Censor,
parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage);
- int curCommandIndex = kCommandIndex + 1;
+ unsigned curCommandIndex = kCommandIndex + 1;
bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&
options.Command.CommandType != NCommandType::kBenchmark &&
options.Command.CommandType != NCommandType::kInfo &&
@@ -1035,6 +1131,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
options.ArchiveName = nonSwitchStrings[curCommandIndex++];
if (options.ArchiveName.IsEmpty())
throw CArcCmdLineException("Archive name cannot by empty");
+ #ifdef _WIN32
+ // options.ArchiveName.Replace(L'/', WCHAR_PATH_SEPARATOR);
+ #endif
}
AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL,
@@ -1060,15 +1159,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
SetMethodOptions(parser, options.Properties);
- options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;
-
- if (options.EnablePercents)
- {
- if ((options.StdOutMode && !options.IsStdErrTerminal) ||
- (!options.StdOutMode && !options.IsStdOutTerminal))
- options.EnablePercents = false;
- }
-
if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue();
SetBoolPair(parser, NKey::kAltStreams, options.AltStreams);
@@ -1106,7 +1196,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
if (!options.Censor.AllAreRelative())
throw CArcCmdLineException("Cannot use absolute pathnames for this command");
- NWildcard::CCensor arcCensor;
+ NWildcard::CCensor &arcCensor = options.arcCensor;
if (parser[NKey::kArInclude].ThereIs)
AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage);
@@ -1125,21 +1215,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
arcCensor.ExtendExclude();
if (options.StdInMode)
- {
- UString arcName = parser[NKey::kStdIn].PostStrings.Front();
- options.ArchivePathsSorted.Add(arcName);
- options.ArchivePathsFullSorted.Add(arcName);
- }
- else
- {
- EnumerateDirItemsAndSort(
- false, // scanAltStreams
- arcCensor,
- NWildcard::k_RelatPath,
- UString(), // addPathPrefix
- options.ArchivePathsSorted,
- options.ArchivePathsFullSorted);
- }
+ options.ArcName_for_StdInMode = parser[NKey::kStdIn].PostStrings.Front();
if (isExtractGroupCommand)
{
@@ -1154,7 +1230,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
eo.OverwriteMode = NExtract::NOverwriteMode::kAsk;
if (parser[NKey::kOverwrite].ThereIs)
{
- eo.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
+ eo.OverwriteMode = k_OverwriteModes[(unsigned)parser[NKey::kOverwrite].PostCharIndex];
eo.OverwriteMode_Force = true;
}
else if (options.YesToAll)
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
index 22e3d4bf..a345505c 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -40,13 +40,18 @@ struct CArcCommand
NExtract::NPathMode::EEnum GetPathMode() const;
};
+enum
+{
+ k_OutStream_disabled = 0,
+ k_OutStream_stdout = 1,
+ k_OutStream_stderr = 2
+};
+
struct CArcCmdLineOptions
{
bool HelpMode;
- #ifdef _WIN32
bool LargePages;
- #endif
bool CaseSensitiveChange;
bool CaseSensitive;
@@ -70,12 +75,16 @@ struct CArcCmdLineOptions
#endif
bool TechMode;
+ bool ShowTime;
UStringVector HashMethods;
bool AppendName;
- UStringVector ArchivePathsSorted;
- UStringVector ArchivePathsFullSorted;
+ // UStringVector ArchivePathsSorted;
+ // UStringVector ArchivePathsFullSorted;
+ NWildcard::CCensor arcCensor;
+ UString ArcName_for_StdInMode;
+
CObjectVector<CProperty> Properties;
CExtractOptionsBase ExtractOptions;
@@ -89,17 +98,32 @@ struct CArcCmdLineOptions
CHashOptions HashOptions;
UString ArcType;
UStringVector ExcludedArcTypes;
- bool EnablePercents;
+
+ unsigned Number_for_Out;
+ unsigned Number_for_Errors;
+ unsigned Number_for_Percents;
+ unsigned LogLevel;
+
+ // bool IsOutAllowed() const { return Number_for_Out != k_OutStream_disabled; }
// Benchmark
UInt32 NumIterations;
CArcCmdLineOptions():
+ LargePages(false),
+ CaseSensitiveChange(false),
+ CaseSensitive(false),
+
StdInMode(false),
StdOutMode(false),
- CaseSensitiveChange(false),
- CaseSensitive(false)
- {};
+
+ Number_for_Out(k_OutStream_stdout),
+ Number_for_Errors(k_OutStream_stderr),
+ Number_for_Percents(k_OutStream_stdout),
+
+ LogLevel(0)
+ {
+ };
};
class CArcCmdLineParser
@@ -111,12 +135,13 @@ public:
void Parse2(CArcCmdLineOptions &options);
};
-void EnumerateDirItemsAndSort(
- bool storeAltStreams,
+HRESULT EnumerateDirItemsAndSort(
NWildcard::CCensor &censor,
NWildcard::ECensorPathMode pathMode,
const UString &addPathPrefix,
UStringVector &sortedPaths,
- UStringVector &sortedFullPaths);
+ UStringVector &sortedFullPaths,
+ CDirItemsStat &st,
+ IDirItemsCallback *callback);
#endif
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index c1d41238..8410756a 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -6,9 +6,11 @@
#undef printf
#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/Wildcard.h"
+#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileName.h"
@@ -84,7 +86,7 @@ int CHardLinkNode::Compare(const CHardLinkNode &a) const
return MyCompare(INode, a.INode);
}
-HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)
+static HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)
{
h.INode = 0;
h.StreamId = (UInt64)(Int64)-1;
@@ -128,9 +130,16 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r
{
CHardLinkNode h;
bool defined;
- RINOK(Archive_Get_HardLinkNode(archive, realIndices ? (*realIndices)[i] : i, h, defined));
+ UInt32 realIndex = realIndices ? (*realIndices)[i] : i;
+
+ RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined));
if (defined)
- hardIDs.Add(h);
+ {
+ bool isAltStream = false;
+ RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream));
+ if (!isAltStream)
+ hardIDs.Add(h);
+ }
}
}
@@ -181,7 +190,7 @@ void CArchiveExtractCallback::Init(
IFolderArchiveExtractCallback *extractCallback2,
bool stdOutMode, bool testMode,
const FString &directoryPath,
- const UStringVector &removePathParts,
+ const UStringVector &removePathParts, bool removePartsForAltStreams,
UInt64 packSize)
{
_extractedFolderPaths.Clear();
@@ -191,17 +200,29 @@ void CArchiveExtractCallback::Init(
_hardLinks.Clear();
#endif
+ #ifdef SUPPORT_ALT_STREAMS
+ _renamedFiles.Clear();
+ #endif
+
_ntOptions = ntOptions;
_wildcardCensor = wildcardCensor;
_stdOutMode = stdOutMode;
_testMode = testMode;
- _unpTotal = 1;
+
+ // _progressTotal = 0;
+ // _progressTotal_Defined = false;
+
+ _progressTotal = _packTotal;
+ _progressTotal_Defined = true;
+
_packTotal = packSize;
_extractCallback2 = extractCallback2;
_compressProgress.Release();
_extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
+ _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage, &_callbackMessage);
+ _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2);
#ifndef _SFX
@@ -221,19 +242,31 @@ void CArchiveExtractCallback::Init(
LocalProgressSpec->SendProgress = false;
_removePathParts = removePathParts;
+ _removePartsForAltStreams = removePartsForAltStreams;
+
+ #ifndef _SFX
_baseParentFolder = (UInt32)(Int32)-1;
_use_baseParentFolder_mode = false;
+ #endif
_arc = arc;
- _directoryPath = directoryPath;
- NName::NormalizeDirPathPrefix(_directoryPath);
- NDir::MyGetFullPathName(directoryPath, _directoryPathFull);
+ _dirPathPrefix = directoryPath;
+ _dirPathPrefix_Full = directoryPath;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (!NName::IsAltPathPrefix(_dirPathPrefix))
+ #endif
+ {
+ NName::NormalizeDirPathPrefix(_dirPathPrefix);
+ NDir::MyGetFullPathName(directoryPath, _dirPathPrefix_Full);
+ NName::NormalizeDirPathPrefix(_dirPathPrefix_Full);
+ }
}
STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
{
COM_TRY_BEGIN
- _unpTotal = size;
+ _progressTotal = size;
+ _progressTotal_Defined = true;
if (!_multiArchives && _extractCallback2)
return _extractCallback2->SetTotal(size);
return S_OK;
@@ -262,18 +295,20 @@ static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)
STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
{
COM_TRY_BEGIN
+
if (!_extractCallback2)
return S_OK;
+ UInt64 packCur;
if (_multiArchives)
{
- if (completeValue != NULL)
- {
- UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal);
- return _extractCallback2->SetCompleted(&packCur);
- }
+ packCur = LocalProgressSpec->InSize;
+ if (completeValue && _progressTotal_Defined)
+ packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal);
+ completeValue = &packCur;
}
return _extractCallback2->SetCompleted(completeValue);
+
COM_TRY_END
}
@@ -284,13 +319,6 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U
COM_TRY_END
}
-#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
-
-static inline bool IsDriveName(const UString &s)
-{
- return s.Len() == 2 && s[1] == ':' && IS_LETTER_CHAR(s[0]);
-}
-
void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)
{
bool isAbsPath = false;
@@ -300,10 +328,10 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
const UString &s = dirPathParts[0];
if (s.IsEmpty())
isAbsPath = true;
- #ifdef _WIN32
+ #if defined(_WIN32) && !defined(UNDER_CE)
else
{
- if (dirPathParts.Size() > 1 && IsDriveName(s))
+ if (NName::IsDrivePath2(s))
isAbsPath = true;
}
#endif
@@ -312,17 +340,17 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath)
fullPath.Empty();
else
- fullPath = _directoryPath;
+ fullPath = _dirPathPrefix;
FOR_VECTOR (i, dirPathParts)
{
- if (i > 0)
- fullPath += FCHAR_PATH_SEPARATOR;
+ if (i != 0)
+ fullPath.Add_PathSepar();
const UString &s = dirPathParts[i];
fullPath += us2fs(s);
- #ifdef _WIN32
+ #if defined(_WIN32) && !defined(UNDER_CE)
if (_pathMode == NExtract::NPathMode::kAbsPaths)
- if (i == 0 && IsDriveName(s))
+ if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s))
continue;
#endif
CreateDir(fullPath);
@@ -349,32 +377,57 @@ HRESULT CArchiveExtractCallback::GetUnpackSize()
return _arc->GetItemSize(_index, _curSize, _curSizeDefined);
}
+static void AddPathToMessage(UString &s, const FString &path)
+{
+ s.AddAscii(" : ");
+ s += fs2us(path);
+}
+
HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)
{
- return _extractCallback2->MessageError(
- UString(L"ERROR: ") +
- GetUnicodeString(message) + L": " + fs2us(path));
+ UString s;
+ s.AddAscii(message);
+ AddPathToMessage(s, path);
+ return _extractCallback2->MessageError(s);
+}
+
+HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)
+{
+ DWORD errorCode = GetLastError();
+ UString s;
+ s.AddAscii(message);
+ if (errorCode != 0)
+ {
+ s.AddAscii(" : ");
+ s += NError::MyFormatMessage(errorCode);
+ }
+ AddPathToMessage(s, path);
+ return _extractCallback2->MessageError(s);
}
HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2)
{
- return _extractCallback2->MessageError(
- UString(L"ERROR: ") +
- GetUnicodeString(message) + UString(L": ") + fs2us(path1) + UString(L" : ") + fs2us(path2));
+ UString s;
+ s.AddAscii(message);
+ AddPathToMessage(s, path1);
+ AddPathToMessage(s, path2);
+ return _extractCallback2->MessageError(s);
}
#ifndef _SFX
STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)
{
+ /*
if (propID == kpidName)
{
COM_TRY_BEGIN
- NCOM::CPropVariant prop = Name.Ptr();
+ NCOM::CPropVariant prop = Name;
prop.Detach(value);
return S_OK;
COM_TRY_END
}
+ */
return Arc->Archive->GetProperty(IndexInArc, propID, value);
}
@@ -388,9 +441,9 @@ static UString GetDirPrefixOf(const UString &src)
UString s = src;
if (!s.IsEmpty())
{
- if (s.Back() == WCHAR_PATH_SEPARATOR)
+ if (IsPathSepar(s.Back()))
s.DeleteBack();
- int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);
+ int pos = s.ReverseFind_PathSepar();
s.DeleteFrom(pos + 1);
}
return s;
@@ -423,6 +476,71 @@ static bool IsSafePath(const UString &path)
#endif
+bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include)
+{
+ bool found = false;
+
+ if (node.CheckPathVect(item.PathParts, !item.MainIsDir, include))
+ {
+ if (!include)
+ return true;
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if (!item.IsAltStream)
+ return true;
+ #endif
+
+ found = true;
+ }
+
+ #ifdef SUPPORT_ALT_STREAMS
+
+ if (!item.IsAltStream)
+ return false;
+
+ UStringVector pathParts2 = item.PathParts;
+ if (pathParts2.IsEmpty())
+ pathParts2.AddNew();
+ UString &back = pathParts2.Back();
+ back += L':';
+ back += item.AltStreamName;
+ bool include2;
+
+ if (node.CheckPathVect(pathParts2,
+ true, // isFile,
+ include2))
+ {
+ include = include2;
+ return true;
+ }
+
+ #endif
+
+ return found;
+}
+
+bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item)
+{
+ bool include;
+ if (CensorNode_CheckPath2(node, item, include))
+ return include;
+ return false;
+}
+
+static FString MakePath_from_2_Parts(const FString &prefix, const FString &path)
+{
+ FString s = prefix;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back()))
+ {
+ if (!NName::IsDriveRootPath_SuperAllowed(prefix))
+ s.DeleteBack();
+ }
+ #endif
+ s += path;
+ return s;
+}
+
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
{
COM_TRY_BEGIN
@@ -438,19 +556,31 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
_outFileStream.Release();
_encrypted = false;
+ _position = 0;
_isSplit = false;
- _isAltStream = false;
+
_curSize = 0;
_curSizeDefined = false;
_index = index;
- UString fullPath;
-
IInArchive *archive = _arc->Archive;
- RINOK(_arc->GetItemPath(index, fullPath));
- RINOK(Archive_IsItem_Folder(archive, index, _fi.IsDir));
- _filePath = fullPath;
+ #ifndef _SFX
+ _item._use_baseParentFolder_mode = _use_baseParentFolder_mode;
+ if (_use_baseParentFolder_mode)
+ {
+ _item._baseParentFolder = _baseParentFolder;
+ if (_pathMode == NExtract::NPathMode::kFullPaths ||
+ _pathMode == NExtract::NPathMode::kAbsPaths)
+ _item._baseParentFolder = -1;
+ }
+ #endif
+
+ #ifdef SUPPORT_ALT_STREAMS
+ _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon;
+ #endif
+
+ RINOK(_arc->GetItem(index, _item));
{
NCOM::CPropVariant prop;
@@ -479,7 +609,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
if (prop.vt == VT_BSTR)
{
isHardLink = true;
- linkPath = prop.bstrVal;
+ linkPath.SetFromBstr(prop.bstrVal);
isRelative = false; // TAR: hard links are from root folder of archive
}
else if (prop.vt == VT_EMPTY)
@@ -495,7 +625,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
if (prop.vt == VT_BSTR)
{
isHardLink = false;
- linkPath = prop.bstrVal;
+ linkPath.SetFromBstr(prop.bstrVal);
isRelative = true; // TAR: symbolic links are relative
}
else if (prop.vt == VT_EMPTY)
@@ -528,7 +658,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
isJunction = reparse.IsMountPoint();
isRelative = reparse.IsRelative();
#ifndef _WIN32
- linkPath.Replace(WCHAR_PATH_SEPARATOR, '/', );
+ linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR);
#endif
}
}
@@ -537,7 +667,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
if (!linkPath.IsEmpty())
{
#ifdef _WIN32
- linkPath.Replace('/', WCHAR_PATH_SEPARATOR);
+ linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR);
#endif
for (;;)
@@ -566,7 +696,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
}
if (!badPrefix)
pathParts.DeleteFrontal(_removePathParts.Size());
- linkPath = MakePathNameFromParts(pathParts);
+ linkPath = MakePathFromParts(pathParts);
}
#endif
@@ -575,56 +705,97 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
RINOK(GetUnpackSize());
- RINOK(Archive_IsItem_AltStream(archive, index, _isAltStream));
-
- if (!_ntOptions.AltStreams.Val && _isAltStream)
+ #ifdef SUPPORT_ALT_STREAMS
+
+ if (!_ntOptions.AltStreams.Val && _item.IsAltStream)
return S_OK;
+ #endif
+
+
+ UStringVector &pathParts = _item.PathParts;
+
if (_wildcardCensor)
{
- if (!_wildcardCensor->CheckPath(_isAltStream, fullPath, !_fi.IsDir))
+ if (!CensorNode_CheckPath(*_wildcardCensor, _item))
return S_OK;
}
-
- UStringVector pathParts;
-
+ #ifndef _SFX
if (_use_baseParentFolder_mode)
{
- int baseParent = _baseParentFolder;
- if (_pathMode == NExtract::NPathMode::kFullPaths ||
- _pathMode == NExtract::NPathMode::kAbsPaths)
- baseParent = -1;
- RINOK(_arc->GetItemPathToParent(index, baseParent, pathParts));
- if (_pathMode == NExtract::NPathMode::kNoPaths && !pathParts.IsEmpty())
- pathParts.DeleteFrontal(pathParts.Size() - 1);
+ if (!pathParts.IsEmpty())
+ {
+ unsigned numRemovePathParts = 0;
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if (_pathMode == NExtract::NPathMode::kNoPathsAlt && _item.IsAltStream)
+ numRemovePathParts = pathParts.Size();
+ else
+ #endif
+ if (_pathMode == NExtract::NPathMode::kNoPaths ||
+ _pathMode == NExtract::NPathMode::kNoPathsAlt)
+ numRemovePathParts = pathParts.Size() - 1;
+ pathParts.DeleteFrontal(numRemovePathParts);
+ }
}
else
+ #endif
{
- SplitPathToParts(fullPath, pathParts);
-
if (pathParts.IsEmpty())
- return E_FAIL;
+ {
+ if (_item.IsDir)
+ return S_OK;
+ /*
+ #ifdef SUPPORT_ALT_STREAMS
+ if (!_item.IsAltStream)
+ #endif
+ return E_FAIL;
+ */
+ }
+
unsigned numRemovePathParts = 0;
switch (_pathMode)
{
+ case NExtract::NPathMode::kFullPaths:
case NExtract::NPathMode::kCurPaths:
{
+ if (_removePathParts.IsEmpty())
+ break;
bool badPrefix = false;
- if (pathParts.Size() <= _removePathParts.Size())
+
+ if (pathParts.Size() < _removePathParts.Size())
badPrefix = true;
else
{
+ if (pathParts.Size() == _removePathParts.Size())
+ {
+ if (_removePartsForAltStreams)
+ {
+ #ifdef SUPPORT_ALT_STREAMS
+ if (!_item.IsAltStream)
+ #endif
+ badPrefix = true;
+ }
+ else
+ {
+ if (!_item.MainIsDir)
+ badPrefix = true;
+ }
+ }
+
+ if (!badPrefix)
FOR_VECTOR (i, _removePathParts)
{
- if (!_removePathParts[i].IsEqualToNoCase(pathParts[i]))
+ if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)
{
badPrefix = true;
break;
}
}
}
+
if (badPrefix)
{
if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
@@ -634,9 +805,22 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
numRemovePathParts = _removePathParts.Size();
break;
}
+
case NExtract::NPathMode::kNoPaths:
{
- numRemovePathParts = pathParts.Size() - 1;
+ if (!pathParts.IsEmpty())
+ numRemovePathParts = pathParts.Size() - 1;
+ break;
+ }
+ case NExtract::NPathMode::kNoPathsAlt:
+ {
+ #ifdef SUPPORT_ALT_STREAMS
+ if (_item.IsAltStream)
+ numRemovePathParts = pathParts.Size();
+ else
+ #endif
+ if (!pathParts.IsEmpty())
+ numRemovePathParts = pathParts.Size() - 1;
break;
}
/*
@@ -660,9 +844,18 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
}
GetProp_Spec->Arc = _arc;
GetProp_Spec->IndexInArc = index;
- GetProp_Spec->Name = MakePathNameFromParts(pathParts);
+ UString name = MakePathFromParts(pathParts);
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if (_item.IsAltStream)
+ {
+ if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt))
+ name += L':';
+ name += _item.AltStreamName;
+ }
+ #endif
- return ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, _fi.IsDir, outStream, askExtractMode, GetProp);
+ return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp);
}
#endif
@@ -698,18 +891,33 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
bool isAnti = false;
RINOK(_arc->IsItemAnti(index, isAnti));
- bool replace = _isAltStream ?
- _ntOptions.ReplaceColonForAltStream :
- !_ntOptions.WriteToAltStreamIfColon;
+ Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, pathParts, _item.MainIsDir);
- if (_pathMode != NExtract::NPathMode::kAbsPaths)
- MakeCorrectPath(_directoryPath.IsEmpty(), pathParts, replace);
- Correct_IfEmptyLastPart(pathParts);
- UString processedPath = MakePathNameFromParts(pathParts);
+ #ifdef SUPPORT_ALT_STREAMS
+
+ if (_item.IsAltStream)
+ {
+ UString s = _item.AltStreamName;
+ Correct_AltStream_Name(s);
+ bool needColon = ((!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt) || !pathParts.IsEmpty());
+ if (pathParts.IsEmpty())
+ pathParts.AddNew();
+ if (_pathMode == NExtract::NPathMode::kAbsPaths &&
+ NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size())
+ pathParts.AddNew();
+ UString &name = pathParts.Back();
+ if (needColon)
+ name += (wchar_t)(_ntOptions.ReplaceColonForAltStream ? L'_' : L':');
+ name += s;
+ }
+
+ #endif
+
+ UString processedPath = MakePathFromParts(pathParts);
if (!isAnti)
{
- if (!_fi.IsDir)
+ if (!_item.IsDir)
{
if (!pathParts.IsEmpty())
pathParts.DeleteBack();
@@ -719,7 +927,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
FString fullPathNew;
CreateComplexDirectory(pathParts, fullPathNew);
- if (_fi.IsDir)
+ if (_item.IsDir)
{
_extractedFolderPaths.Add(fullPathNew);
_extractedFolderIndices.Add(index);
@@ -733,11 +941,34 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
FString fullProcessedPath = us2fs(processedPath);
- if (_pathMode != NExtract::NPathMode::kAbsPaths ||
- !NName::IsAbsolutePath(processedPath))
- fullProcessedPath = _directoryPath + fullProcessedPath;
+ if (_pathMode != NExtract::NPathMode::kAbsPaths
+ || !NName::IsAbsolutePath(processedPath))
+ {
+ fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath);
+ }
- if (_fi.IsDir)
+ #ifdef SUPPORT_ALT_STREAMS
+
+ if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1)
+ {
+ CIndexToPathPair pair(_item.ParentIndex);
+ int renIndex = _renamedFiles.FindInSorted(pair);
+ if (renIndex >= 0)
+ {
+ const CIndexToPathPair &pair = _renamedFiles[renIndex];
+ fullProcessedPath = pair.Path;
+ fullProcessedPath += (FChar)':';
+ UString s = _item.AltStreamName;
+ Correct_AltStream_Name(s);
+ fullProcessedPath += us2fs(s);
+ }
+ }
+
+ #endif
+
+ bool isRenamed = false;
+
+ if (_item.IsDir)
{
_diskFilePath = fullProcessedPath;
if (isAnti)
@@ -749,6 +980,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
}
else if (!_isSplit)
{
+
+ // ----- Is file (not split) -----
NFind::CFileInfo fileInfo;
if (fileInfo.Find(fullProcessedPath))
{
@@ -758,21 +991,17 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
return S_OK;
case NExtract::NOverwriteMode::kAsk:
{
- int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));
- #ifdef _WIN32
- int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
+ int slashPos = fullProcessedPath.ReverseFind_PathSepar();
FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name;
- Int32 overwiteResult;
+ Int32 overwriteResult;
RINOK(_extractCallback2->AskOverwrite(
- fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath,
+ fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path,
_fi.MTimeDefined ? &_fi.MTime : NULL,
_curSizeDefined ? &_curSize : NULL,
- &overwiteResult))
+ &overwriteResult))
- switch (overwiteResult)
+ switch (overwriteResult)
{
case NOverwriteAnswer::kCancel: return E_ABORT;
case NOverwriteAnswer::kNo: return S_OK;
@@ -792,6 +1021,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
return E_FAIL;
}
+ isRenamed = true;
}
else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)
{
@@ -801,10 +1031,10 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
return E_FAIL;
}
- // MyMoveFile can raname folders. So it's OK to use it folders too
+ // MyMoveFile can raname folders. So it's OK to use it for folders too
if (!MyMoveFile(fullProcessedPath, existPath))
{
- RINOK(SendMessageError(kCantRenameFile, fullProcessedPath));
+ RINOK(SendMessageError2(kCantRenameFile, existPath, fullProcessedPath));
return E_FAIL;
}
}
@@ -815,18 +1045,45 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
// do we need to delete all files in folder?
if (!RemoveDir(fullProcessedPath))
{
- RINOK(SendMessageError(kCantDeleteOutputDir, fullProcessedPath));
+ RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath));
return S_OK;
}
}
- else if (!DeleteFileAlways(fullProcessedPath))
+ else
{
- RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath));
- return S_OK;
- // return E_FAIL;
+ bool needDelete = true;
+ if (needDelete)
+ {
+ if (!DeleteFileAlways(fullProcessedPath))
+ {
+ RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath));
+ return S_OK;
+ // return E_FAIL;
+ }
+ }
}
}
}
+ else // not Find(fullProcessedPath)
+ {
+ // we need to clear READ-ONLY of parent before creating alt stream
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ int colonPos = NName::FindAltStreamColon(fullProcessedPath);
+ if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0)
+ {
+ FString parentFsPath = fullProcessedPath;
+ parentFsPath.DeleteFrom(colonPos);
+ NFind::CFileInfo parentFi;
+ if (parentFi.Find(parentFsPath))
+ {
+ if (parentFi.IsReadOnly())
+ SetFileAttrib(parentFsPath, parentFi.Attrib & ~FILE_ATTRIBUTE_READONLY);
+ }
+ }
+ #endif
+ }
+ // ----- END of code for Is file (not split) -----
+
}
_diskFilePath = fullProcessedPath;
@@ -841,7 +1098,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
UString relatPath;
if (isRelative)
- relatPath = GetDirPrefixOf(_filePath);
+ relatPath = GetDirPrefixOf(_item.Path);
relatPath += linkPath;
if (!IsSafePath(relatPath))
@@ -853,7 +1110,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
FString existPath;
if (isHardLink || !isRelative)
{
- if (!NName::GetFullPath(_directoryPathFull, us2fs(relatPath), existPath))
+ if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))
{
RINOK(SendMessageError("Incorrect path", us2fs(relatPath)));
}
@@ -876,7 +1133,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
else if (_ntOptions.SymLinks.Val)
{
// bool isSymLink = true; // = false for junction
- if (_fi.IsDir && !isRelative)
+ if (_item.IsDir && !isRelative)
{
// if it's before Vista we use Junction Point
// isJunction = true;
@@ -889,12 +1146,13 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
CReparseAttr attr;
if (!attr.Parse(data, data.Size()))
{
- return E_FAIL; // "Internal conversion error";
+ RINOK(SendMessageError("Internal error for symbolic link file", _item.Path));
+ // return E_FAIL;
}
-
- if (!NFile::NIO::SetReparseData(fullProcessedPath, _fi.IsDir, data, (DWORD)data.Size()))
+ else
+ if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size()))
{
- RINOK(SendMessageError("Can not set reparse data", fullProcessedPath));
+ RINOK(SendMessageError_with_LastError("Can not create symbolic link", fullProcessedPath));
}
}
}
@@ -909,7 +1167,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
bool needWriteFile = true;
#ifdef SUPPORT_LINKS
- if (!_hardLinks.IDs.IsEmpty())
+ if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream)
{
CHardLinkNode h;
bool defined;
@@ -946,10 +1204,23 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
// if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
{
- RINOK(SendMessageError("Can not open output file ", fullProcessedPath));
+ RINOK(SendMessageError_with_LastError("Can not open output file", fullProcessedPath));
return S_OK;
}
}
+
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if (isRenamed && !_item.IsAltStream)
+ {
+ CIndexToPathPair pair(index, fullProcessedPath);
+ unsigned oldSize = _renamedFiles.Size();
+ unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair);
+ if (oldSize == _renamedFiles.Size())
+ _renamedFiles[insertIndex].Path = fullProcessedPath;
+ }
+ #endif
+
if (_isSplit)
{
RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
@@ -1004,25 +1275,33 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
_extractMode = true;
break;
};
- return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir,
+
+ return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir),
askExtractMode, _isSplit ? &_position: 0);
+
COM_TRY_END
}
-STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
{
COM_TRY_BEGIN
#ifndef _SFX
if (ExtractToStreamCallback)
- return ExtractToStreamCallback->SetOperationResult7(operationResult, _encrypted);
+ return ExtractToStreamCallback->SetOperationResult7(opRes, BoolToInt(_encrypted));
#endif
#ifndef _SFX
if (_hashStreamWasUsed)
{
- _hashStreamSpec->_hash->Final(_fi.IsDir, _isAltStream, _filePath);
+ _hashStreamSpec->_hash->Final(_item.IsDir,
+ #ifdef SUPPORT_ALT_STREAMS
+ _item.IsAltStream
+ #else
+ false
+ #endif
+ , _item.Path);
_curSize = _hashStreamSpec->GetSize();
_curSizeDefined = true;
_hashStreamSpec->ReleaseStream();
@@ -1069,40 +1348,61 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
GetUnpackSize();
if (_curSizeDefined)
{
- if (_isAltStream)
+ #ifdef SUPPORT_ALT_STREAMS
+ if (_item.IsAltStream)
AltStreams_UnpackSize += _curSize;
else
+ #endif
UnpackSize += _curSize;
}
- if (_fi.IsDir)
+ if (_item.IsDir)
NumFolders++;
- else if (_isAltStream)
+ #ifdef SUPPORT_ALT_STREAMS
+ else if (_item.IsAltStream)
NumAltStreams++;
+ #endif
else
NumFiles++;
if (_extractMode && _fi.AttribDefined)
SetFileAttrib(_diskFilePath, _fi.Attrib);
- RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));
+ RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
return S_OK;
COM_TRY_END
}
-/*
-STDMETHODIMP CArchiveExtractCallback::GetInStream(
- const wchar_t *name, ISequentialInStream **inStream)
+STDMETHODIMP CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)
{
- COM_TRY_BEGIN
- CInFileStream *inFile = new CInFileStream;
- CMyComPtr<ISequentialInStream> inStreamTemp = inFile;
- if (!inFile->Open(_srcDirectoryPrefix + name))
- return ::GetLastError();
- *inStream = inStreamTemp.Detach();
+ if (_folderArchiveExtractCallback2)
+ {
+ bool isEncrypted = false;
+ wchar_t temp[16];
+ UString s2;
+ const wchar_t *s = NULL;
+
+ if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1)
+ {
+ CReadArcItem item;
+ RINOK(_arc->GetItem(index, item));
+ s2 = item.Path;
+ s = s2;
+ RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted));
+ }
+ else
+ {
+ temp[0] = '#';
+ ConvertUInt32ToString(index, temp + 1);
+ s = temp;
+ // if (indexType == NArchive::NEventIndexType::kBlockIndex) {}
+ }
+
+ return _folderArchiveExtractCallback2->ReportExtractResult(opRes, isEncrypted, s);
+ }
+
return S_OK;
- COM_TRY_END
}
-*/
+
STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
{
@@ -1119,8 +1419,8 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
struct CExtrRefSortPair
{
- int Len;
- int Index;
+ unsigned Len;
+ unsigned Index;
int Compare(const CExtrRefSortPair &a) const;
};
@@ -1133,18 +1433,14 @@ int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const
return MyCompare(Index, a.Index);
}
-static int GetNumSlashes(const FChar *s)
+static unsigned GetNumSlashes(const FChar *s)
{
- for (int numSlashes = 0;;)
+ for (unsigned numSlashes = 0;;)
{
FChar c = *s++;
if (c == 0)
return numSlashes;
- if (
- #ifdef _WIN32
- c == FTEXT('\\') ||
- #endif
- c == FTEXT('/'))
+ if (IS_PATH_SEPAR(c))
numSlashes++;
}
}
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index ed41ba8d..561a6e42 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -76,7 +76,7 @@ class CGetProp:
public:
const CArc *Arc;
UInt32 IndexInArc;
- UString Name; // relative path
+ // UString Name; // relative path
MY_UNKNOWN_IMP1(IGetProp)
INTERFACE_IGetProp(;)
@@ -124,9 +124,27 @@ public:
#endif
+#ifdef SUPPORT_ALT_STREAMS
+
+struct CIndexToPathPair
+{
+ UInt32 Index;
+ FString Path;
+
+ CIndexToPathPair(UInt32 index): Index(index) {}
+ CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}
+
+ int Compare(const CIndexToPathPair &pair) const
+ {
+ return MyCompare(Index, pair.Index);
+ }
+};
+
+#endif
+
class CArchiveExtractCallback:
public IArchiveExtractCallback,
- // public IArchiveVolumeExtractCallback,
+ public IArchiveExtractCallbackMessage,
public ICryptoGetTextPassword,
public ICompressProgressInfo,
public CMyUnknownImp
@@ -134,12 +152,15 @@ class CArchiveExtractCallback:
const CArc *_arc;
CExtractNtOptions _ntOptions;
- const NWildcard::CCensorNode *_wildcardCensor;
+ const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
CMyComPtr<ICompressProgressInfo> _compressProgress;
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
- FString _directoryPath;
- FString _directoryPathFull;
+ CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage;
+ CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
+
+ FString _dirPathPrefix;
+ FString _dirPathPrefix_Full;
NExtract::NPathMode::EEnum _pathMode;
NExtract::NOverwriteMode::EEnum _overwriteMode;
@@ -151,11 +172,10 @@ class CArchiveExtractCallback:
#endif
+ CReadArcItem _item;
FString _diskFilePath;
- UString _filePath;
UInt64 _position;
bool _isSplit;
- bool _isAltStream;
bool _extractMode;
@@ -176,8 +196,6 @@ class CArchiveExtractCallback:
bool ATimeDefined;
bool MTimeDefined;
bool AttribDefined;
-
- bool IsDir;
} _fi;
UInt32 _index;
@@ -194,9 +212,13 @@ class CArchiveExtractCallback:
#endif
+ bool _removePartsForAltStreams;
UStringVector _removePathParts;
+
+ #ifndef _SFX
bool _use_baseParentFolder_mode;
UInt32 _baseParentFolder;
+ #endif
bool _stdOutMode;
bool _testMode;
@@ -204,7 +226,9 @@ class CArchiveExtractCallback:
CMyComPtr<ICompressProgressInfo> _localProgress;
UInt64 _packTotal;
- UInt64 _unpTotal;
+
+ UInt64 _progressTotal;
+ bool _progressTotal_Defined;
FStringVector _extractedFolderPaths;
CRecordVector<UInt32> _extractedFolderIndices;
@@ -218,6 +242,7 @@ class CArchiveExtractCallback:
HRESULT GetUnpackSize();
HRESULT SendMessageError(const char *message, const FString &path);
+ HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2);
public:
@@ -230,16 +255,13 @@ public:
UInt64 UnpackSize;
UInt64 AltStreams_UnpackSize;
- MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo)
- // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)
+ MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)
INTERFACE_IArchiveExtractCallback(;)
+ INTERFACE_IArchiveExtractCallbackMessage(;)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
- // IArchiveVolumeExtractCallback
- // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);
-
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
CArchiveExtractCallback();
@@ -274,7 +296,7 @@ public:
IFolderArchiveExtractCallback *extractCallback2,
bool stdOutMode, bool testMode,
const FString &directoryPath,
- const UStringVector &removePathParts,
+ const UStringVector &removePathParts, bool removePartsForAltStreams,
UInt64 packSize);
#ifdef SUPPORT_LINKS
@@ -285,15 +307,23 @@ public:
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
#endif
+ #ifdef SUPPORT_ALT_STREAMS
+ CObjectVector<CIndexToPathPair> _renamedFiles;
+ #endif
+
// call it after Init()
+ #ifndef _SFX
void SetBaseParentFolderIndex(UInt32 indexInArc)
{
- _use_baseParentFolder_mode = true;
_baseParentFolder = indexInArc;
+ _use_baseParentFolder_mode = true;
}
+ #endif
HRESULT SetDirsTimes();
};
+bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
+
#endif
diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp
index dcf6590e..06d2ab80 100644
--- a/CPP/7zip/UI/Common/ArchiveName.cpp
+++ b/CPP/7zip/UI/Common/ArchiveName.cpp
@@ -3,68 +3,76 @@
#include "StdAfx.h"
#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
#include "ExtractingFilePath.h"
#include "ArchiveName.h"
using namespace NWindows;
+using namespace NFile;
-UString CreateArchiveName(const NFile::NFind::CFileInfo fileInfo, bool keepName)
+UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName)
{
- FString resultName = fileInfo.Name;
- if (!fileInfo.IsDir() && !keepName)
+ FString resultName = fi.Name;
+ if (!fi.IsDir() && !keepName)
{
- int dotPos = resultName.ReverseFind(FTEXT('.'));
+ int dotPos = resultName.ReverseFind_Dot();
if (dotPos > 0)
{
FString archiveName2 = resultName.Left(dotPos);
- if (archiveName2.ReverseFind(FTEXT('.')) < 0)
+ if (archiveName2.ReverseFind_Dot() < 0)
resultName = archiveName2;
}
}
- return GetCorrectFsPath(fs2us(resultName));
+ return Get_Correct_FsFile_Name(fs2us(resultName));
}
-static FString CreateArchiveName2(const FString &srcName, bool fromPrev, bool keepName)
+static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName)
{
FString resultName = FTEXT("Archive");
if (fromPrev)
{
FString dirPrefix;
- if (NFile::NDir::GetOnlyDirPrefix(srcName, dirPrefix))
+ if (NDir::GetOnlyDirPrefix(path, dirPrefix))
{
- if (dirPrefix.Len() > 0)
- if (dirPrefix.Back() == FCHAR_PATH_SEPARATOR)
+ if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back()))
+ {
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (NName::IsDriveRootPath_SuperAllowed(dirPrefix))
+ resultName = dirPrefix[dirPrefix.Len() - 3]; // only letter
+ else
+ #endif
{
dirPrefix.DeleteBack();
- NFile::NFind::CFileInfo fileInfo;
- if (fileInfo.Find(dirPrefix))
- resultName = fileInfo.Name;
+ NFind::CFileInfo fi;
+ if (fi.Find(dirPrefix))
+ resultName = fi.Name;
}
+ }
}
}
else
{
- NFile::NFind::CFileInfo fileInfo;
- if (!fileInfo.Find(srcName))
- // return resultName;
- return srcName;
- resultName = fileInfo.Name;
- if (!fileInfo.IsDir() && !keepName)
+ NFind::CFileInfo fi;
+ if (fi.Find(path))
{
- int dotPos = resultName.ReverseFind('.');
- if (dotPos > 0)
+ resultName = fi.Name;
+ if (!fi.IsDir() && !keepName)
{
- FString archiveName2 = resultName.Left(dotPos);
- if (archiveName2.ReverseFind(FTEXT('.')) < 0)
- resultName = archiveName2;
+ int dotPos = resultName.ReverseFind_Dot();
+ if (dotPos > 0)
+ {
+ FString name2 = resultName.Left(dotPos);
+ if (name2.ReverseFind_Dot() < 0)
+ resultName = name2;
+ }
}
}
}
return resultName;
}
-UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)
+UString CreateArchiveName(const UString &path, bool fromPrev, bool keepName)
{
- return GetCorrectFsPath(fs2us(CreateArchiveName2(us2fs(srcName), fromPrev, keepName)));
+ return Get_Correct_FsFile_Name(fs2us(CreateArchiveName2(us2fs(path), fromPrev, keepName)));
}
diff --git a/CPP/7zip/UI/Common/ArchiveName.h b/CPP/7zip/UI/Common/ArchiveName.h
index 99ba086c..ec2f1e8d 100644
--- a/CPP/7zip/UI/Common/ArchiveName.h
+++ b/CPP/7zip/UI/Common/ArchiveName.h
@@ -7,7 +7,7 @@
#include "../../../Windows/FileFind.h"
-UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);
-UString CreateArchiveName(const NWindows::NFile::NFind::CFileInfo fileInfo, bool keepName);
+UString CreateArchiveName(const UString &path, bool fromPrev, bool keepName);
+UString CreateArchiveName(const NWindows::NFile::NFind::CFileInfo &fileInfo, bool keepName);
#endif
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index e698f56f..2ed68e80 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -119,6 +119,7 @@ STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
}
if (!Callback)
return E_NOTIMPL;
+ PasswordWasAsked = true;
return Callback->Open_CryptoGetTextPassword(password);
COM_TRY_END
}
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
index 8627de00..afa03766 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -20,9 +20,9 @@
#define INTERFACE_IOpenCallbackUI_Crypto(x) \
virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \
- virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; \
- virtual bool Open_WasPasswordAsked() x; \
- virtual void Open_ClearPasswordWasAskedFlag() x; \
+ /* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; */ \
+ /* virtual bool Open_WasPasswordAsked() x; */ \
+ /* virtual void Open_Clear_PasswordWasAsked_Flag() x; */ \
#endif
@@ -30,6 +30,7 @@
virtual HRESULT Open_CheckBreak() x; \
virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \
virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \
+ virtual HRESULT Open_Finished() x; \
INTERFACE_IOpenCallbackUI_Crypto(x)
struct IOpenCallbackUI
@@ -85,6 +86,8 @@ public:
UStringVector FileNames;
CBoolVector FileNames_WasUsed;
CRecordVector<UInt64> FileSizes;
+
+ bool PasswordWasAsked;
IOpenCallbackUI *Callback;
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
@@ -101,6 +104,7 @@ public:
FileSizes.Clear();
_subArchiveMode = false;
// TotalSize = 0;
+ PasswordWasAsked = false;
}
bool SetSecondFileInfo(CFSTR newName)
{
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
index 8cb65755..c38b132c 100644
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -30,7 +30,7 @@
#include "../../../../C/Alloc.h"
#include "../../../../C/CpuArch.h"
-#if !defined(_7ZIP_ST) || defined(_WIN32)
+#if defined(_WIN32)
#include "../../../Windows/System.h"
#endif
@@ -212,7 +212,7 @@ STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processed
for (UInt32 i = 0; i < size; i++)
((Byte *)data)[i] = Data[Pos + i];
Pos += size;
- if(processedSize != NULL)
+ if (processedSize)
*processedSize = size;
return S_OK;
}
@@ -224,7 +224,7 @@ class CBenchmarkOutStream:
{
// bool _overflow;
public:
- UInt32 Pos;
+ size_t Pos;
bool RealCopy;
bool CalcCrc;
UInt32 Crc;
@@ -247,12 +247,15 @@ STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *p
size_t curSize = BufferSize - Pos;
if (curSize > size)
curSize = size;
- if (RealCopy)
- memcpy(Buffer + Pos, data, curSize);
- if (CalcCrc)
- Crc = CrcUpdate(Crc, data, curSize);
- Pos += (UInt32)curSize;
- if(processedSize != NULL)
+ if (curSize != 0)
+ {
+ if (RealCopy)
+ memcpy(Buffer + Pos, data, curSize);
+ if (CalcCrc)
+ Crc = CrcUpdate(Crc, data, curSize);
+ Pos += curSize;
+ }
+ if (processedSize)
*processedSize = (UInt32)curSize;
if (curSize != size)
{
@@ -280,7 +283,7 @@ STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *process
{
if (CalcCrc)
Crc = CrcUpdate(Crc, data, size);
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = size;
return S_OK;
}
@@ -616,6 +619,7 @@ struct CEncoderInfo
CBenchProgressInfo *progressInfoSpec[2];
CMyComPtr<ICompressProgressInfo> progressInfo[2];
UInt64 NumIterations;
+
#ifdef USE_ALLOCA
size_t AllocaSize;
#endif
@@ -630,10 +634,11 @@ struct CEncoderInfo
{
CEncoderInfo *Encoder;
UInt32 DecoderIndex;
+ bool CallbackMode;
+
#ifdef USE_ALLOCA
size_t AllocaSize;
#endif
- bool CallbackMode;
};
CDecoderInfo decodersInfo[2];
@@ -647,7 +652,7 @@ struct CEncoderInfo
IBenchPrintCallback *printCallback;
UInt32 crc;
UInt32 kBufferSize;
- UInt32 compressedSize;
+ size_t compressedSize;
CBenchRandomGenerator rg;
CBenchBuffer rgCopy; // it must be 16-byte aligned !!!
CBenchmarkOutStream *propStreamSpec;
@@ -671,6 +676,7 @@ struct CEncoderInfo
outStreamSpec(0), callback(0), printCallback(0), propStreamSpec(0) {}
#ifndef _7ZIP_ST
+
static THREAD_FUNC_DECL EncodeThreadFunction(void *param)
{
HRESULT res;
@@ -680,6 +686,7 @@ struct CEncoderInfo
#ifdef USE_ALLOCA
alloca(encoder->AllocaSize);
#endif
+
res = encoder->Encode();
encoder->Results[0] = res;
}
@@ -691,12 +698,15 @@ struct CEncoderInfo
encoder->progressInfoSpec[0]->Status->SetResult(res);
return 0;
}
+
static THREAD_FUNC_DECL DecodeThreadFunction(void *param)
{
CDecoderInfo *decoder = (CDecoderInfo *)param;
+
#ifdef USE_ALLOCA
alloca(decoder->AllocaSize);
#endif
+
CEncoderInfo *encoder = decoder->Encoder;
encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex);
return 0;
@@ -707,7 +717,7 @@ struct CEncoderInfo
return thread[0].Create(EncodeThreadFunction, this);
}
- HRESULT CreateDecoderThread(int index, bool callbackMode
+ HRESULT CreateDecoderThread(unsigned index, bool callbackMode
#ifdef USE_ALLOCA
, size_t allocaSize
#endif
@@ -716,12 +726,15 @@ struct CEncoderInfo
CDecoderInfo &decoder = decodersInfo[index];
decoder.DecoderIndex = index;
decoder.Encoder = this;
+
#ifdef USE_ALLOCA
decoder.AllocaSize = allocaSize;
#endif
+
decoder.CallbackMode = callbackMode;
return thread[index].Create(DecodeThreadFunction, &decoder);
}
+
#endif
};
@@ -945,7 +958,7 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)
if (setDecProps)
{
- RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));
+ RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, (UInt32)propStreamSpec->Pos));
}
{
@@ -984,7 +997,7 @@ HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)
return E_FAIL;
memcpy(rgCopy.Buffer, outStreamSpec->Buffer, compressedSize);
_decoderFilter->Init();
- _decoderFilter->Filter(rgCopy.Buffer, compressedSize);
+ _decoderFilter->Filter(rgCopy.Buffer, (UInt32)compressedSize);
RINOK(WriteStream(crcOutStream, rgCopy.Buffer, rg.BufferSize));
}
else
@@ -1021,23 +1034,32 @@ static UInt64 GetNumIterations(UInt64 numCommands, UInt64 complexInCommands)
static HRESULT MethodBench(
DECL_EXTERNAL_CODECS_LOC_VARS
UInt64 complexInCommands,
- bool oldLzmaBenchMode,
- UInt32 numThreads,
+ bool
+ #ifndef _7ZIP_ST
+ oldLzmaBenchMode
+ #endif
+ ,
+ UInt32
+ #ifndef _7ZIP_ST
+ numThreads
+ #endif
+ ,
const COneMethodInfo &method2,
UInt32 uncompressedDataSize,
unsigned generateDictBits,
+
IBenchPrintCallback *printCallback,
IBenchCallback *callback,
CBenchProps *benchProps)
{
COneMethodInfo method = method2;
UInt64 methodId;
- UInt32 numInStreams, numOutStreams;
+ UInt32 numStreams;
if (!FindMethod(
EXTERNAL_CODECS_LOC_VARS
- method.MethodName, methodId, numInStreams, numOutStreams))
+ method.MethodName, methodId, numStreams))
return E_NOTIMPL;
- if (numInStreams != 1 || numOutStreams != 1)
+ if (numStreams != 1)
return E_INVALIDARG;
UInt32 numEncoderThreads = 1;
@@ -1051,7 +1073,7 @@ static HRESULT MethodBench(
bool fixedNumber;
UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(fixedNumber);
if (!fixedNumber && numThreads == 1)
- method.AddNumThreadsProp(1);
+ method.AddProp_NumThreads(1);
if (numThreads > 1 && numLzmaThreads > 1)
{
numEncoderThreads = numThreads / 2;
@@ -1070,12 +1092,13 @@ static HRESULT MethodBench(
encoder.callback = (i == 0) ? callback : 0;
encoder.printCallback = printCallback;
- CMyComPtr<ICompressCoder2> coder2;
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId,
- encoder._encoderFilter, encoder._encoder, coder2, true, false));
- if (!encoder._encoder && !encoder._encoderFilter)
- return E_NOTIMPL;
- // encoder._encoderFilter.Release(); // we can disable filter to check the speed of FilterCoder.
+ {
+ CCreatedCoder cod;
+ RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, true, encoder._encoderFilter, cod));
+ encoder._encoder = cod.Coder;
+ if (!encoder._encoder && !encoder._encoderFilter)
+ return E_NOTIMPL;
+ }
encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30 ;
encoder.CheckCrc_Dec = (benchProps->DecComplexCompr + benchProps->DecComplexUnc) > 30 ;
@@ -1086,10 +1109,10 @@ static HRESULT MethodBench(
for (UInt32 j = 0; j < numSubDecoderThreads; j++)
{
- CMyComPtr<ICompressCoder2> coder2de;
+ CCreatedCoder cod;
CMyComPtr<ICompressCoder> &decoder = encoder._decoders[j];
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId,
- encoder._decoderFilter, decoder, coder2de, false, false));
+ RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodId, false, encoder._decoderFilter, cod));
+ decoder = cod.Coder;
if (!encoder._decoderFilter && !decoder)
return E_NOTIMPL;
}
@@ -1135,6 +1158,7 @@ static HRESULT MethodBench(
#ifdef USE_ALLOCA
encoder.AllocaSize = (i * 16 * 21) & 0x7FF;
#endif
+
RINOK(encoder.CreateEncoderThread())
}
else
@@ -1208,6 +1232,7 @@ static HRESULT MethodBench(
RINOK(encoder.Decode(0));
}
}
+
#ifndef _7ZIP_ST
HRESULT res = S_OK;
if (numDecoderThreads > 1)
@@ -1221,8 +1246,10 @@ static HRESULT MethodBench(
}
RINOK(res);
#endif
+
RINOK(status.Res);
encoders[0].progressInfoSpec[0]->SetFinishTime(info);
+
#ifndef _7ZIP_ST
#ifdef UNDER_CE
if (numDecoderThreads > 1)
@@ -1235,6 +1262,7 @@ static HRESULT MethodBench(
}
#endif
#endif
+
info.UnpackSize = 0;
info.PackSize = 0;
info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;
@@ -1246,6 +1274,7 @@ static HRESULT MethodBench(
}
RINOK(callback->SetDecodeResult(info, false));
RINOK(callback->SetDecodeResult(info, true));
+
return S_OK;
}
@@ -1301,7 +1330,6 @@ static HRESULT CrcBig(const void *data, UInt32 size, UInt64 numIterations,
sum ^= GetUi32(hash + j);
if (checkSum && sum != *checkSum)
{
- // printf(" %08X ", sum);
return S_FALSE;
}
}
@@ -1316,6 +1344,8 @@ UInt32 g_BenchCpuFreqTemp = 1;
#define YY7 YY5 YY5 YY5 YY5
static const UInt32 kNumFreqCommands = 128;
+EXTERN_C_BEGIN
+
static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val)
{
for (UInt32 i = 0; i < num; i++)
@@ -1325,6 +1355,9 @@ static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val)
return sum;
}
+EXTERN_C_END
+
+
#ifndef _7ZIP_ST
struct CFreqInfo
@@ -1392,6 +1425,10 @@ struct CCrcInfo
CMyComPtr<IHasher> Hasher;
HRESULT Res;
+ #ifdef USE_ALLOCA
+ size_t AllocaSize;
+ #endif
+
void Wait()
{
Thread.Wait();
@@ -1402,6 +1439,11 @@ struct CCrcInfo
static THREAD_FUNC_DECL CrcThreadFunction(void *param)
{
CCrcInfo *p = (CCrcInfo *)param;
+
+ #ifdef USE_ALLOCA
+ alloca(p->AllocaSize);
+ #endif
+
p->Res = CrcBig(p->Data, p->Size, p->NumIterations,
p->CheckSumDefined ? &p->CheckSum : NULL, p->Hasher,
p->Callback);
@@ -1475,6 +1517,7 @@ bool CrcInternalTest()
struct CBenchMethod
{
+ unsigned Weight;
unsigned DictBits;
UInt32 EncComplex;
UInt32 DecComplexCompr;
@@ -1484,27 +1527,33 @@ struct CBenchMethod
static const CBenchMethod g_Bench[] =
{
- { 17, 357, 145, 20, "LZMA:x1" },
- { 24, 1220, 145, 20, "LZMA:x5:mt1" },
- { 24, 1220, 145, 20, "LZMA:x5:mt2" },
- { 16, 124, 40, 14, "Deflate:x1" },
- { 16, 376, 40, 14, "Deflate:x5" },
- { 16, 1082, 40, 14, "Deflate:x7" },
- { 17, 422, 40, 14, "Deflate64:x5" },
- { 15, 590, 69, 69, "BZip2:x1" },
- { 19, 815, 122, 122, "BZip2:x5" },
- { 19, 815, 122, 122, "BZip2:x5:mt2" },
- { 19, 2530, 122, 122, "BZip2:x7" },
- { 18, 1010, 0, 1150, "PPMD:x1" },
- { 22, 1655, 0, 1830, "PPMD:x5" },
- { 0, 6, 0, 6, "Delta:4" },
- { 0, 4, 0, 4, "BCJ" },
- { 0, 24, 0, 24, "AES256CBC:1" },
- { 0, 8, 0, 2, "AES256CBC:2" }
+ { 40, 17, 357, 145, 20, "LZMA:x1" },
+ { 80, 24, 1220, 145, 20, "LZMA:x5:mt1" },
+ { 80, 24, 1220, 145, 20, "LZMA:x5:mt2" },
+
+ { 10, 16, 124, 40, 14, "Deflate:x1" },
+ { 20, 16, 376, 40, 14, "Deflate:x5" },
+ { 10, 16, 1082, 40, 14, "Deflate:x7" },
+ { 10, 17, 422, 40, 14, "Deflate64:x5" },
+
+ { 10, 15, 590, 69, 69, "BZip2:x1" },
+ { 20, 19, 815, 122, 122, "BZip2:x5" },
+ { 10, 19, 815, 122, 122, "BZip2:x5:mt2" },
+ { 10, 19, 2530, 122, 122, "BZip2:x7" },
+
+ { 10, 18, 1010, 0, 1150, "PPMD:x1" },
+ { 10, 22, 1655, 0, 1830, "PPMD:x5" },
+
+ { 2, 0, 6, 0, 6, "Delta:4" },
+ { 2, 0, 4, 0, 4, "BCJ" },
+
+ { 10, 0, 24, 0, 24, "AES256CBC:1" },
+ { 2, 0, 8, 0, 2, "AES256CBC:2" }
};
struct CBenchHash
{
+ unsigned Weight;
UInt32 Complex;
UInt32 CheckSum;
const char *Name;
@@ -1512,26 +1561,32 @@ struct CBenchHash
static const CBenchHash g_Hash[] =
{
- { 558, 0x8F8FEDAB, "CRC32:4" },
- { 339, 0x8F8FEDAB, "CRC32:8" },
- { 512, 0xDF1C17CC, "CRC64" },
- { 11900, 0x2D79FF2E, "SHA256" },
- { 5230, 0x4C25132B, "SHA1" }
+ { 1, 1820, 0x8F8FEDAB, "CRC32:1" },
+ { 10, 558, 0x8F8FEDAB, "CRC32:4" },
+ { 10, 339, 0x8F8FEDAB, "CRC32:8" },
+ { 10, 512, 0xDF1C17CC, "CRC64" },
+ { 10, 5100, 0x2D79FF2E, "SHA256" },
+ { 10, 2340, 0x4C25132B, "SHA1" }
};
struct CTotalBenchRes
{
- UInt64 NumIterations;
+ // UInt64 NumIterations1; // for Usage
+ UInt64 NumIterations2; // for Rating / RPU
+
UInt64 Rating;
UInt64 Usage;
UInt64 RPU;
- void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }
+
+ void Init() { /* NumIterations1 = 0; */ NumIterations2 = 0; Rating = 0; Usage = 0; RPU = 0; }
+
void SetSum(const CTotalBenchRes &r1, const CTotalBenchRes &r2)
{
Rating = (r1.Rating + r2.Rating);
Usage = (r1.Usage + r2.Usage);
RPU = (r1.RPU + r2.RPU);
- NumIterations = (r1.NumIterations + r2.NumIterations);
+ // NumIterations1 = (r1.NumIterations1 + r2.NumIterations1);
+ NumIterations2 = (r1.NumIterations2 + r2.NumIterations2);
}
};
@@ -1580,7 +1635,7 @@ static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, in
PrintNumber(f, (val * 100 + divider / 2) / divider, size);
}
-static void PrintChars(IBenchPrintCallback &f, char c, int size)
+static void PrintChars(IBenchPrintCallback &f, char c, unsigned size)
{
char s[256];
memset(s, (Byte)c, size);
@@ -1588,7 +1643,7 @@ static void PrintChars(IBenchPrintCallback &f, char c, int size)
f.Print(s);
}
-static void PrintSpaces(IBenchPrintCallback &f, int size)
+static void PrintSpaces(IBenchPrintCallback &f, unsigned size)
{
PrintChars(f, ' ', size);
}
@@ -1613,7 +1668,12 @@ static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt6
}
}
-static void PrintResults(IBenchPrintCallback *f, const CBenchInfo &info, UInt64 rating, bool showFreq, UInt64 cpuFreq, CTotalBenchRes *res)
+static void PrintResults(IBenchPrintCallback *f,
+ const CBenchInfo &info,
+ unsigned weight,
+ UInt64 rating,
+ bool showFreq, UInt64 cpuFreq,
+ CTotalBenchRes *res)
{
UInt64 speed = info.GetSpeed(info.UnpackSize * info.NumIterations);
if (f)
@@ -1632,20 +1692,20 @@ static void PrintResults(IBenchPrintCallback *f, const CBenchInfo &info, UInt64
if (res)
{
- res->NumIterations++;
- res->RPU += rpu;
- res->Rating += rating;
- res->Usage += usage;
+ // res->NumIterations1++;
+ res->NumIterations2 += weight;
+ res->RPU += (rpu * weight);
+ res->Rating += (rating * weight);
+ res->Usage += (usage * weight);
}
}
static void PrintTotals(IBenchPrintCallback &f, bool showFreq, UInt64 cpuFreq, const CTotalBenchRes &res)
{
PrintSpaces(f, 1 + kFieldSize_Speed);
- UInt64 numIterations = res.NumIterations;
- if (numIterations == 0)
- numIterations = 1;
- PrintResults(f, res.Usage / numIterations, res.RPU / numIterations, res.Rating / numIterations, showFreq, cpuFreq);
+ // UInt64 numIterations1 = res.NumIterations1; if (numIterations1 == 0) numIterations1 = 1;
+ UInt64 numIterations2 = res.NumIterations2; if (numIterations2 == 0) numIterations2 = 1;
+ PrintResults(f, res.Usage / numIterations2, res.RPU / numIterations2, res.Rating / numIterations2, showFreq, cpuFreq);
}
static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)
@@ -1673,7 +1733,17 @@ struct CBenchCallbackToPrint: public IBenchCallback
bool ShowFreq;
UInt64 CpuFreq;
- CBenchCallbackToPrint(): Use2Columns(false), NameFieldSize(0), ShowFreq(false), CpuFreq(0) {}
+ unsigned EncodeWeight;
+ unsigned DecodeWeight;
+
+ CBenchCallbackToPrint():
+ Use2Columns(false),
+ NameFieldSize(0),
+ ShowFreq(false),
+ CpuFreq(0),
+ EncodeWeight(1),
+ DecodeWeight(1)
+ {}
void Init() { EncodeRes.Init(); DecodeRes.Init(); }
void Print(const char *s);
@@ -1697,7 +1767,11 @@ HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool fina
if (final)
{
UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations);
- PrintResults(_file, info, rating, ShowFreq, CpuFreq, &EncodeRes);
+ PrintResults(_file, info,
+ EncodeWeight, rating,
+ ShowFreq, CpuFreq, &EncodeRes);
+ if (!Use2Columns)
+ _file->NewLine();
}
return S_OK;
}
@@ -1713,15 +1787,14 @@ HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool fina
if (Use2Columns)
_file->Print(kSep);
else
- {
- _file->NewLine();
PrintSpaces(*_file, NameFieldSize);
- }
CBenchInfo info2 = info;
info2.UnpackSize *= info2.NumIterations;
info2.PackSize *= info2.NumIterations;
info2.NumIterations = 1;
- PrintResults(_file, info2, rating, ShowFreq, CpuFreq, &DecodeRes);
+ PrintResults(_file, info2,
+ DecodeWeight, rating,
+ ShowFreq, CpuFreq, &DecodeRes);
}
return S_OK;
}
@@ -1759,7 +1832,7 @@ static HRESULT TotalBench(
{
for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++)
{
- CBenchMethod bench = g_Bench[i];
+ const CBenchMethod &bench = g_Bench[i];
PrintLeft(*callback->_file, bench.Name, kFieldSize_Name);
callback->BenchProps.DecComplexUnc = bench.DecComplexUnc;
callback->BenchProps.DecComplexCompr = bench.DecComplexCompr;
@@ -1767,12 +1840,15 @@ static HRESULT TotalBench(
COneMethodInfo method;
NCOM::CPropVariant propVariant;
propVariant = bench.Name;
- RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant));
+ RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant));
UInt32 unpackSize2 = unpackSize;
if (!forceUnpackSize && bench.DictBits == 0)
unpackSize2 = kFilterUnpackSize;
+ callback->EncodeWeight = bench.Weight;
+ callback->DecodeWeight = bench.Weight;
+
HRESULT res = MethodBench(
EXTERNAL_CODECS_LOC_VARS
complexInCommands,
@@ -1874,7 +1950,10 @@ static HRESULT FreqBench(
UInt64 numCommands = (UInt64)numIterations * bufferSize * numThreads * complexity;
UInt64 rating = info.GetSpeed(numCommands);
cpuFreq = rating / numThreads;
- PrintResults(_file, info, rating, showFreq, showFreq ? cpuFreq : 0, NULL);
+ PrintResults(_file, info,
+ 0, // weight
+ rating,
+ showFreq, showFreq ? cpuFreq : 0, NULL);
}
RINOK(_file->CheckBreak());
}
@@ -1889,7 +1968,7 @@ static HRESULT CrcBench(
UInt64 complexInCommands,
UInt32 numThreads, UInt32 bufferSize,
UInt64 &speed,
- UInt32 complexity,
+ UInt32 complexity, unsigned benchWeight,
const UInt32 *checkSum,
const COneMethodInfo &method,
IBenchPrintCallback *_file,
@@ -1903,7 +1982,7 @@ static HRESULT CrcBench(
numThreads = 1;
#endif
- UString methodName = method.MethodName;
+ AString methodName = method.MethodName;
// methodName.RemoveChar(L'-');
CMethodId hashID;
if (!FindHashMethod(
@@ -1932,11 +2011,12 @@ static HRESULT CrcBench(
if (numThreads > 1)
{
threads.Items = new CCrcInfo[numThreads];
+
UInt32 i;
for (i = 0; i < numThreads; i++)
{
CCrcInfo &info = threads.Items[i];
- UString name;
+ AString name;
RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, info.Hasher));
if (!info.Hasher)
return E_NOTIMPL;
@@ -1960,8 +2040,14 @@ static HRESULT CrcBench(
info.CheckSum = *checkSum;
info.CheckSumDefined = (checkSum && (i == 0));
}
+
+ #ifdef USE_ALLOCA
+ info.AllocaSize = (i * 16 * 21) & 0x7FF;
+ #endif
}
+
progressInfoSpec.SetStartTime();
+
for (i = 0; i < numThreads; i++)
{
CCrcInfo &info = threads.Items[i];
@@ -1980,7 +2066,7 @@ static HRESULT CrcBench(
/* UInt32 crc = */ RandGenCrc(buf, bufferSize, RG);
progressInfoSpec.SetStartTime();
CMyComPtr<IHasher> hasher;
- UString name;
+ AString name;
RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher));
if (!hasher)
return E_NOTIMPL;
@@ -1993,6 +2079,7 @@ static HRESULT CrcBench(
}
RINOK(CrcBig(buf, bufferSize, numIterations, checkSum, hasher, _file));
}
+
CBenchInfo info;
progressInfoSpec.SetFinishTime(info);
@@ -2007,7 +2094,9 @@ static HRESULT CrcBench(
{
UInt64 numCommands = unpSizeThreads * complexity / 256;
UInt64 rating = info.GetSpeed(numCommands);
- PrintResults(_file, info, rating, showFreq, cpuFreq, encodeRes);
+ PrintResults(_file, info,
+ benchWeight, rating,
+ showFreq, cpuFreq, encodeRes);
}
RINOK(_file->CheckBreak());
}
@@ -2036,7 +2125,7 @@ static HRESULT TotalBench_Hash(
COneMethodInfo method;
NCOM::CPropVariant propVariant;
propVariant = bench.Name;
- RINOK(method.ParseMethodFromPROPVARIANT(L"", propVariant));
+ RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant));
UInt64 speed;
HRESULT res = CrcBench(
@@ -2044,7 +2133,8 @@ static HRESULT TotalBench_Hash(
complexInCommands,
numThreads, bufSize,
speed,
- bench.Complex, &bench.CheckSum, method,
+ bench.Complex, bench.Weight,
+ &bench.CheckSum, method,
printCallback, encodeRes, showFreq, cpuFreq);
if (res == E_NOTIMPL)
{
@@ -2087,19 +2177,103 @@ static UInt32 GetNumThreadsNext(unsigned i, UInt32 numThreads)
return (num <= numThreads) ? num : numThreads;
}
-static bool AreSameMethodNames(const char *fullName, const wchar_t *shortName)
+static bool AreSameMethodNames(const char *fullName, const char *shortName)
{
for (;;)
{
- wchar_t c2 = *shortName++;
+ char c2 = *shortName++;
if (c2 == 0)
return true;
char c1 = *fullName++;
- if ((unsigned char)MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
+ if (MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
return false;
}
}
+
+#ifdef MY_CPU_X86_OR_AMD64
+
+static void PrintCpuChars(AString &s, UInt32 v)
+{
+ for (int j = 0; j < 4; j++)
+ {
+ Byte b = (Byte)(v & 0xFF);
+ v >>= 8;
+ if (b == 0)
+ break;
+ s += (char)b;
+ }
+}
+
+static void x86cpuid_to_String(const Cx86cpuid &c, AString &s)
+{
+ s.Empty();
+
+ UInt32 maxFunc2 = 0;
+ UInt32 t[3];
+
+ MyCPUID(0x80000000, &maxFunc2, &t[0], &t[1], &t[2]);
+
+ bool fullNameIsAvail = (maxFunc2 >= 0x80000004);
+
+ if (!fullNameIsAvail)
+ {
+ for (int i = 0; i < 3; i++)
+ PrintCpuChars(s, c.vendor[i]);
+ }
+ else
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ UInt32 c[4] = { 0 };
+ MyCPUID(0x80000002 + i, &c[0], &c[1], &c[2], &c[3]);
+ for (int j = 0; j < 4; j++)
+ PrintCpuChars(s, c[j]);
+ }
+ }
+
+ s.Add_Space_if_NotEmpty();
+ {
+ char temp[32];
+ ConvertUInt32ToHex(c.ver, temp);
+ s += '(';
+ s += temp;
+ s += ')';
+ }
+}
+
+#endif
+
+
+void GetCpuName(AString &s)
+{
+ s.Empty();
+
+ #ifdef MY_CPU_X86_OR_AMD64
+ {
+ Cx86cpuid cpuid;
+ if (x86cpuid_CheckAndRead(&cpuid))
+ {
+ x86cpuid_to_String(cpuid, s);
+ return;
+ }
+ #ifdef MY_CPU_AMD64
+ s = "x64";
+ #else
+ s = "x86";
+ #endif
+ }
+ #else
+
+ #ifdef MY_CPU_LE
+ s = "LE";
+ #elif defined(MY_CPU_BE)
+ s = "BE";
+ #endif
+
+ #endif
+}
+
HRESULT Bench(
DECL_EXTERNAL_CODECS_LOC_VARS
IBenchPrintCallback *printCallback,
@@ -2113,16 +2287,21 @@ HRESULT Bench(
UInt32 numCPUs = 1;
UInt64 ramSize = (UInt64)512 << 20;
+
#ifndef _7ZIP_ST
numCPUs = NSystem::GetNumberOfProcessors();
#endif
- #if !defined(_7ZIP_ST) || defined(_WIN32)
+
+ #if defined(_WIN32)
ramSize = NSystem::GetRamSize();
#endif
- UInt32 numThreads = numCPUs;
+
+ UInt32 numThreadsSpecified = numCPUs;
UInt32 testTime = kComplexInSeconds;
+ bool multiThreadTests = false;
+
COneMethodInfo method;
unsigned i;
for (i = 0; i < props.Size(); i++)
@@ -2138,10 +2317,24 @@ HRESULT Bench(
RINOK(ParsePropToUInt32(L"", propVariant, testTime));
continue;
}
- if (name.IsPrefixedBy(L"mt"))
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
+ UString s = name.Ptr(2);
+ if (s == L"*")
+ {
+ multiThreadTests = true;
+ continue;
+ }
+ if (s.IsEmpty() && propVariant.vt == VT_BSTR)
+ {
+ if (wcscmp(propVariant.bstrVal, L"*") == 0)
+ {
+ multiThreadTests = true;
+ continue;
+ }
+ }
#ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads));
+ RINOK(ParseMtProp(s, propVariant, numCPUs, numThreadsSpecified));
#endif
continue;
}
@@ -2150,17 +2343,28 @@ HRESULT Bench(
if (printCallback)
{
+ AString s;
+ GetCpuName(s);
+ printCallback->Print(s);
+ printCallback->NewLine();
+ }
+
+ if (printCallback)
+ {
printCallback->Print("CPU Freq:");
}
UInt64 complexInCommands = kComplexInCommands;
- if (printCallback)
+ if (printCallback /* || benchCallback */)
{
UInt64 numMilCommands = (1 << 6);
for (int jj = 0;; jj++)
{
+ if (printCallback)
+ RINOK(printCallback->CheckBreak());
+
UInt64 start = ::GetTimeCount();
UInt32 sum = (UInt32)start;
sum = CountCpuFreq(sum, (UInt32)(numMilCommands * 1000000 / kNumFreqCommands), g_BenchCpuFreqTemp);
@@ -2168,12 +2372,18 @@ HRESULT Bench(
if (start == 0)
start = 1;
UInt64 freq = GetFreq();
- UInt64 mipsVal = numMilCommands * freq / start;
+ UInt64 mips = numMilCommands * freq / start;
if (printCallback)
- PrintNumber(*printCallback, mipsVal, 5 + ((sum >> 31) & 1));
+ PrintNumber(*printCallback, mips, 5 + ((sum == 0xF1541213) ? 1 : 0));
+
+ /*
+ if (benchCallback)
+ benchCallback->AddCpuFreq(mips);
+ */
+
if (jj >= 3)
{
- SetComplexCommands(testTime, mipsVal * 1000000, complexInCommands);
+ SetComplexCommands(testTime, mips * 1000000, complexInCommands);
if (jj >= 8 || start >= freq)
break;
// break; // change it
@@ -2181,6 +2391,7 @@ HRESULT Bench(
}
}
}
+
if (printCallback)
{
printCallback->NewLine();
@@ -2188,14 +2399,14 @@ HRESULT Bench(
PrintRequirements(*printCallback, "size: ", ramSize, "CPU hardware threads:", numCPUs);
}
- if (numThreads < 1 || numThreads > kNumThreadsMax)
+ if (numThreadsSpecified < 1 || numThreadsSpecified > kNumThreadsMax)
return E_INVALIDARG;
UInt32 dict;
bool dictIsDefined = method.Get_DicSize(dict);
if (method.MethodName.IsEmpty())
- method.MethodName = L"LZMA";
+ method.MethodName = "LZMA";
if (benchCallback)
{
@@ -2206,16 +2417,17 @@ HRESULT Bench(
return MethodBench(
EXTERNAL_CODECS_LOC_VARS
complexInCommands,
- true, numThreads,
+ true, numThreadsSpecified,
method, uncompressedDataSize,
kOldLzmaDictBits, printCallback, benchCallback, &benchProps);
}
- UString methodName = method.MethodName;
- if (methodName.IsEqualToNoCase(L"CRC"))
- methodName = L"crc32";
+ AString methodName = method.MethodName;
+ if (methodName.IsEqualTo_Ascii_NoCase("CRC"))
+ methodName = "crc32";
method.MethodName = methodName;
CMethodId hashID;
+
if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, hashID))
{
if (!printCallback)
@@ -2232,11 +2444,20 @@ HRESULT Bench(
for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++)
{
const CBenchHash &h = g_Hash[i];
- if (AreSameMethodNames(h.Name, methodName))
+ AString s = h.Name;
+ AString hProp;
+ int propPos = s.Find(':');
+ if (propPos >= 0)
+ {
+ hProp = s.Ptr(propPos + 1);
+ s.DeleteFrom(propPos);
+ }
+
+ if (AreSameMethodNames(s, methodName))
{
complexity = h.Complex;
checkSum = &h.CheckSum;
- if (strcmp(h.Name, "CRC32:4") != 0)
+ if (method.PropsString.IsEqualTo_Ascii_NoCase(hProp))
break;
}
}
@@ -2248,10 +2469,10 @@ HRESULT Bench(
unsigned numThreadsTests = 0;
for (;;)
{
- UInt32 t = GetNumThreadsNext(numThreadsTests, numThreads);
+ UInt32 t = GetNumThreadsNext(numThreadsTests, numThreadsSpecified);
PrintNumber(f, t, kFieldSize_CrcSpeed);
numThreadsTests++;
- if (t >= numThreads)
+ if (t >= numThreadsSpecified)
break;
}
f.NewLine();
@@ -2272,7 +2493,7 @@ HRESULT Bench(
break;
char s[16];
ConvertUInt32ToString(pow, s);
- int pos = MyStringLen(s);
+ unsigned pos = MyStringLen(s);
s[pos++] = ':';
s[pos++] = ' ';
s[pos] = 0;
@@ -2281,10 +2502,12 @@ HRESULT Bench(
for (unsigned ti = 0; ti < numThreadsTests; ti++)
{
RINOK(f.CheckBreak());
- UInt32 t = GetNumThreadsNext(ti, numThreads);
+ UInt32 t = GetNumThreadsNext(ti, numThreadsSpecified);
UInt64 speed = 0;
RINOK(CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands,
- t, bufSize, speed, complexity,
+ t, bufSize, speed,
+ complexity,
+ 1, // benchWeight,
(pow == kNumHashDictBits) ? checkSum : NULL, method, NULL, NULL, false, 0));
PrintNumber(f, (speed >> 20), kFieldSize_CrcSpeed);
speedTotals.Values[ti] += speed;
@@ -2308,23 +2531,60 @@ HRESULT Bench(
bool use2Columns = false;
+ bool totalBenchMode = (method.MethodName.IsEqualTo_Ascii_NoCase("*"));
+
+ // ---------- Threads loop ----------
+ for (unsigned threadsPassIndex = 0; threadsPassIndex < 3; threadsPassIndex++)
+ {
+
+ UInt32 numThreads = numThreadsSpecified;
+
+ if (!multiThreadTests)
+ {
+ if (threadsPassIndex != 0)
+ break;
+ }
+ else
+ {
+ numThreads = 1;
+ if (threadsPassIndex != 0)
+ {
+ if (numCPUs < 2)
+ break;
+ numThreads = numCPUs;
+ if (threadsPassIndex == 1)
+ {
+ if (numCPUs >= 4)
+ numThreads = numCPUs / 2;
+ }
+ else if (numCPUs < 4)
+ break;
+ }
+ }
+
CBenchCallbackToPrint callback;
callback.Init();
callback._file = printCallback;
+
+ IBenchPrintCallback &f = *printCallback;
+
+ if (threadsPassIndex > 0)
+ {
+ f.NewLine();
+ f.NewLine();
+ }
if (!dictIsDefined)
{
- int dicSizeLog;
- for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
+ unsigned dicSizeLog = (totalBenchMode ? 24 : 25);
+ for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)
break;
- dict = (1 << dicSizeLog);
+ dict = (UInt32)1 << dicSizeLog;
}
- IBenchPrintCallback &f = *printCallback;
PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dict), "Benchmark threads: ", numThreads);
- bool totalBenchMode = (method.MethodName == L"*");
f.NewLine();
if (totalBenchMode)
@@ -2385,7 +2645,7 @@ HRESULT Bench(
for (j = 0; j < 2; j++)
{
- PrintRight(f, "KB/s", kFieldSize_Speed + 1);
+ PrintRight(f, "KiB/s", kFieldSize_Speed + 1);
PrintRight(f, "%", kFieldSize_Usage + 1);
PrintRight(f, "MIPS", kFieldSize_RU + 1);
PrintRight(f, "MIPS", kFieldSize_Rating + 1);
@@ -2453,7 +2713,7 @@ HRESULT Bench(
else
{
bool needSetComplexity = true;
- if (!methodName.IsEqualToNoCase(L"LZMA"))
+ if (!methodName.IsEqualTo_Ascii_NoCase("LZMA"))
{
for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++)
{
@@ -2492,7 +2752,7 @@ HRESULT Bench(
COneMethodInfo method2 = method;
- if (StringsAreEqualNoCase_Ascii(method2.MethodName, L"LZMA"))
+ if (StringsAreEqualNoCase_Ascii(method2.MethodName, "LZMA"))
{
// We add dictionary size property.
// method2 can have two different dictionary size properties.
@@ -2526,7 +2786,9 @@ HRESULT Bench(
f.Print(kSep);
PrintChars(f, '-', fileldSize);
}
+
f.NewLine();
+
if (use2Columns)
{
PrintLeft(f, "Avr:", callback.NameFieldSize);
@@ -2535,10 +2797,13 @@ HRESULT Bench(
PrintTotals(f, showFreq, cpuFreq, callback.DecodeRes);
f.NewLine();
}
+
PrintLeft(f, "Tot:", callback.NameFieldSize);
CTotalBenchRes midRes;
midRes.SetSum(callback.EncodeRes, callback.DecodeRes);
PrintTotals(f, showFreq, cpuFreq, midRes);
f.NewLine();
+
+ }
return S_OK;
}
diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp
index f5407b03..37da9d1a 100644
--- a/CPP/7zip/UI/Common/CompressCall.cpp
+++ b/CPP/7zip/UI/Common/CompressCall.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <wchar.h>
+
#include "../../../Common/IntToString.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/Random.h"
@@ -21,25 +23,32 @@
using namespace NWindows;
#define MY_TRY_BEGIN try {
+
#define MY_TRY_FINISH } \
catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; }
+
#define MY_TRY_FINISH_VOID } \
catch(...) { ErrorMessageHRESULT(E_FAIL); }
-static LPCWSTR kShowDialogSwitch = L" -ad";
-static LPCWSTR kEmailSwitch = L" -seml.";
-static LPCWSTR kIncludeSwitch = L" -i";
-static LPCWSTR kArchiveTypeSwitch = L" -t";
-static LPCWSTR kArcIncludeSwitches = L" -an -ai";
-static LPCWSTR kHashIncludeSwitches = L" -i";
-static LPCWSTR kStopSwitchParsing = L" --";
-static LPCWSTR kLargePagesDisable = L" -slp-";
+static const char *k7zGui = "7zG.exe";
+
+static const char *kShowDialogSwitch = " -ad";
+static const char *kEmailSwitch = " -seml.";
+static const char *kIncludeSwitch = " -i";
+static const char *kArchiveTypeSwitch = " -t";
+static const char *kArcIncludeSwitches = " -an -ai";
+static const char *kHashIncludeSwitches = " -i";
+static const char *kStopSwitchParsing = " --";
+static const char *kLargePagesDisable = " -slp-";
extern HWND g_HWND;
UString GetQuotedString(const UString &s)
{
- return UString(L'\"') + s + UString(L'\"');
+ UString s2 = L'\"';
+ s2 += s;
+ s2 += L'\"';
+ return s2;
}
static void ErrorMessage(LPCWSTR message)
@@ -52,17 +61,20 @@ static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL)
UString s2 = NError::MyFormatMessage(res);
if (s)
{
- s2 += L'\n';
+ s2.Add_LF();
s2 += s;
}
ErrorMessage(s2);
}
-static HRESULT MyCreateProcess(LPCWSTR imageName, const UString &params,
+static HRESULT Call7zGui(const UString &params,
// LPCWSTR curDir,
bool waitFinish,
NSynchronization::CBaseEvent *event)
{
+ UString imageName = fs2us(NWindows::NDLL::GetModuleDirPrefix());
+ imageName.AddAscii(k7zGui);
+
CProcess process;
WRes res = process.Create(imageName, params, NULL); // curDir);
if (res != 0)
@@ -83,12 +95,7 @@ static HRESULT MyCreateProcess(LPCWSTR imageName, const UString &params,
static void AddLagePagesSwitch(UString &params)
{
if (!ReadLockMemoryEnable())
- params += kLargePagesDisable;
-}
-
-static UString Get7zGuiPath()
-{
- return fs2us(NWindows::NDLL::GetModuleDirPrefix()) + L"7zG.exe";
+ params.AddAscii(kLargePagesDisable);
}
class CRandNameGenerator
@@ -96,11 +103,12 @@ class CRandNameGenerator
CRandom _random;
public:
CRandNameGenerator() { _random.Init(); }
- UString GenerateName()
+ void GenerateName(UString &s, const char *prefix)
{
- wchar_t temp[16];
- ConvertUInt32ToString((UInt32)_random.Generate(), temp);
- return temp;
+ s.AddAscii(prefix);
+ char temp[16];
+ ConvertUInt32ToString((UInt32)(unsigned)_random.Generate(), temp);
+ s.AddAscii(temp);
}
};
@@ -108,9 +116,11 @@ static HRESULT CreateMap(const UStringVector &names,
CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event,
UString &params)
{
- UInt32 totalSize = 1;
- FOR_VECTOR (i, names)
- totalSize += (names[i].Len() + 1);
+ size_t totalSize = 1;
+ {
+ FOR_VECTOR (i, names)
+ totalSize += (names[i].Len() + 1);
+ }
totalSize *= sizeof(wchar_t);
CRandNameGenerator random;
@@ -118,7 +128,7 @@ static HRESULT CreateMap(const UStringVector &names,
UString mappingName;
for (;;)
{
- mappingName = L"7zMap" + random.GenerateName();
+ random.GenerateName(mappingName, "7zMap");
WRes res = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName));
if (fileMapping.IsCreated() && res == 0)
@@ -131,7 +141,7 @@ static HRESULT CreateMap(const UStringVector &names,
UString eventName;
for (;;)
{
- eventName = L"7zEvent" + random.GenerateName();
+ random.GenerateName(eventName, "7zEvent");
WRes res = event.CreateWithName(false, GetSystemString(eventName));
if (event.IsCreated() && res == 0)
break;
@@ -143,25 +153,25 @@ static HRESULT CreateMap(const UStringVector &names,
params += L'#';
params += mappingName;
params += L':';
- wchar_t temp[16];
- ConvertUInt32ToString(totalSize, temp);
- params += temp;
+ char temp[32];
+ ConvertUInt64ToString(totalSize, temp);
+ params.AddAscii(temp);
params += L':';
params += eventName;
LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize);
- if (data == NULL)
+ if (!data)
return E_FAIL;
CFileUnmapper unmapper(data);
{
wchar_t *cur = (wchar_t *)data;
- *cur++ = 0;
+ *cur++ = 0; // it means wchar_t strings (UTF-16 in WIN32)
FOR_VECTOR (i, names)
{
const UString &s = names[i];
- int len = s.Len() + 1;
- memcpy(cur, (const wchar_t *)s, len * sizeof(wchar_t));
+ unsigned len = s.Len() + 1;
+ wmemcpy(cur, (const wchar_t *)s, len);
cur += len;
}
}
@@ -181,33 +191,33 @@ HRESULT CompressFiles(
CFileMapping fileMapping;
NSynchronization::CManualResetEvent event;
- params += kIncludeSwitch;
+ params.AddAscii(kIncludeSwitch);
RINOK(CreateMap(names, fileMapping, event, params));
if (!arcType.IsEmpty())
{
- params += kArchiveTypeSwitch;
+ params.AddAscii(kArchiveTypeSwitch);
params += arcType;
}
if (email)
- params += kEmailSwitch;
+ params.AddAscii(kEmailSwitch);
if (showDialog)
- params += kShowDialogSwitch;
+ params.AddAscii(kShowDialogSwitch);
AddLagePagesSwitch(params);
if (arcName.IsEmpty())
- params += L" -an";
+ params.AddAscii(" -an");
if (addExtension)
- params += L" -saa";
+ params.AddAscii(" -saa");
else
- params += L" -sae";
+ params.AddAscii(" -sae");
- params += kStopSwitchParsing;
- params += L' ';
+ params.AddAscii(kStopSwitchParsing);
+ params.Add_Space();
if (!arcName.IsEmpty())
{
@@ -218,7 +228,7 @@ HRESULT CompressFiles(
arcName);
}
- return MyCreateProcess(Get7zGuiPath(), params,
+ return Call7zGui(params,
// (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix),
waitFinish, &event);
MY_TRY_FINISH
@@ -227,12 +237,12 @@ HRESULT CompressFiles(
static void ExtractGroupCommand(const UStringVector &arcPaths, UString &params, bool isHash)
{
AddLagePagesSwitch(params);
- params += isHash ? kHashIncludeSwitches : kArcIncludeSwitches;
+ params.AddAscii(isHash ? kHashIncludeSwitches : kArcIncludeSwitches);
CFileMapping fileMapping;
NSynchronization::CManualResetEvent event;
HRESULT result = CreateMap(arcPaths, fileMapping, event, params);
if (result == S_OK)
- result = MyCreateProcess(Get7zGuiPath(), params, false, &event);
+ result = Call7zGui(params, false, &event);
if (result != S_OK)
ErrorMessageHRESULT(result);
}
@@ -243,13 +253,13 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo
UString params = L'x';
if (!outFolder.IsEmpty())
{
- params += L" -o";
+ params.AddAscii(" -o");
params += GetQuotedString(outFolder);
}
if (elimDup)
- params += L" -spe";
+ params.AddAscii(" -spe");
if (showDialog)
- params += kShowDialogSwitch;
+ params.AddAscii(kShowDialogSwitch);
ExtractGroupCommand(arcPaths, params, false);
MY_TRY_FINISH_VOID
}
@@ -268,7 +278,7 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName)
UString params = L'h';
if (!methodName.IsEmpty())
{
- params += L" -scrc";
+ params.AddAscii(" -scrc");
params += methodName;
}
ExtractGroupCommand(paths, params, true);
@@ -278,7 +288,7 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName)
void Benchmark(bool totalMode)
{
MY_TRY_BEGIN
- HRESULT result = MyCreateProcess(Get7zGuiPath(), totalMode ? L"b -mm=*" : L"b", false, NULL);
+ HRESULT result = Call7zGui(totalMode ? L"b -mm=*" : L"b", false, NULL);
if (result != S_OK)
ErrorMessageHRESULT(result);
MY_TRY_FINISH_VOID
diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp
index bd27f37b..b3421e5a 100644
--- a/CPP/7zip/UI/Common/CompressCall2.cpp
+++ b/CPP/7zip/UI/Common/CompressCall2.cpp
@@ -30,28 +30,39 @@ static void ThrowException_if_Error(HRESULT res)
throw CSystemException(res);
}
+#ifdef EXTERNAL_CODECS
+
#define CREATE_CODECS \
CCodecs *codecs = new CCodecs; \
CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; \
ThrowException_if_Error(codecs->Load());
-#ifdef EXTERNAL_CODECS
-
#define LOAD_EXTERNAL_CODECS \
CExternalCodecs __externalCodecs; \
__externalCodecs.GetCodecs = codecs; \
__externalCodecs.GetHashers = codecs; \
- ThrowException_if_Error(__externalCodecs.LoadCodecs());
+ ThrowException_if_Error(__externalCodecs.Load());
#else
-LOAD_EXTERNAL_CODECS
+#define CREATE_CODECS \
+ CCodecs *codecs = new CCodecs; \
+ CMyComPtr<IUnknown> compressCodecsInfo = codecs; \
+ ThrowException_if_Error(codecs->Load());
+
+#define LOAD_EXTERNAL_CODECS
#endif
+
+
+
UString GetQuotedString(const UString &s)
{
- return UString(L'\"') + s + UString(L'\"');
+ UString s2 = L'\"';
+ s2 += s;
+ s2 += L'\"';
+ return s2;
}
static void ErrorMessage(LPCWSTR message)
@@ -78,6 +89,7 @@ HRESULT CompressFiles(
bool email, bool showDialog, bool /* waitFinish */)
{
MY_TRY_BEGIN
+
CREATE_CODECS
CUpdateCallbackGUI callback;
@@ -128,6 +140,7 @@ HRESULT CompressFiles(
throw CSystemException(E_FAIL);
return E_FAIL;
}
+
MY_TRY_FINISH
return S_OK;
}
@@ -136,6 +149,7 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false)
{
MY_TRY_BEGIN
+
CREATE_CODECS
CExtractOptions eo;
@@ -160,7 +174,12 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
arcCensor.AddPreItem(arcPaths[i]);
}
arcCensor.AddPathsToCensor(NWildcard::k_RelatPath);
- EnumerateDirItemsAndSort(false, arcCensor, NWildcard::k_RelatPath, UString(), arcPathsSorted, arcFullPathsSorted);
+ CDirItemsStat st;
+ EnumerateDirItemsAndSort(arcCensor, NWildcard::k_RelatPath, UString(),
+ arcPathsSorted, arcFullPathsSorted,
+ st,
+ NULL // &scan: change it!!!!
+ );
}
CObjectVector<COpenType> formatIndices;
@@ -184,6 +203,7 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
throw CSystemException(result);
}
return ecs->IsOK() ? S_OK : E_FAIL;
+
MY_TRY_FINISH
return result;
}
@@ -201,6 +221,7 @@ void TestArchives(const UStringVector &arcPaths)
void CalcChecksum(const UStringVector &paths, const UString &methodName)
{
MY_TRY_BEGIN
+
CREATE_CODECS
LOAD_EXTERNAL_CODECS
@@ -216,13 +237,14 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName)
CHashOptions options;
options.Methods.Add(methodName);
- result = HashCalcGUI(EXTERNAL_CODECS_VARS censor, options, messageWasDisplayed);
+ result = HashCalcGUI(EXTERNAL_CODECS_VARS_L censor, options, messageWasDisplayed);
if (result != S_OK)
{
if (result != E_ABORT && messageWasDisplayed)
return; // E_FAIL;
throw CSystemException(result);
}
+
MY_TRY_FINISH
return; // result;
}
@@ -230,6 +252,7 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName)
void Benchmark(bool totalMode)
{
MY_TRY_BEGIN
+
CREATE_CODECS
LOAD_EXTERNAL_CODECS
@@ -241,6 +264,7 @@ void Benchmark(bool totalMode)
prop.Value = L"*";
props.Add(prop);
}
- result = Benchmark(EXTERNAL_CODECS_VARS props, g_HWND);
+ result = Benchmark(EXTERNAL_CODECS_VARS_L props, g_HWND);
+
MY_TRY_FINISH
}
diff --git a/CPP/7zip/UI/Common/DefaultName.cpp b/CPP/7zip/UI/Common/DefaultName.cpp
index ce0b327b..02f611c3 100644
--- a/CPP/7zip/UI/Common/DefaultName.cpp
+++ b/CPP/7zip/UI/Common/DefaultName.cpp
@@ -7,21 +7,23 @@
static UString GetDefaultName3(const UString &fileName,
const UString &extension, const UString &addSubExtension)
{
- int extLength = extension.Len();
- int fileNameLength = fileName.Len();
- if (fileNameLength > extLength + 1)
+ const unsigned extLen = extension.Len();
+ const unsigned fileNameLen = fileName.Len();
+
+ if (fileNameLen > extLen + 1)
{
- int dotPos = fileNameLength - (extLength + 1);
+ const unsigned dotPos = fileNameLen - (extLen + 1);
if (fileName[dotPos] == '.')
- if (extension.IsEqualToNoCase(fileName.Ptr(dotPos + 1)))
+ if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1)))
return fileName.Left(dotPos) + addSubExtension;
}
- int dotPos = fileName.ReverseFind(L'.');
+
+ int dotPos = fileName.ReverseFind_Dot();
if (dotPos > 0)
return fileName.Left(dotPos) + addSubExtension;
if (addSubExtension.IsEmpty())
- return fileName + L"~";
+ return fileName + L'~';
else
return fileName + addSubExtension;
}
diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
index ce48b582..4286b4e8 100644
--- a/CPP/7zip/UI/Common/DirItem.h
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -11,6 +11,38 @@
#include "../../Archive/IArchive.h"
+struct CDirItemsStat
+{
+ UInt64 NumDirs;
+ UInt64 NumFiles;
+ UInt64 NumAltStreams;
+ UInt64 FilesSize;
+ UInt64 AltStreamsSize;
+
+ UInt64 NumErrors;
+ // UInt64 GetTotalItems() const { return NumDirs + NumFiles + NumAltStreams; }
+
+ UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; }
+
+ CDirItemsStat():
+ NumDirs(0),
+ NumFiles(0),
+ NumAltStreams(0),
+ FilesSize(0),
+ AltStreamsSize(0),
+ NumErrors(0)
+ {}
+};
+
+#define INTERFACE_IDirItemsCallback(x) \
+ virtual HRESULT ScanError(const FString &path, DWORD systemError) x; \
+ virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x; \
+
+struct IDirItemsCallback
+{
+ INTERFACE_IDirItemsCallback(=0)
+};
+
struct CDirItem
{
UInt64 Size;
@@ -46,7 +78,7 @@ class CDirItems
UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;
- void EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);
+ HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);
public:
CObjectVector<CDirItem> Items;
@@ -54,26 +86,14 @@ public:
bool SymLinks;
bool ScanAltStreams;
- FStringVector ErrorPaths;
- CRecordVector<DWORD> ErrorCodes;
- UInt64 TotalSize;
-
+
+ CDirItemsStat Stat;
#ifndef UNDER_CE
- void SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,
+ HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,
const FString &phyPrefix);
#endif
- void AddError(const FString &path, DWORD errorCode)
- {
- ErrorCodes.Add(errorCode);
- ErrorPaths.Add(path);
- }
-
- void AddError(const FString &path)
- {
- AddError(path, ::GetLastError());
- }
#if defined(_WIN32) && !defined(UNDER_CE)
@@ -82,19 +102,30 @@ public:
bool _saclEnabled;
bool ReadSecure;
- void AddSecurityItem(const FString &path, int &secureIndex);
+ HRESULT AddSecurityItem(const FString &path, int &secureIndex);
#endif
+ IDirItemsCallback *Callback;
+
CDirItems();
- int GetNumFolders() const { return Prefixes.Size(); }
- UString GetPhyPath(unsigned index) const;
+ void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
+ const NWindows::NFile::NFind::CFileInfo &fi);
+
+ HRESULT AddError(const FString &path, DWORD errorCode);
+ HRESULT AddError(const FString &path);
+
+ HRESULT ScanProgress(const FString &path);
+
+ // unsigned GetNumFolders() const { return Prefixes.Size(); }
+ FString GetPhyPath(unsigned index) const;
UString GetLogPath(unsigned index) const;
unsigned AddPrefix(int phyParent, int logParent, const UString &prefix);
void DeleteLastPrefix();
- void EnumerateItems2(
+
+ HRESULT EnumerateItems2(
const FString &phyPrefix,
const UString &logPrefix,
const FStringVector &filePaths,
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
index 14285cfe..3ebf25aa 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <wchar.h>
+
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileDir.h"
@@ -19,8 +21,8 @@ using namespace NWindows;
using namespace NFile;
using namespace NName;
-void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
- const NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems)
+void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex,
+ const NFind::CFileInfo &fi)
{
CDirItem di;
di.Size = fi.Size;
@@ -36,35 +38,72 @@ void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
#if defined(_WIN32) && !defined(UNDER_CE)
// di.ShortName = fs2us(fi.ShortName);
#endif
- dirItems.Add(di);
+ Items.Add(di);
+
+ if (fi.IsDir())
+ Stat.NumDirs++;
+ else if (fi.IsAltStream)
+ {
+ Stat.NumAltStreams++;
+ Stat.AltStreamsSize += fi.Size;
+ }
+ else
+ {
+ Stat.NumFiles++;
+ Stat.FilesSize += fi.Size;
+ }
+}
+
+HRESULT CDirItems::AddError(const FString &path, DWORD errorCode)
+{
+ Stat.NumErrors++;
+ if (Callback)
+ return Callback->ScanError(path, errorCode);
+ return S_OK;
+}
+
+HRESULT CDirItems::AddError(const FString &path)
+{
+ return AddError(path, ::GetLastError());
+}
+
+static const unsigned kScanProgressStepMask = (1 << 12) - 1;
+
+HRESULT CDirItems::ScanProgress(const FString &dirPath)
+{
+ if (Callback)
+ return Callback->ScanProgress(Stat, dirPath, true);
+ return S_OK;
}
UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const
{
UString path;
unsigned len = name.Len();
+
int i;
for (i = index; i >= 0; i = parents[i])
len += Prefixes[i].Len();
- unsigned totalLen = len;
- wchar_t *p = path.GetBuffer(len);
- p[len] = 0;
- len -= name.Len();
- memcpy(p + len, (const wchar_t *)name, name.Len() * sizeof(wchar_t));
+
+ wchar_t *p = path.GetBuf_SetEnd(len) + len;
+
+ p -= name.Len();
+ wmemcpy(p, (const wchar_t *)name, name.Len());
+
for (i = index; i >= 0; i = parents[i])
{
const UString &s = Prefixes[i];
- len -= s.Len();
- memcpy(p + len, (const wchar_t *)s, s.Len() * sizeof(wchar_t));
+ p -= s.Len();
+ wmemcpy(p, (const wchar_t *)s, s.Len());
}
- path.ReleaseBuffer(totalLen);
+
return path;
}
-UString CDirItems::GetPhyPath(unsigned index) const
+FString CDirItems::GetPhyPath(unsigned index) const
{
const CDirItem &di = Items[index];
- return GetPrefixesPath(PhyParents, di.PhyParent, di.Name);
+ return us2fs(GetPrefixesPath(PhyParents, di.PhyParent, di.Name));
}
UString CDirItems::GetLogPath(unsigned index) const
@@ -99,10 +138,11 @@ bool InitLocalPrivileges();
CDirItems::CDirItems():
SymLinks(false),
- TotalSize(0)
+ ScanAltStreams(false)
#ifdef _USE_SECURITY_CODE
, ReadSecure(false)
#endif
+ , Callback(NULL)
{
#ifdef _USE_SECURITY_CODE
_saclEnabled = InitLocalPrivileges();
@@ -111,7 +151,7 @@ CDirItems::CDirItems():
#ifdef _USE_SECURITY_CODE
-void CDirItems::AddSecurityItem(const FString &path, int &secureIndex)
+HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex)
{
secureIndex = -1;
@@ -124,11 +164,13 @@ void CDirItems::AddSecurityItem(const FString &path, int &secureIndex)
DWORD errorCode = 0;
DWORD secureSize;
+
BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize);
+
if (res)
{
if (secureSize == 0)
- return;
+ return S_OK;
if (secureSize > TempSecureBuf.Size())
errorCode = ERROR_INVALID_FUNCTION;
}
@@ -153,51 +195,61 @@ void CDirItems::AddSecurityItem(const FString &path, int &secureIndex)
}
}
}
+
if (res)
{
secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize);
- return;
+ return S_OK;
}
+
if (errorCode == 0)
errorCode = ERROR_INVALID_FUNCTION;
- AddError(path, errorCode);
+ return AddError(path, errorCode);
}
#endif
-void CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix)
+HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix)
{
+ RINOK(ScanProgress(phyPrefix));
+
NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK);
- for (;;)
+ for (unsigned ttt = 0; ; ttt++)
{
NFind::CFileInfo fi;
bool found;
if (!enumerator.Next(fi, found))
{
- AddError(phyPrefix);
- return;
+ return AddError(phyPrefix);
}
if (!found)
- break;
+ return S_OK;
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (ReadSecure)
- AddSecurityItem(phyPrefix + fi.Name, secureIndex);
+ {
+ RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex));
+ }
#endif
- AddDirFileInfo(phyParent, logParent, secureIndex, fi, Items);
+ AddDirFileInfo(phyParent, logParent, secureIndex, fi);
+ if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask)
+ {
+ RINOK(ScanProgress(phyPrefix));
+ }
+
if (fi.IsDir())
{
const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;
unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2));
- EnumerateDir(parent, parent, phyPrefix + name2);
+ RINOK(EnumerateDir(parent, parent, phyPrefix + name2));
}
}
}
-void CDirItems::EnumerateItems2(
+HRESULT CDirItems::EnumerateItems2(
const FString &phyPrefix,
const UString &logPrefix,
const FStringVector &filePaths,
@@ -213,13 +265,13 @@ void CDirItems::EnumerateItems2(
const FString phyPath = phyPrefix + filePath;
if (!fi.Find(phyPath))
{
- AddError(phyPath);
+ RINOK(AddError(phyPath));
continue;
}
if (requestedPaths)
requestedPaths->Add(phyPath);
- int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR);
+ int delimiter = filePath.ReverseFind_PathSepar();
FString phyPrefixCur;
int phyParentCur = phyParent;
if (delimiter >= 0)
@@ -231,19 +283,23 @@ void CDirItems::EnumerateItems2(
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (ReadSecure)
- AddSecurityItem(phyPath, secureIndex);
+ {
+ RINOK(AddSecurityItem(phyPath, secureIndex));
+ }
#endif
- AddDirFileInfo(phyParentCur, logParent, secureIndex, fi, Items);
+ AddDirFileInfo(phyParentCur, logParent, secureIndex, fi);
if (fi.IsDir())
{
const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;
unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2));
- EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2);
+ RINOK(EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2));
}
}
+
ReserveDown();
+ return S_OK;
}
@@ -256,8 +312,7 @@ static HRESULT EnumerateDirItems(
int phyParent, int logParent, const FString &phyPrefix,
const UStringVector &addArchivePrefix,
CDirItems &dirItems,
- bool enterToSubFolders,
- IEnumDirItemCallback *callback);
+ bool enterToSubFolders);
static HRESULT EnumerateDirItems_Spec(
const NWildcard::CCensorNode &curNode,
@@ -265,15 +320,14 @@ static HRESULT EnumerateDirItems_Spec(
const FString &phyPrefix,
const UStringVector &addArchivePrefix,
CDirItems &dirItems,
- bool enterToSubFolders,
- IEnumDirItemCallback *callback)
+ bool enterToSubFolders)
{
const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR;
unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2));
unsigned numItems = dirItems.Items.Size();
HRESULT res = EnumerateDirItems(
curNode, parent, parent, phyPrefix + name2,
- addArchivePrefix, dirItems, enterToSubFolders, callback);
+ addArchivePrefix, dirItems, enterToSubFolders);
if (numItems == dirItems.Items.Size())
dirItems.DeleteLastPrefix();
return res;
@@ -281,14 +335,15 @@ static HRESULT EnumerateDirItems_Spec(
#ifndef UNDER_CE
-static void EnumerateAltStreams(
+#ifdef _WIN32
+
+static HRESULT EnumerateAltStreams(
const NFind::CFileInfo &fi,
const NWildcard::CCensorNode &curNode,
- int phyParent, int logParent, const FString &phyPrefix,
+ int phyParent, int logParent, const FString &fullPath,
const UStringVector &addArchivePrefix, // prefix from curNode
CDirItems &dirItems)
{
- const FString fullPath = phyPrefix + fi.Name;
NFind::CStreamEnumerator enumerator(fullPath);
for (;;)
{
@@ -296,11 +351,10 @@ static void EnumerateAltStreams(
bool found;
if (!enumerator.Next(si, found))
{
- dirItems.AddError(fullPath + FTEXT(":*"), (DWORD)E_FAIL);
- break;
+ return dirItems.AddError(fullPath + FTEXT(":*")); // , (DWORD)E_FAIL
}
if (!found)
- break;
+ return S_OK;
if (si.IsMainStream())
continue;
UStringVector addArchivePrefixNew = addArchivePrefix;
@@ -313,26 +367,28 @@ static void EnumerateAltStreams(
fi2.Size = si.Size;
fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;
fi2.IsAltStream = true;
- AddDirFileInfo(phyParent, logParent, -1, fi2, dirItems.Items);
- dirItems.TotalSize += fi2.Size;
+ dirItems.AddDirFileInfo(phyParent, logParent, -1, fi2);
}
}
-void CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,
+#endif
+
+HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,
const FString &phyPrefix)
{
if (!SymLinks || !fi.HasReparsePoint())
- return;
+ return S_OK;
const FString path = phyPrefix + fi.Name;
CByteBuffer &buf = dirItem.ReparseData;
if (NIO::GetReparseData(path, buf))
{
CReparseAttr attr;
if (attr.Parse(buf, buf.Size()))
- return;
+ return S_OK;
}
- AddError(path);
+ DWORD res = ::GetLastError();
buf.Free();
+ return AddError(path , res);
}
#endif
@@ -343,8 +399,7 @@ static HRESULT EnumerateForItem(
int phyParent, int logParent, const FString &phyPrefix,
const UStringVector &addArchivePrefix, // prefix from curNode
CDirItems &dirItems,
- bool enterToSubFolders,
- IEnumDirItemCallback *callback)
+ bool enterToSubFolders)
{
const UString name = fs2us(fi.Name);
bool enterToSubFolders2 = enterToSubFolders;
@@ -362,12 +417,13 @@ static HRESULT EnumerateForItem(
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (dirItems.ReadSecure)
- dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex);
+ {
+ RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex));
+ }
#endif
dirItemIndex = dirItems.Items.Size();
- AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items);
- dirItems.TotalSize += fi.Size;
+ dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
if (fi.IsDir())
enterToSubFolders2 = true;
}
@@ -375,14 +431,15 @@ static HRESULT EnumerateForItem(
#ifndef UNDER_CE
if (dirItems.ScanAltStreams)
{
- EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix,
- addArchivePrefixNew, dirItems);
+ RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
+ phyPrefix + fi.Name,
+ addArchivePrefixNew, dirItems));
}
if (dirItemIndex >= 0)
{
CDirItem &dirItem = dirItems.Items[dirItemIndex];
- dirItems.SetLinkInfo(dirItem, fi, phyPrefix);
+ RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix));
if (dirItem.ReparseData.Size() != 0)
return S_OK;
}
@@ -412,7 +469,7 @@ static HRESULT EnumerateForItem(
*nextNode, phyParent, logParent, fi.Name, phyPrefix,
addArchivePrefixNew,
dirItems,
- enterToSubFolders2, callback);
+ enterToSubFolders2);
}
@@ -424,11 +481,13 @@ static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode)
if (item.Recursive || item.PathParts.Size() != 1)
return false;
const UString &name = item.PathParts.Front();
+ /*
if (name.IsEmpty())
return false;
+ */
- /* Windows doesn't support file name with wildcard.
- but if another system supports file name with wildcard,
+ /* Windows doesn't support file name with wildcard
+ But if another system supports file name with wildcard,
and wildcard mode is disabled, we can ignore wildcard in name */
/*
if (!item.WildcardParsing)
@@ -441,19 +500,30 @@ static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode)
}
+#if defined(_WIN32) && !defined(UNDER_CE)
+
+static bool IsVirtualFsFolder(const FString &prefix, const UString &name)
+{
+ UString s = fs2us(prefix);
+ s += name;
+ s.Add_PathSepar();
+ return IsPathSepar(s[0]) && GetRootPrefixSize(s) == 0;
+}
+
+#endif
+
static HRESULT EnumerateDirItems(
const NWildcard::CCensorNode &curNode,
int phyParent, int logParent, const FString &phyPrefix,
const UStringVector &addArchivePrefix, // prefix from curNode
CDirItems &dirItems,
- bool enterToSubFolders,
- IEnumDirItemCallback *callback)
+ bool enterToSubFolders)
{
if (!enterToSubFolders)
if (curNode.NeedCheckSubDirs())
enterToSubFolders = true;
- if (callback)
- RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true));
+
+ RINOK(dirItems.ScanProgress(phyPrefix));
// try direct_names case at first
if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
@@ -469,25 +539,68 @@ static HRESULT EnumerateDirItems(
{
const NWildcard::CItem &item = curNode.IncludeItems[i];
const UString &name = item.PathParts.Front();
- const FString fullPath = phyPrefix + us2fs(name);
+ FString fullPath = phyPrefix + us2fs(name);
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ bool needAltStreams = true;
+ #endif
+
+ #ifdef _USE_SECURITY_CODE
+ bool needSecurity = true;
+ #endif
+
+ if (phyPrefix.IsEmpty())
+ {
+ if (!item.ForFile)
+ {
+ /* we don't like some names for alt streams inside archive:
+ ":sname" for "\"
+ "c:::sname" for "C:\"
+ So we ignore alt streams for these cases */
+ if (name.IsEmpty())
+ {
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ needAltStreams = false;
+ #endif
+
+ /*
+ // do we need to ignore security info for "\\" folder ?
+ #ifdef _USE_SECURITY_CODE
+ needSecurity = false;
+ #endif
+ */
+
+ fullPath = FCHAR_PATH_SEPARATOR;
+ }
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ else if (item.IsDriveItem())
+ {
+ needAltStreams = false;
+ fullPath.Add_PathSepar();
+ }
+ #endif
+ }
+ }
+
NFind::CFileInfo fi;
- #ifdef _WIN32
- if (phyPrefix.IsEmpty() && item.IsDriveItem())
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (IsVirtualFsFolder(phyPrefix, name))
{
fi.SetAsDir();
- fi.Name = fullPath;
+ fi.Name = us2fs(name);
}
else
#endif
if (!fi.Find(fullPath))
{
- dirItems.AddError(fullPath);
+ RINOK(dirItems.AddError(fullPath));
continue;
}
+
bool isDir = fi.IsDir();
if (isDir && !item.ForDir || !isDir && !item.ForFile)
{
- dirItems.AddError(fullPath, (DWORD)E_FAIL);
+ RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL));
continue;
}
{
@@ -499,30 +612,37 @@ static HRESULT EnumerateDirItems(
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
- if (dirItems.ReadSecure)
- dirItems.AddSecurityItem(fullPath, secureIndex);
+ if (needSecurity && dirItems.ReadSecure)
+ {
+ RINOK(dirItems.AddSecurityItem(fullPath, secureIndex));
+ }
#endif
- AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items);
+ dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
#ifndef UNDER_CE
{
CDirItem &dirItem = dirItems.Items.Back();
- dirItems.SetLinkInfo(dirItem, fi, phyPrefix);
+ RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix));
if (dirItem.ReparseData.Size() != 0)
+ {
+ if (fi.IsAltStream)
+ dirItems.Stat.AltStreamsSize -= fi.Size;
+ else
+ dirItems.Stat.FilesSize -= fi.Size;
continue;
+ }
}
#endif
- dirItems.TotalSize += fi.Size;
#ifndef UNDER_CE
- if (dirItems.ScanAltStreams)
+ if (needAltStreams && dirItems.ScanAltStreams)
{
UStringVector pathParts;
pathParts.Add(fs2us(fi.Name));
- EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix,
- pathParts, dirItems);
+ RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
+ fullPath, pathParts, dirItems));
}
#endif
@@ -546,7 +666,7 @@ static HRESULT EnumerateDirItems(
}
RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,
- addArchivePrefixNew, dirItems, true, callback));
+ addArchivePrefixNew, dirItems, true));
}
for (i = 0; i < curNode.SubNodes.Size(); i++)
@@ -555,31 +675,50 @@ static HRESULT EnumerateDirItems(
if (!needEnterVector[i])
continue;
const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
- const FString fullPath = phyPrefix + us2fs(nextNode.Name);
+ FString fullPath = phyPrefix + us2fs(nextNode.Name);
NFind::CFileInfo fi;
- #ifdef _WIN32
- if (phyPrefix.IsEmpty() && NWildcard::IsDriveColonName(nextNode.Name))
+
+ if (phyPrefix.IsEmpty())
+ {
+ {
+ if (nextNode.Name.IsEmpty())
+ fullPath = FCHAR_PATH_SEPARATOR;
+ #ifdef _WIN32
+ else if (NWildcard::IsDriveColonName(nextNode.Name))
+ fullPath.Add_PathSepar();
+ #endif
+ }
+ }
+
+ // we don't want to call fi.Find() for root folder or virtual folder
+ if (phyPrefix.IsEmpty() && nextNode.Name.IsEmpty()
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ || IsVirtualFsFolder(phyPrefix, nextNode.Name)
+ #endif
+ )
{
fi.SetAsDir();
- fi.Name = fullPath;
+ fi.Name = us2fs(nextNode.Name);
}
else
- #endif
- if (!fi.Find(fullPath))
{
- if (!nextNode.AreThereIncludeItems())
+ if (!fi.Find(fullPath))
+ {
+ if (!nextNode.AreThereIncludeItems())
+ continue;
+ RINOK(dirItems.AddError(fullPath));
continue;
- dirItems.AddError(fullPath);
- continue;
- }
- if (!fi.IsDir())
- {
- dirItems.AddError(fullPath, (DWORD)E_FAIL);
- continue;
+ }
+
+ if (!fi.IsDir())
+ {
+ RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL));
+ continue;
+ }
}
RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,
- UStringVector(), dirItems, false, callback));
+ UStringVector(), dirItems, false));
}
return S_OK;
@@ -625,7 +764,7 @@ static HRESULT EnumerateDirItems(
fi.Name = driveName;
RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,
- addArchivePrefix, dirItems, enterToSubFolders, callback));
+ addArchivePrefix, dirItems, enterToSubFolders));
}
return S_OK;
}
@@ -641,18 +780,21 @@ static HRESULT EnumerateDirItems(
bool found;
if (!enumerator.Next(fi, found))
{
- dirItems.AddError(phyPrefix);
+ RINOK(dirItems.AddError(phyPrefix));
break;
}
if (!found)
break;
- if (callback && (ttt & 0xFF) == 0xFF)
- RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true));
+ if (dirItems.Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask)
+ {
+ RINOK(dirItems.ScanProgress(phyPrefix));
+ }
RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,
- addArchivePrefix, dirItems, enterToSubFolders, callback));
+ addArchivePrefix, dirItems, enterToSubFolders));
}
+
return S_OK;
}
@@ -660,8 +802,7 @@ HRESULT EnumerateItems(
const NWildcard::CCensor &censor,
const NWildcard::ECensorPathMode pathMode,
const UString &addPathPrefix,
- CDirItems &dirItems,
- IEnumDirItemCallback *callback)
+ CDirItems &dirItems)
{
FOR_VECTOR (i, censor.Pairs)
{
@@ -679,8 +820,8 @@ HRESULT EnumerateItems(
RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(),
dirItems,
- false, // enterToSubFolders
- callback));
+ false // enterToSubFolders
+ ));
}
dirItems.ReserveDown();
@@ -719,7 +860,7 @@ void CDirItems::FillFixedReparse()
// maybe we need to support networks paths also ?
FString fullPathF;
- if (!NDir::MyGetFullPathName(us2fs(GetPhyPath(i)), fullPathF))
+ if (!NDir::MyGetFullPathName(GetPhyPath(i), fullPathF))
continue;
UString fullPath = fs2us(fullPathF);
const UString logPath = GetLogPath(i);
@@ -729,7 +870,7 @@ void CDirItems::FillFixedReparse()
continue;
const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len());
- if (prefix.Back() != WCHAR_PATH_SEPARATOR)
+ if (!IsPathSepar(prefix.Back()))
continue;
unsigned rootPrefixSize = GetRootPrefixSize(prefix);
diff --git a/CPP/7zip/UI/Common/EnumDirItems.h b/CPP/7zip/UI/Common/EnumDirItems.h
index 803a64e7..7afb800a 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.h
+++ b/CPP/7zip/UI/Common/EnumDirItems.h
@@ -12,16 +12,10 @@
void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems);
-struct IEnumDirItemCallback
-{
- virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) = 0;
-};
-
HRESULT EnumerateItems(
const NWildcard::CCensor &censor,
NWildcard::ECensorPathMode pathMode,
const UString &addPathPrefix,
- CDirItems &dirItems,
- IEnumDirItemCallback *callback);
+ CDirItems &dirItems);
#endif
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
index 67cad3ac..14aa7407 100644
--- a/CPP/7zip/UI/Common/Extract.cpp
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -51,19 +51,19 @@ static HRESULT DecompressArchive(
replaceName = arc0.DefaultName;
}
- outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(replaceName)));
+ outDir.Replace(FSTRING_ANY_MASK, us2fs(Get_Correct_FsFile_Name(replaceName)));
bool elimIsPossible = false;
UString elimPrefix; // only pure name without dir delimiter
FString outDirReduced = outDir;
- if (options.ElimDup.Val)
+ if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths)
{
UString dirPrefix;
SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);
if (!elimPrefix.IsEmpty())
{
- if (IsCharDirLimiter(elimPrefix.Back()))
+ if (IsPathSepar(elimPrefix.Back()))
elimPrefix.DeleteBack();
if (!elimPrefix.IsEmpty())
{
@@ -73,37 +73,66 @@ static HRESULT DecompressArchive(
}
}
+ bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
+
if (!options.StdInMode)
{
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
- UString filePath;
+ CReadArcItem item;
for (UInt32 i = 0; i < numItems; i++)
{
- RINOK(arc.GetItemPath(i, filePath));
+ if (elimIsPossible || !allFilesAreAllowed)
+ {
+ RINOK(arc.GetItem(i, item));
+ }
+ else
+ {
+ #ifdef SUPPORT_ALT_STREAMS
+ item.IsAltStream = false;
+ if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream)
+ {
+ RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream));
+ }
+ #endif
+ }
- if (elimIsPossible && options.ElimDup.Val)
+ #ifdef SUPPORT_ALT_STREAMS
+ if (!options.NtOptions.AltStreams.Val && item.IsAltStream)
+ continue;
+ #endif
+
+ if (elimIsPossible)
{
- if (!IsPath1PrefixedByPath2(filePath, elimPrefix))
+ const UString &s =
+ #ifdef SUPPORT_ALT_STREAMS
+ item.MainPath;
+ #else
+ item.Path;
+ #endif
+ if (!IsPath1PrefixedByPath2(s, elimPrefix))
elimIsPossible = false;
else
{
- wchar_t c = filePath[elimPrefix.Len()];
- if (c != 0 && !IsCharDirLimiter(c))
+ wchar_t c = s[elimPrefix.Len()];
+ if (c == 0)
+ {
+ if (!item.MainIsDir)
+ elimIsPossible = false;
+ }
+ else if (!IsPathSepar(c))
elimIsPossible = false;
}
}
- bool isFolder;
- RINOK(Archive_IsItem_Folder(archive, i, isFolder));
- bool isAltStream;
- RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));
- if (!options.NtOptions.AltStreams.Val && isAltStream)
- continue;
- if (!wildcardCensor.CheckPath(isAltStream, filePath, !isFolder))
- continue;
+ if (!allFilesAreAllowed)
+ {
+ if (!CensorNode_CheckPath(wildcardCensor, item))
+ continue;
+ }
+
realIndices.Add(i);
}
@@ -115,7 +144,10 @@ static HRESULT DecompressArchive(
}
if (elimIsPossible)
- outDir = outDirReduced;
+ {
+ removePathParts.Add(elimPrefix);
+ // outDir = outDirReduced;
+ }
#ifdef _WIN32
// GetCorrectFullFsPath doesn't like "..".
@@ -124,16 +156,21 @@ static HRESULT DecompressArchive(
#endif
if (outDir.IsEmpty())
- outDir = FString(FTEXT(".")) + FString(FSTRING_PATH_SEPARATOR);
- else
- if (!CreateComplexDir(outDir))
- {
- HRESULT res = ::GetLastError();
- if (res == S_OK)
- res = E_FAIL;
- errorMessage = ((UString)L"Can not create output directory ") + fs2us(outDir);
- return res;
- }
+ outDir = FTEXT(".") FSTRING_PATH_SEPARATOR;
+ /*
+ #ifdef _WIN32
+ else if (NName::IsAltPathPrefix(outDir)) {}
+ #endif
+ */
+ else if (!CreateComplexDir(outDir))
+ {
+ HRESULT res = ::GetLastError();
+ if (res == S_OK)
+ res = E_FAIL;
+ errorMessage.SetFromAscii("Can not create output directory: ");
+ errorMessage += fs2us(outDir);
+ return res;
+ }
ecs->Init(
options.NtOptions,
@@ -142,7 +179,7 @@ static HRESULT DecompressArchive(
callback,
options.StdOutMode, options.TestMode,
outDir,
- removePathParts,
+ removePathParts, false,
packSize);
@@ -209,15 +246,16 @@ HRESULT Extract(
IHashCalc *hash,
#endif
UString &errorMessage,
- CDecompressStat &stat)
+ CDecompressStat &st)
{
- stat.Clear();
+ st.Clear();
UInt64 totalPackSize = 0;
CRecordVector<UInt64> arcSizes;
unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size();
unsigned i;
+
for (i = 0; i < numArcs; i++)
{
NFind::CFileInfo fi;
@@ -272,11 +310,13 @@ HRESULT Extract(
throw "there is no such archive";
}
+ /*
#ifndef _NO_CRYPTO
- openCallback->Open_ClearPasswordWasAskedFlag();
+ openCallback->Open_Clear_PasswordWasAsked_Flag();
#endif
+ */
- RINOK(extractCallback->BeforeOpen(arcPath));
+ RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode));
CArchiveLink arcLink;
CObjectVector<COpenType> types2 = types;
@@ -318,36 +358,17 @@ HRESULT Extract(
op.stdInMode = options.StdInMode;
op.stream = NULL;
op.filePath = arcPath;
- HRESULT result = arcLink.Open2(op, openCallback);
+
+ HRESULT result = arcLink.Open3(op, openCallback);
if (result == E_ABORT)
return result;
- bool crypted = false;
- #ifndef _NO_CRYPTO
- crypted = openCallback->Open_WasPasswordAsked();
- #endif
-
- if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
+ if (result == S_OK && arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
result = S_FALSE;
// arcLink.Set_ErrorsText();
- RINOK(extractCallback->OpenResult(arcPath, result, crypted));
-
-
- {
- FOR_VECTOR (r, arcLink.Arcs)
- {
- const CArc &arc = arcLink.Arcs[r];
- const CArcErrorInfo &er = arc.ErrorInfo;
- if (er.IsThereErrorOrWarning())
- {
- RINOK(extractCallback->SetError(r, arc.Path,
- er.GetErrorFlags(), er.ErrorMessage,
- er.GetWarningFlags(), er.WarningMessage));
- }
- }
- }
+ RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result));
if (result != S_OK)
{
@@ -379,8 +400,8 @@ HRESULT Extract(
{
if ((unsigned)index > i)
{
- skipArcs[index] = true;
- correctionSize -= arcSizes[index];
+ skipArcs[(unsigned)index] = true;
+ correctionSize -= arcSizes[(unsigned)index];
}
}
}
@@ -395,6 +416,9 @@ HRESULT Extract(
}
}
+ /*
+ // Now openCallback and extractCallback use same object. So we don't need to send password.
+
#ifndef _NO_CRYPTO
bool passwordIsDefined;
UString password;
@@ -404,31 +428,7 @@ HRESULT Extract(
RINOK(extractCallback->SetPassword(password));
}
#endif
-
- FOR_VECTOR (k, arcLink.Arcs)
- {
- const CArc &arc = arcLink.Arcs[k];
- const CArcErrorInfo &er = arc.ErrorInfo;
-
- if (er.ErrorFormatIndex >= 0)
- {
- RINOK(extractCallback->OpenTypeWarning(arc.Path,
- codecs->GetFormatNamePtr(arc.FormatIndex),
- codecs->GetFormatNamePtr(er.ErrorFormatIndex)))
- /*
- UString s = L"Can not open the file as [" + codecs->Formats[arc.ErrorFormatIndex].Name + L"] archive\n";
- s += L"The file is open as [" + codecs->Formats[arc.FormatIndex].Name + L"] archive";
- RINOK(extractCallback->MessageError(s));
- */
- }
- {
- const UString &s = er.ErrorMessage;
- if (!s.IsEmpty())
- {
- RINOK(extractCallback->MessageError(s));
- }
- }
- }
+ */
CArc &arc = arcLink.Arcs.Back();
arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
@@ -450,6 +450,7 @@ HRESULT Extract(
options,
calcCrc,
extractCallback, ecs, errorMessage, packProcessed));
+
if (!options.StdInMode)
packProcessed = fi.Size + arcLink.VolumesSize;
totalPackProcessed += packProcessed;
@@ -464,12 +465,13 @@ HRESULT Extract(
RINOK(extractCallback->SetTotal(totalPackSize));
RINOK(extractCallback->SetCompleted(&totalPackProcessed));
}
- stat.NumFolders = ecs->NumFolders;
- stat.NumFiles = ecs->NumFiles;
- stat.NumAltStreams = ecs->NumAltStreams;
- stat.UnpackSize = ecs->UnpackSize;
- stat.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;
- stat.NumArchives = arcPaths.Size();
- stat.PackSize = ecs->LocalProgressSpec->InSize;
+
+ st.NumFolders = ecs->NumFolders;
+ st.NumFiles = ecs->NumFiles;
+ st.NumAltStreams = ecs->NumAltStreams;
+ st.UnpackSize = ecs->UnpackSize;
+ st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;
+ st.NumArchives = arcPaths.Size();
+ st.PackSize = ecs->LocalProgressSpec->InSize;
return S_OK;
}
diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
index e6bd5cb7..03ac74b2 100644
--- a/CPP/7zip/UI/Common/Extract.h
+++ b/CPP/7zip/UI/Common/Extract.h
@@ -89,6 +89,6 @@ HRESULT Extract(
IHashCalc *hash,
#endif
UString &errorMessage,
- CDecompressStat &stat);
+ CDecompressStat &st);
#endif
diff --git a/CPP/7zip/UI/Common/ExtractMode.h b/CPP/7zip/UI/Common/ExtractMode.h
index c2e43f6a..3b2b9a02 100644
--- a/CPP/7zip/UI/Common/ExtractMode.h
+++ b/CPP/7zip/UI/Common/ExtractMode.h
@@ -12,7 +12,8 @@ namespace NPathMode
kFullPaths,
kCurPaths,
kNoPaths,
- kAbsPaths
+ kAbsPaths,
+ kNoPathsAlt // alt streams must be extracted without name of base file
};
}
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
index 37e15013..5ba14045 100644
--- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -8,183 +8,228 @@
#include "ExtractingFilePath.h"
-static UString ReplaceIncorrectChars(const UString &s, bool repaceColon)
+static void ReplaceIncorrectChars(UString &s)
{
- #ifdef _WIN32
- UString res;
- bool beforeColon = true;
{
for (unsigned i = 0; i < s.Len(); i++)
{
wchar_t c = s[i];
- if (beforeColon)
- if (c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"')
- c = '_';
- if (c == ':')
- {
- if (repaceColon)
- c = '_';
- else
- beforeColon = false;
- }
- res += c;
+ if (
+ #ifdef _WIN32
+ c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"'
+ || c == '/' ||
+ #endif
+ c == WCHAR_PATH_SEPARATOR)
+ s.ReplaceOneCharAtPos(i, '_');
}
}
- if (beforeColon)
+
+ #ifdef _WIN32
{
- for (int i = res.Len() - 1; i >= 0; i--)
+ for (unsigned i = s.Len(); i != 0;)
{
- wchar_t c = res[i];
+ wchar_t c = s[--i];
if (c != '.' && c != ' ')
break;
- res.ReplaceOneCharAtPos(i, '_');
+ s.ReplaceOneCharAtPos(i, '_');
}
}
- return res;
- #else
- return s;
#endif
}
#ifdef _WIN32
-static const wchar_t *g_ReservedNames[] =
-{
- L"CON", L"PRN", L"AUX", L"NUL"
-};
+/* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream.
+ But colon in postfix ":$DATA" is allowed.
+ WIN32 functions don't allow empty alt stream name "name:" */
-static bool CheckTail(const UString &name, unsigned len)
+void Correct_AltStream_Name(UString &s)
{
- int dotPos = name.Find(L'.');
- if (dotPos < 0)
- dotPos = name.Len();
- UString s = name.Left(dotPos);
- s.TrimRight();
- return s.Len() != len;
+ unsigned len = s.Len();
+ const unsigned kPostfixSize = 6;
+ if (s.Len() >= kPostfixSize
+ && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA"))
+ len -= kPostfixSize;
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = s[i];
+ if (c == ':' || c == '\\' || c == '/')
+ s.ReplaceOneCharAtPos(i, '_');
+ }
+ if (s.IsEmpty())
+ s = L'_';
}
-static bool CheckNameNum(const UString &name, const wchar_t *reservedName)
+static const unsigned g_ReservedWithNum_Index = 4;
+
+static const char * const g_ReservedNames[] =
{
- unsigned len = MyStringLen(reservedName);
- if (name.Len() <= len)
- return true;
- if (MyStringCompareNoCase_N(name, reservedName, len) != 0)
- return true;
- wchar_t c = name[len];
- if (c < L'0' || c > L'9')
- return true;
- return CheckTail(name, len + 1);
-}
+ "CON", "PRN", "AUX", "NUL",
+ "COM", "LPT"
+};
static bool IsSupportedName(const UString &name)
{
for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)
{
- const wchar_t *reservedName = g_ReservedNames[i];
+ const char *reservedName = g_ReservedNames[i];
unsigned len = MyStringLen(reservedName);
if (name.Len() < len)
continue;
- if (MyStringCompareNoCase_N(name, reservedName, len) != 0)
+ if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))
continue;
- if (!CheckTail(name, len))
- return false;
+ if (i >= g_ReservedWithNum_Index)
+ {
+ wchar_t c = name[len];
+ if (c < L'0' || c > L'9')
+ continue;
+ len++;
+ }
+ for (;;)
+ {
+ wchar_t c = name[len++];
+ if (c == 0 || c == '.')
+ return false;
+ if (c != ' ')
+ break;
+ }
}
- if (!CheckNameNum(name, L"COM"))
- return false;
- return CheckNameNum(name, L"LPT");
+ return true;
+}
+
+static void CorrectUnsupportedName(UString &name)
+{
+ if (!IsSupportedName(name))
+ name.InsertAtFront(L'_');
}
#endif
-static UString GetCorrectFileName(const UString &path, bool repaceColon)
+static void Correct_PathPart(UString &s)
+{
+ // "." and ".."
+ if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0))
+ s.Empty();
+ #ifdef _WIN32
+ else
+ ReplaceIncorrectChars(s);
+ #endif
+}
+
+// static const wchar_t *k_EmptyReplaceName = L"[]";
+static const wchar_t k_EmptyReplaceName = L'_';
+
+UString Get_Correct_FsFile_Name(const UString &name)
{
- if (path == L".." || path == L".")
- return UString();
- return ReplaceIncorrectChars(path, repaceColon);
+ UString res = name;
+ Correct_PathPart(res);
+
+ #ifdef _WIN32
+ CorrectUnsupportedName(res);
+ #endif
+
+ if (res.IsEmpty())
+ res = k_EmptyReplaceName;
+ return res;
}
-void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon)
+
+void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir)
{
- for (unsigned i = 0; i < pathParts.Size();)
+ unsigned i = 0;
+
+ if (absIsAllowed)
{
- UString &s = pathParts[i];
- #ifdef _WIN32
- bool needReplaceColon = (replaceAltStreamColon || i != pathParts.Size() - 1);
- if (i == 0 && isPathFromRoot && NWindows::NFile::NName::IsDrivePath(s))
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ bool isDrive = false;
+ #endif
+ if (parts[0].IsEmpty())
{
- UString s2 = s[0];
- s2 += L'_';
- s2 += GetCorrectFileName(s.Ptr(2), needReplaceColon);
- s = s2;
+ i = 1;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (parts.Size() > 1 && parts[1].IsEmpty())
+ {
+ i = 2;
+ if (parts.Size() > 2 && parts[2] == L"?")
+ {
+ i = 3;
+ if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
+ {
+ isDrive = true;
+ i = 4;
+ }
+ }
+ }
+ #endif
}
- else
- s = GetCorrectFileName(s, needReplaceColon);
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ else if (NWindows::NFile::NName::IsDrivePath2(parts[0]))
+ {
+ isDrive = true;
+ i = 1;
+ }
+
+ if (isDrive)
+ {
+ // we convert "c:name" to "c:\name", if absIsAllowed path.
+ const UString &ds = parts[i - 1];
+ if (ds.Len() != 2)
+ {
+ UString s = ds.Ptr(2);
+ parts.Insert(i, s);
+ }
+ }
+ #endif
+ }
+
+ for (; i < parts.Size();)
+ {
+ UString &s = parts[i];
+
+ #ifdef _WIN32
+ Correct_PathPart(s);
#endif
if (s.IsEmpty())
- pathParts.Delete(i);
+ {
+ if (isDir || i != parts.Size() - 1)
+ {
+ parts.Delete(i);
+ continue;
+ }
+ s = k_EmptyReplaceName;
+ }
else
{
#ifdef _WIN32
- if (!IsSupportedName(s))
- s = (UString)L"_" + s;
+ CorrectUnsupportedName(s);
#endif
- i++;
}
+
+ i++;
}
-}
-
-UString MakePathNameFromParts(const UStringVector &parts)
-{
- UString result;
- FOR_VECTOR (i, parts)
- {
- if (i != 0)
- result += WCHAR_PATH_SEPARATOR;
- result += parts[i];
- }
- return result;
-}
-
-static const wchar_t *k_EmptyReplaceName = L"[]";
-void Correct_IfEmptyLastPart(UStringVector &parts)
-{
- if (parts.IsEmpty())
- parts.Add(k_EmptyReplaceName);
- else
+ if (!isDir)
{
- UString &s = parts.Back();
- if (s.IsEmpty())
- s = k_EmptyReplaceName;
+ if (parts.IsEmpty())
+ parts.Add(k_EmptyReplaceName);
+ else
+ {
+ UString &s = parts.Back();
+ if (s.IsEmpty())
+ s = k_EmptyReplaceName;
+ }
}
}
-UString GetCorrectFsPath(const UString &path)
+UString MakePathFromParts(const UStringVector &parts)
{
- UString res = GetCorrectFileName(path, true);
- #ifdef _WIN32
- if (!IsSupportedName(res))
- res = (UString)L"_" + res;
- #endif
- if (res.IsEmpty())
- res = k_EmptyReplaceName;
- return res;
-}
-
-UString GetCorrectFullFsPath(const UString &path)
-{
- UStringVector parts;
- SplitPathToParts(path, parts);
+ UString s;
FOR_VECTOR (i, parts)
{
- UString &s = parts[i];
- #ifdef _WIN32
- while (!s.IsEmpty() && (s.Back() == '.' || s.Back() == ' '))
- s.DeleteBack();
- if (!IsSupportedName(s))
- s.InsertAtFront(L'_');
- #endif
+ if (i != 0)
+ s.Add_PathSepar();
+ s += parts[i];
}
- return MakePathNameFromParts(parts);
+ return s;
}
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h
index 751248a9..a52a1f4a 100644
--- a/CPP/7zip/UI/Common/ExtractingFilePath.h
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.h
@@ -5,17 +5,15 @@
#include "../../../Common/MyString.h"
-UString MakePathNameFromParts(const UStringVector &parts);
+#ifdef _WIN32
+void Correct_AltStream_Name(UString &s);
+#endif
-/* for WIN32:
- if (isRoot == true), and pathParts[0] contains path like "c:name",
- it thinks that "c:" is drive prefix (it's not ":name alt stream) and
- the function changes part to c_name */
-void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon);
+// replaces unsuported characters, and replaces "." , ".." and "" to "[]"
+UString Get_Correct_FsFile_Name(const UString &name);
-UString GetCorrectFsPath(const UString &path);
-UString GetCorrectFullFsPath(const UString &path);
+void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir);
-void Correct_IfEmptyLastPart(UStringVector &parts);
+UString MakePathFromParts(const UStringVector &parts);
#endif
diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp
index 6abe59ac..c33f837f 100644
--- a/CPP/7zip/UI/Common/HashCalc.cpp
+++ b/CPP/7zip/UI/Common/HashCalc.cpp
@@ -30,23 +30,17 @@ public:
~CHashMidBuf() { ::MidFree(_data); }
};
-struct CEnumDirItemCallback_Hash: public IEnumDirItemCallback
-{
- IHashCallbackUI *Callback;
-
- HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)
- {
- return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir);
- }
-};
-
-static const wchar_t *k_DefaultHashMethod = L"CRC32";
+static const char *k_DefaultHashMethod = "CRC32";
HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)
{
UStringVector names = hashMethods;
if (names.IsEmpty())
- names.Add(k_DefaultHashMethod);
+ {
+ UString s;
+ s.SetFromAscii(k_DefaultHashMethod);
+ names.Add(s);
+ }
CRecordVector<CMethodId> ids;
CObjectVector<COneMethodInfo> methods;
@@ -60,7 +54,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto
if (m.MethodName.IsEmpty())
m.MethodName = k_DefaultHashMethod;
- if (m.MethodName == L"*")
+ if (m.MethodName == "*")
{
CRecordVector<CMethodId> tempMethods;
GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);
@@ -68,7 +62,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto
ids.Clear();
FOR_VECTOR (t, tempMethods)
{
- int index = ids.AddToUniqueSorted(tempMethods[t]);
+ unsigned index = ids.AddToUniqueSorted(tempMethods[t]);
if (ids.Size() != methods.Size())
methods.Insert(index, m);
}
@@ -80,7 +74,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto
CMethodId id;
if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id))
return E_NOTIMPL;
- int index = ids.AddToUniqueSorted(id);
+ unsigned index = ids.AddToUniqueSorted(id);
if (ids.Size() != methods.Size())
methods.Insert(index, m);
}
@@ -89,7 +83,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto
for (i = 0; i < ids.Size(); i++)
{
CMyComPtr<IHasher> hasher;
- UString name;
+ AString name;
RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher));
if (!hasher)
throw "Can't create hasher";
@@ -98,9 +92,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto
CMyComPtr<ICompressSetCoderProperties> scp;
hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
if (scp)
- {
RINOK(m.SetCoderProps(scp, NULL));
- }
}
UInt32 digestSize = hasher->GetDigestSize();
if (digestSize > k_HashCalc_DigestSize_Max)
@@ -109,9 +101,10 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto
h.Hasher = hasher;
h.Name = name;
h.DigestSize = digestSize;
- for (int i = 0; i < k_HashCalc_NumGroups; i++)
+ for (unsigned i = 0; i < k_HashCalc_NumGroups; i++)
memset(h.Digests[i], 0, digestSize);
}
+
return S_OK;
}
@@ -203,13 +196,12 @@ HRESULT HashCalc(
DECL_EXTERNAL_CODECS_LOC_VARS
const NWildcard::CCensor &censor,
const CHashOptions &options,
- UString &errorInfo,
+ AString &errorInfo,
IHashCallbackUI *callback)
{
CDirItems dirItems;
+ dirItems.Callback = callback;
- UInt64 numErrors = 0;
- UInt64 totalBytes = 0;
if (options.StdInMode)
{
CDirItem di;
@@ -222,34 +214,29 @@ HRESULT HashCalc(
}
else
{
- CEnumDirItemCallback_Hash enumCallback;
- enumCallback.Callback = callback;
RINOK(callback->StartScanning());
dirItems.ScanAltStreams = options.AltStreamsMode;
+
HRESULT res = EnumerateItems(censor,
options.PathMode,
UString(),
- dirItems, &enumCallback);
- totalBytes = dirItems.TotalSize;
- FOR_VECTOR (i, dirItems.ErrorPaths)
- {
- RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i]));
- }
- numErrors = dirItems.ErrorPaths.Size();
+ dirItems);
+
if (res != S_OK)
{
if (res != E_ABORT)
- errorInfo = L"Scanning error";
+ errorInfo = "Scanning error";
return res;
}
- RINOK(callback->FinishScanning());
+ RINOK(callback->FinishScanning(dirItems.Stat));
}
unsigned i;
CHashBundle hb;
RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods));
hb.Init();
- hb.NumErrors = numErrors;
+
+ hb.NumErrors = dirItems.Stat.NumErrors;
if (options.StdInMode)
{
@@ -257,7 +244,7 @@ HRESULT HashCalc(
}
else
{
- RINOK(callback->SetTotal(totalBytes));
+ RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes()));
}
const UInt32 kBufSize = 1 << 15;
@@ -289,8 +276,8 @@ HRESULT HashCalc(
path = dirItems.GetLogPath(i);
if (!isDir)
{
- UString phyPath = dirItems.GetPhyPath(i);
- if (!inStreamSpec->OpenShared(us2fs(phyPath), options.OpenShareForWrite))
+ FString phyPath = dirItems.GetPhyPath(i);
+ if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite))
{
HRESULT res = callback->OpenFileError(phyPath, ::GetLastError());
hb.NumErrors++;
@@ -327,14 +314,15 @@ HRESULT HashCalc(
}
-static inline char GetHex(Byte value)
+static inline char GetHex(unsigned v)
{
- return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+ return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
}
void AddHashHexToString(char *dest, const Byte *data, UInt32 size)
{
dest[size * 2] = 0;
+
if (!data)
{
for (UInt32 i = 0; i < size; i++)
@@ -345,17 +333,19 @@ void AddHashHexToString(char *dest, const Byte *data, UInt32 size)
}
return;
}
+
int step = 2;
if (size <= 8)
{
step = -2;
dest += size * 2 - 2;
}
+
for (UInt32 i = 0; i < size; i++)
{
- Byte b = data[i];
- dest[0] = GetHex((Byte)((b >> 4) & 0xF));
- dest[1] = GetHex((Byte)(b & 0xF));
+ unsigned b = data[i];
+ dest[0] = GetHex((b >> 4) & 0xF);
+ dest[1] = GetHex(b & 0xF);
dest += step;
}
}
diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h
index 3d7b9bc8..38908e2e 100644
--- a/CPP/7zip/UI/Common/HashCalc.h
+++ b/CPP/7zip/UI/Common/HashCalc.h
@@ -8,6 +8,7 @@
#include "../../Common/CreateCoder.h"
#include "../../Common/MethodProps.h"
+#include "DirItem.h"
#include "Property.h"
const unsigned k_HashCalc_DigestSize_Max = 64;
@@ -25,7 +26,7 @@ enum
struct CHasherState
{
CMyComPtr<IHasher> Hasher;
- UString Name;
+ AString Name;
UInt32 DigestSize;
Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max];
};
@@ -42,8 +43,8 @@ struct CHashBundle: public IHashCalc
{
CObjectVector<CHasherState> Hashers;
- UInt64 NumFiles;
UInt64 NumDirs;
+ UInt64 NumFiles;
UInt64 NumAltStreams;
UInt64 FilesSize;
UInt64 AltStreamsSize;
@@ -55,7 +56,7 @@ struct CHashBundle: public IHashCalc
void Init()
{
- NumFiles = NumDirs = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
+ NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
}
void InitForNewFile();
@@ -65,21 +66,20 @@ struct CHashBundle: public IHashCalc
};
#define INTERFACE_IHashCallbackUI(x) \
+ INTERFACE_IDirItemsCallback(x) \
virtual HRESULT StartScanning() x; \
- virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \
- virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \
- virtual HRESULT FinishScanning() x; \
+ virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \
virtual HRESULT SetNumFiles(UInt64 numFiles) x; \
virtual HRESULT SetTotal(UInt64 size) x; \
virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \
virtual HRESULT CheckBreak() x; \
virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \
virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \
- virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \
+ virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \
virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \
virtual HRESULT AfterLastFile(const CHashBundle &hb) x; \
-struct IHashCallbackUI
+struct IHashCallbackUI: public IDirItemsCallback
{
INTERFACE_IHashCallbackUI(=0)
};
@@ -99,7 +99,7 @@ HRESULT HashCalc(
DECL_EXTERNAL_CODECS_LOC_VARS
const NWildcard::CCensor &censor,
const CHashOptions &options,
- UString &errorInfo,
+ AString &errorInfo,
IHashCallbackUI *callback);
void AddHashHexToString(char *dest, const Byte *data, UInt32 size);
diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h
index 7bb85279..c456c862 100644
--- a/CPP/7zip/UI/Common/IFileExtractCallback.h
+++ b/CPP/7zip/UI/Common/IFileExtractCallback.h
@@ -7,6 +7,9 @@
#include "../../IDecl.h"
+#include "LoadCodecs.h"
+#include "OpenArchive.h"
+
namespace NOverwriteAnswer
{
enum EEnum
@@ -20,35 +23,74 @@ namespace NOverwriteAnswer
};
}
+
+/* ---------- IFolderArchiveExtractCallback ----------
+is implemented by
+ Console/ExtractCallbackConsole.h CExtractCallbackConsole
+ FileManager/ExtractCallback.h CExtractCallbackImp
+ FAR/ExtractEngine.cpp CExtractCallBackImp: (QueryInterface is not supported)
+
+IID_IFolderArchiveExtractCallback is requested by:
+ - Agent/ArchiveFolder.cpp
+ CAgentFolder::CopyTo(..., IFolderOperationsExtractCallback *callback)
+ is sent to IArchiveFolder::Extract()
+
+ - FileManager/PanelCopy.cpp
+ CPanel::CopyTo(), if (options->testMode)
+ is sent to IArchiveFolder::Extract()
+
+ IFolderArchiveExtractCallback is used by Common/ArchiveExtractCallback.cpp
+*/
+
+#define INTERFACE_IFolderArchiveExtractCallback(x) \
+ STDMETHOD(AskOverwrite)( \
+ const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \
+ const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \
+ Int32 *answer) x; \
+ STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position) x; \
+ STDMETHOD(MessageError)(const wchar_t *message) x; \
+ STDMETHOD(SetOperationResult)(Int32 opRes, Int32 encrypted) x; \
+
DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07)
{
-public:
- STDMETHOD(AskOverwrite)(
- const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
- const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
- Int32 *answer) PURE;
- STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE;
- STDMETHOD(MessageError)(const wchar_t *message) PURE;
- STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE;
+ INTERFACE_IFolderArchiveExtractCallback(PURE)
+};
+
+#define INTERFACE_IFolderArchiveExtractCallback2(x) \
+ STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 encrypted, const wchar_t *name) x; \
+
+DECL_INTERFACE_SUB(IFolderArchiveExtractCallback2, IUnknown, 0x01, 0x08)
+{
+ INTERFACE_IFolderArchiveExtractCallback2(PURE)
};
+/* ---------- IExtractCallbackUI ----------
+is implemented by
+ Console/ExtractCallbackConsole.h CExtractCallbackConsole
+ FileManager/ExtractCallback.h CExtractCallbackImp
+*/
+
+#ifdef _NO_CRYPTO
+ #define INTERFACE_IExtractCallbackUI_Crypto(x)
+#else
+ #define INTERFACE_IExtractCallbackUI_Crypto(x) \
+ virtual HRESULT SetPassword(const UString &password) x;
+#endif
+
+#define INTERFACE_IExtractCallbackUI(x) \
+ virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) x; \
+ virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \
+ virtual HRESULT ThereAreNoFiles() x; \
+ virtual HRESULT ExtractResult(HRESULT result) x; \
+ INTERFACE_IExtractCallbackUI_Crypto(x)
+
struct IExtractCallbackUI: IFolderArchiveExtractCallback
{
- virtual HRESULT BeforeOpen(const wchar_t *name) = 0;
- virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0;
- virtual HRESULT SetError(int level, const wchar_t *name,
- UInt32 errorFlags, const wchar_t *errors,
- UInt32 warningFlags, const wchar_t *warnings) = 0;
- virtual HRESULT ThereAreNoFiles() = 0;
- virtual HRESULT ExtractResult(HRESULT result) = 0;
- virtual HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) = 0;
-
- #ifndef _NO_CRYPTO
- virtual HRESULT SetPassword(const UString &password) = 0;
- #endif
+ INTERFACE_IExtractCallbackUI(PURE)
};
+
#define INTERFACE_IGetProp(x) \
STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \
@@ -61,7 +103,7 @@ DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20)
STDMETHOD(UseExtractToStream)(Int32 *res) x; \
STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \
STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \
- STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, bool encrypted) x; \
+ STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, Int32 encrypted) x; \
DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)
{
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index bbdf0fe8..696b6749 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -1,5 +1,36 @@
// LoadCodecs.cpp
+/*
+EXTERNAL_CODECS
+---------------
+ CCodecs::Load() tries to detect the directory with plugins.
+ It stops the checking, if it can find any of the following items:
+ - 7z.dll file
+ - "Formats" subdir
+ - "Codecs" subdir
+ The order of check:
+ 1) directory of client executable
+ 2) WIN32: directory for REGISTRY item [HKEY_*\Software\7-Zip\Path**]
+ The order for HKEY_* : Path** :
+ - HKEY_CURRENT_USER : PathXX
+ - HKEY_LOCAL_MACHINE : PathXX
+ - HKEY_CURRENT_USER : Path
+ - HKEY_LOCAL_MACHINE : Path
+ PathXX is Path32 in 32-bit code
+ PathXX is Path64 in 64-bit code
+
+
+EXPORT_CODECS
+-------------
+ if (EXTERNAL_CODECS) is defined, then the code exports internal
+ codecs of client from CCodecs object to external plugins.
+ 7-Zip doesn't use that feature. 7-Zip uses the scheme:
+ - client application without internal plugins.
+ - 7z.dll module contains all (or almost all) plugins.
+ 7z.dll can use codecs from another plugins, if required.
+*/
+
+
#include "StdAfx.h"
#include "../../../../C/7zVersion.h"
@@ -23,13 +54,21 @@ using namespace NWindows;
#ifdef EXTERNAL_CODECS
-#include "../../../Windows/FileFind.h"
-#include "../../../Windows/DLL.h"
+// #define EXPORT_CODECS
+
+#endif
+
#ifdef NEW_FOLDER_INTERFACE
+extern HINSTANCE g_hInstance;
#include "../../../Windows/ResourceString.h"
static const UINT kIconTypesResId = 100;
#endif
+#ifdef EXTERNAL_CODECS
+
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/DLL.h"
+
#ifdef _WIN32
#include "../../../Windows/FileName.h"
#include "../../../Windows/Registry.h"
@@ -37,13 +76,18 @@ static const UINT kIconTypesResId = 100;
using namespace NFile;
-#ifdef _WIN32
-extern HINSTANCE g_hInstance;
-#endif
#define kCodecsFolderName FTEXT("Codecs")
#define kFormatsFolderName FTEXT("Formats")
-static CFSTR kMainDll = FTEXT("7z.dll");
+
+
+static CFSTR kMainDll =
+ // #ifdef _WIN32
+ FTEXT("7z.dll");
+ // #else
+ // FTEXT("7z.so");
+ // #endif
+
#ifdef _WIN32
@@ -77,7 +121,7 @@ static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)
#endif // EXTERNAL_CODECS
-static const unsigned kNumArcsMax = 48;
+static const unsigned kNumArcsMax = 64;
static unsigned g_NumArcs = 0;
static const CArcInfo *g_Arcs[kNumArcsMax];
@@ -118,7 +162,7 @@ static void SplitString(const UString &srcString, UStringVector &destStrings)
int CArcInfoEx::FindExtension(const UString &ext) const
{
FOR_VECTOR (i, Exts)
- if (ext.IsEqualToNoCase(Exts[i].Ext))
+ if (ext.IsEqualTo_NoCase(Exts[i].Ext))
return i;
return -1;
}
@@ -182,6 +226,7 @@ static FString GetBaseFolderPrefixFromRegistry()
return moduleFolderPrefix;
}
+
static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,
PROPID propId, CLSID &clsId, bool &isAssigned)
{
@@ -203,14 +248,18 @@ static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 in
HRESULT CCodecs::LoadCodecs()
{
CCodecLib &lib = Libs.Back();
+
+ lib.CreateDecoder = (Func_CreateDecoder)lib.Lib.GetProc("CreateDecoder");
+ lib.CreateEncoder = (Func_CreateEncoder)lib.Lib.GetProc("CreateEncoder");
lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty");
+
if (lib.GetMethodProperty)
{
UInt32 numMethods = 1;
- Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods");
- if (getNumberOfMethodsFunc)
+ Func_GetNumberOfMethods getNumberOfMethods = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods");
+ if (getNumberOfMethods)
{
- RINOK(getNumberOfMethodsFunc(&numMethods));
+ RINOK(getNumberOfMethods(&numMethods));
}
for (UInt32 i = 0; i < numMethods; i++)
{
@@ -226,10 +275,10 @@ HRESULT CCodecs::LoadCodecs()
Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers");
if (getHashers)
{
- RINOK(getHashers(&lib.Hashers));
- if (lib.Hashers)
+ RINOK(getHashers(&lib.ComHashers));
+ if (lib.ComHashers)
{
- UInt32 numMethods = lib.Hashers->GetNumHashers();
+ UInt32 numMethods = lib.ComHashers->GetNumHashers();
for (UInt32 i = 0; i < numMethods; i++)
{
CDllHasherInfo info;
@@ -239,6 +288,7 @@ HRESULT CCodecs::LoadCodecs()
}
}
}
+
return S_OK;
}
@@ -295,7 +345,7 @@ static HRESULT GetProp_String(
NCOM::CPropVariant prop;
RINOK(GetProp(getProp, getProp2, index, propID, prop));
if (prop.vt == VT_BSTR)
- res = prop.bstrVal;
+ res.SetFromBstr(prop.bstrVal);
else if (prop.vt != VT_EMPTY)
return E_FAIL;
return S_OK;
@@ -416,54 +466,6 @@ HRESULT CCodecs::LoadFormats()
return S_OK;
}
-#ifdef NEW_FOLDER_INTERFACE
-void CCodecIcons::LoadIcons(HMODULE m)
-{
- UString iconTypes;
- MyLoadString(m, kIconTypesResId, iconTypes);
- UStringVector pairs;
- SplitString(iconTypes, pairs);
- FOR_VECTOR (i, pairs)
- {
- const UString &s = pairs[i];
- int pos = s.Find(L':');
- CIconPair iconPair;
- iconPair.IconIndex = -1;
- if (pos < 0)
- pos = s.Len();
- else
- {
- UString num = s.Ptr(pos + 1);
- if (!num.IsEmpty())
- {
- const wchar_t *end;
- iconPair.IconIndex = ConvertStringToUInt32(num, &end);
- if (*end != 0)
- continue;
- }
- }
- iconPair.Ext = s.Left(pos);
- IconPairs.Add(iconPair);
- }
-}
-
-bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
-{
- iconIndex = -1;
- FOR_VECTOR (i, IconPairs)
- {
- const CIconPair &pair = IconPairs[i];
- if (ext.IsEqualToNoCase(pair.Ext))
- {
- iconIndex = pair.IconIndex;
- return true;
- }
- }
- return false;
-}
-
-#endif // EXTERNAL_CODECS
-
#ifdef _7ZIP_LARGE_PAGES
extern "C"
{
@@ -471,21 +473,28 @@ extern "C"
}
#endif
-HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll)
+HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK)
{
+ if (loadedOK)
+ *loadedOK = false;
+
if (needCheckDll)
{
- NDLL::CLibrary library;
- if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
+ NDLL::CLibrary lib;
+ if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
return S_OK;
}
- Libs.Add(CCodecLib());
+
+ Libs.AddNew();
CCodecLib &lib = Libs.Back();
lib.Path = dllPath;
bool used = false;
HRESULT res = S_OK;
+
if (lib.Lib.Load(dllPath))
{
+ if (loadedOK)
+ *loadedOK = true;
#ifdef NEW_FOLDER_INTERFACE
lib.LoadIcons();
#endif
@@ -521,8 +530,10 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll)
}
}
}
+
if (!used)
Libs.DeleteBack();
+
return res;
}
@@ -539,17 +550,42 @@ HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix)
return S_OK;
}
-#endif
+void CCodecs::CloseLibs()
+{
+ // OutputDebugStringA("~CloseLibs start");
+ /*
+ WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected,
+ if it's called from another FreeLibrary() call.
+ So we need to call FreeLibrary() before global destructors.
+
+ Also we free global links from DLLs to object of this module before CLibrary::Free() call.
+ */
+
+ FOR_VECTOR(i, Libs)
+ {
+ const CCodecLib &lib = Libs[i];
+ if (lib.SetCodecs)
+ lib.SetCodecs(NULL);
+ }
+
+ // OutputDebugStringA("~CloseLibs after SetCodecs");
+ Libs.Clear();
+ // OutputDebugStringA("~CloseLibs end");
+}
+
+#endif // EXTERNAL_CODECS
+
HRESULT CCodecs::Load()
{
#ifdef NEW_FOLDER_INTERFACE
- InternalIcons.LoadIcons(g_hInstance);
+ InternalIcons.LoadIcons(g_hInstance);
#endif
Formats.Clear();
#ifdef EXTERNAL_CODECS
+ MainDll_ErrorPath.Empty();
Codecs.Clear();
Hashers.Clear();
#endif
@@ -593,11 +629,46 @@ HRESULT CCodecs::Load()
#ifdef EXTERNAL_CODECS
const FString baseFolder = GetBaseFolderPrefixFromRegistry();
- RINOK(LoadDll(baseFolder + kMainDll, false));
+ {
+ bool loadedOK;
+ RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK));
+ if (!loadedOK)
+ MainDll_ErrorPath = kMainDll;
+ }
RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR));
RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR));
+
+ NeedSetLibCodecs = true;
+
+ if (Libs.Size() == 0)
+ NeedSetLibCodecs = false;
+ else if (Libs.Size() == 1)
+ {
+ // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module.
+ #ifndef EXPORT_CODECS
+ if (g_NumArcs == 0)
+ NeedSetLibCodecs = false;
+ #endif
+ }
+
+ if (NeedSetLibCodecs)
+ {
+ /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c)
+ old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */
+
+ FOR_VECTOR(i, Libs)
+ {
+ CCodecLib &lib = Libs[i];
+ lib.SetCodecs = (Func_SetCodecs)lib.Lib.GetProc("SetCodecs");
+ if (lib.SetCodecs)
+ {
+ RINOK(lib.SetCodecs(this));
+ }
+ }
+ }
+
#endif
-
+
return S_OK;
}
@@ -605,14 +676,13 @@ HRESULT CCodecs::Load()
int CCodecs::FindFormatForArchiveName(const UString &arcPath) const
{
- int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);
- int dotPos = arcPath.ReverseFind(L'.');
- if (dotPos < 0 || dotPos < slashPos)
+ int dotPos = arcPath.ReverseFind_Dot();
+ if (dotPos <= arcPath.ReverseFind_PathSepar())
return -1;
const UString ext = arcPath.Ptr(dotPos + 1);
if (ext.IsEmpty())
return -1;
- if (ext.IsEqualToNoCase(L"exe"))
+ if (ext.IsEqualTo_Ascii_NoCase("exe"))
return -1;
FOR_VECTOR (i, Formats)
{
@@ -640,7 +710,7 @@ int CCodecs::FindFormatForExtension(const UString &ext) const
int CCodecs::FindFormatForArchiveType(const UString &arcType) const
{
FOR_VECTOR (i, Formats)
- if (Formats[i].Name.IsEqualToNoCase(arcType))
+ if (Formats[i].Name.IsEqualTo_NoCase(arcType))
return i;
return -1;
}
@@ -650,7 +720,7 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma
formatIndices.Clear();
for (unsigned pos = 0; pos < arcType.Len();)
{
- int pos2 = arcType.Find('.', pos);
+ int pos2 = arcType.Find(L'.', pos);
if (pos2 < 0)
pos2 = arcType.Len();
const UString name = arcType.Mid(pos, pos2 - pos);
@@ -671,6 +741,56 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma
#endif // _SFX
+#ifdef NEW_FOLDER_INTERFACE
+
+void CCodecIcons::LoadIcons(HMODULE m)
+{
+ UString iconTypes;
+ MyLoadString(m, kIconTypesResId, iconTypes);
+ UStringVector pairs;
+ SplitString(iconTypes, pairs);
+ FOR_VECTOR (i, pairs)
+ {
+ const UString &s = pairs[i];
+ int pos = s.Find(L':');
+ CIconPair iconPair;
+ iconPair.IconIndex = -1;
+ if (pos < 0)
+ pos = s.Len();
+ else
+ {
+ UString num = s.Ptr(pos + 1);
+ if (!num.IsEmpty())
+ {
+ const wchar_t *end;
+ iconPair.IconIndex = ConvertStringToUInt32(num, &end);
+ if (*end != 0)
+ continue;
+ }
+ }
+ iconPair.Ext = s.Left(pos);
+ IconPairs.Add(iconPair);
+ }
+}
+
+bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
+{
+ iconIndex = -1;
+ FOR_VECTOR (i, IconPairs)
+ {
+ const CIconPair &pair = IconPairs[i];
+ if (ext.IsEqualTo_NoCase(pair.Ext))
+ {
+ iconIndex = pair.IconIndex;
+ return true;
+ }
+ }
+ return false;
+}
+
+#endif // NEW_FOLDER_INTERFACE
+
+
#ifdef EXTERNAL_CODECS
// #define EXPORT_CODECS
@@ -678,7 +798,8 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma
#ifdef EXPORT_CODECS
extern unsigned g_NumCodecs;
-STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);
+STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject);
+STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject);
STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
#define NUM_EXPORT_CODECS g_NumCodecs
@@ -694,7 +815,7 @@ STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
#endif // EXPORT_CODECS
-STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)
+STDMETHODIMP CCodecs::GetNumMethods(UInt32 *numMethods)
{
*numMethods = NUM_EXPORT_CODECS
#ifdef EXTERNAL_CODECS
@@ -718,13 +839,14 @@ STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *valu
propID == NMethodPropID::kEncoderIsAssigned)
{
NCOM::CPropVariant prop;
- prop = (propID == NMethodPropID::kDecoderIsAssigned) ?
+ prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ?
ci.DecoderIsAssigned :
- ci.EncoderIsAssigned;
+ ci.EncoderIsAssigned);
prop.Detach(value);
return S_OK;
}
- return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);
+ const CCodecLib &lib = Libs[ci.LibIndex];
+ return lib.GetMethodProperty(ci.CodecIndex, propID, value);
#else
return E_FAIL;
#endif
@@ -734,12 +856,18 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
{
#ifdef EXPORT_CODECS
if (index < g_NumCodecs)
- return CreateCoder2(false, index, iid, coder);
+ return CreateDecoder(index, iid, coder);
#endif
+
#ifdef EXTERNAL_CODECS
const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
if (ci.DecoderIsAssigned)
- return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);
+ {
+ const CCodecLib &lib = Libs[ci.LibIndex];
+ if (lib.CreateDecoder)
+ return lib.CreateDecoder(index - NUM_EXPORT_CODECS, iid, (void **)coder);
+ return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
+ }
return S_OK;
#else
return E_FAIL;
@@ -750,12 +878,18 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
{
#ifdef EXPORT_CODECS
if (index < g_NumCodecs)
- return CreateCoder2(true, index, iid, coder);
+ return CreateEncoder(index, iid, coder);
#endif
+
#ifdef EXTERNAL_CODECS
const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
if (ci.EncoderIsAssigned)
- return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);
+ {
+ const CCodecLib &lib = Libs[ci.LibIndex];
+ if (lib.CreateEncoder)
+ return lib.CreateEncoder(index - NUM_EXPORT_CODECS, iid, (void **)coder);
+ return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
+ }
return S_OK;
#else
return E_FAIL;
@@ -781,7 +915,7 @@ STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *va
#ifdef EXTERNAL_CODECS
const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
- return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value);
+ return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value);
#else
return E_FAIL;
#endif
@@ -795,18 +929,19 @@ STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher)
#endif
#ifdef EXTERNAL_CODECS
const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
- return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher);
+ return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher);
#else
return E_FAIL;
#endif
}
-int CCodecs::GetCodecLibIndex(UInt32 index)
+int CCodecs::GetCodec_LibIndex(UInt32 index) const
{
#ifdef EXPORT_CODECS
if (index < g_NumCodecs)
return -1;
#endif
+
#ifdef EXTERNAL_CODECS
const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
return ci.LibIndex;
@@ -821,6 +956,7 @@ int CCodecs::GetHasherLibIndex(UInt32 index)
if (index < g_NumHashers)
return -1;
#endif
+
#ifdef EXTERNAL_CODECS
const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
return ci.LibIndex;
@@ -829,27 +965,62 @@ int CCodecs::GetHasherLibIndex(UInt32 index)
#endif
}
-bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)
+bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const
{
#ifdef EXPORT_CODECS
if (index < g_NumCodecs)
{
NCOM::CPropVariant prop;
- if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)
- if (prop.vt != VT_EMPTY)
- return true;
+ if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK)
+ {
+ if (prop.vt == VT_BOOL)
+ return VARIANT_BOOLToBool(prop.boolVal);
+ }
return false;
}
#endif
+
#ifdef EXTERNAL_CODECS
- const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
- return ci.EncoderIsAssigned;
+ return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned;
#else
return false;
#endif
}
-HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)
+bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumCodecs)
+ {
+ NCOM::CPropVariant prop;
+ if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK)
+ {
+ if (prop.vt == VT_BOOL)
+ return VARIANT_BOOLToBool(prop.boolVal);
+ }
+ return false;
+ }
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned;
+ #else
+ return false;
+ #endif
+}
+
+UInt32 CCodecs::GetCodec_NumStreams(UInt32 index)
+{
+ NCOM::CPropVariant prop;
+ RINOK(GetProperty(index, NMethodPropID::kPackStreams, &prop));
+ if (prop.vt == VT_UI4)
+ return (UInt32)prop.ulVal;
+ if (prop.vt == VT_EMPTY)
+ return 1;
+ return 0;
+}
+
+HRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id)
{
NCOM::CPropVariant prop;
RINOK(GetProperty(index, NMethodPropID::kID, &prop));
@@ -859,32 +1030,33 @@ HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)
return S_OK;
}
-UString CCodecs::GetCodecName(UInt32 index)
+AString CCodecs::GetCodec_Name(UInt32 index)
{
- UString s;
+ AString s;
NCOM::CPropVariant prop;
if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
if (prop.vt == VT_BSTR)
- s = prop.bstrVal;
+ s.SetFromWStr_if_Ascii(prop.bstrVal);
return s;
}
UInt64 CCodecs::GetHasherId(UInt32 index)
{
NCOM::CPropVariant prop;
- RINOK(GetHasherProp(index, NMethodPropID::kID, &prop));
+ if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK)
+ return 0;
if (prop.vt != VT_UI8)
return 0;
return prop.uhVal.QuadPart;
}
-UString CCodecs::GetHasherName(UInt32 index)
+AString CCodecs::GetHasherName(UInt32 index)
{
- UString s;
+ AString s;
NCOM::CPropVariant prop;
if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)
if (prop.vt == VT_BSTR)
- s = prop.bstrVal;
+ s.SetFromWStr_if_Ascii(prop.bstrVal);
return s;
}
diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h
index 5a54d365..ac9eeac7 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.h
+++ b/CPP/7zip/UI/Common/LoadCodecs.h
@@ -3,34 +3,82 @@
#ifndef __LOAD_CODECS_H
#define __LOAD_CODECS_H
+/*
+Client application uses LoadCodecs.* to load plugins to
+CCodecs object, that contains 3 lists of plugins:
+ 1) Formats - internal and external archive handlers
+ 2) Codecs - external codecs
+ 3) Hashers - external hashers
+
+EXTERNAL_CODECS
+---------------
+
+ if EXTERNAL_CODECS is defined, then the code tries to load external
+ plugins from DLL files (shared libraries).
+
+ There are two types of executables in 7-Zip:
+
+ 1) Executable that uses external plugins must be compiled
+ with EXTERNAL_CODECS defined:
+ - 7z.exe, 7zG.exe, 7zFM.exe
+
+ Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h
+ that code is used in plugin module (7z.dll).
+
+ 2) Standalone modules are compiled without EXTERNAL_CODECS:
+ - SFX modules: 7z.sfx, 7zCon.sfx
+ - standalone versions of console 7-Zip: 7za.exe, 7zr.exe
+
+ if EXTERNAL_CODECS is defined, CCodecs class implements interfaces:
+ - ICompressCodecsInfo : for Codecs
+ - IHashers : for Hashers
+
+ The client application can send CCodecs object to each plugin module.
+ And plugin module can use ICompressCodecsInfo or IHashers interface to access
+ another plugins.
+
+ There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin
+ 1) for old versions:
+ a) request ISetCompressCodecsInfo from created archive handler.
+ b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo)
+ 2) for new versions:
+ a) request "SetCodecs" function from DLL file
+ b) call SetCodecs(compressCodecsInfo) function from DLL file
+*/
+
#include "../../../Common/MyBuffer.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/MyString.h"
#include "../../../Common/ComTry.h"
-#include "../../ICoder.h"
-
#ifdef EXTERNAL_CODECS
#include "../../../Windows/DLL.h"
#endif
+#include "../../ICoder.h"
+
+#include "../../Archive/IArchive.h"
+
+
+#ifdef EXTERNAL_CODECS
+
struct CDllCodecInfo
{
- CLSID Encoder;
- CLSID Decoder;
+ unsigned LibIndex;
+ UInt32 CodecIndex;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
- int LibIndex;
- UInt32 CodecIndex;
+ CLSID Encoder;
+ CLSID Decoder;
};
struct CDllHasherInfo
{
- int LibIndex;
+ unsigned LibIndex;
UInt32 HasherIndex;
};
-#include "../../Archive/IArchive.h"
+#endif
struct CArcExtInfo
{
@@ -129,9 +177,8 @@ struct CArcInfoEx
{}
};
-#ifdef EXTERNAL_CODECS
-
#ifdef NEW_FOLDER_INTERFACE
+
struct CCodecIcons
{
struct CIconPair
@@ -140,11 +187,15 @@ struct CCodecIcons
int IconIndex;
};
CObjectVector<CIconPair> IconPairs;
+
void LoadIcons(HMODULE m);
bool FindIconIndex(const UString &ext, int &iconIndex) const;
};
+
#endif
+#ifdef EXTERNAL_CODECS
+
struct CCodecLib
#ifdef NEW_FOLDER_INTERFACE
: public CCodecIcons
@@ -152,56 +203,108 @@ struct CCodecLib
{
NWindows::NDLL::CLibrary Lib;
FString Path;
- Func_GetMethodProperty GetMethodProperty;
+
Func_CreateObject CreateObject;
- CMyComPtr<IHashers> Hashers;
+ Func_GetMethodProperty GetMethodProperty;
+ Func_CreateDecoder CreateDecoder;
+ Func_CreateEncoder CreateEncoder;
+ Func_SetCodecs SetCodecs;
+
+ CMyComPtr<IHashers> ComHashers;
#ifdef NEW_FOLDER_INTERFACE
void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }
#endif
- CCodecLib(): GetMethodProperty(NULL) {}
+ CCodecLib():
+ CreateObject(NULL),
+ GetMethodProperty(NULL),
+ CreateDecoder(NULL),
+ CreateEncoder(NULL),
+ SetCodecs(NULL)
+ {}
};
+
#endif
+
class CCodecs:
#ifdef EXTERNAL_CODECS
- public ICompressCodecsInfo,
- public IHashers,
+ public ICompressCodecsInfo,
+ public IHashers,
#else
- public IUnknown,
+ public IUnknown,
#endif
public CMyUnknownImp
{
+ CLASS_NO_COPY(CCodecs);
public:
#ifdef EXTERNAL_CODECS
+
CObjectVector<CCodecLib> Libs;
- CRecordVector<CDllCodecInfo> Codecs;
- CRecordVector<CDllHasherInfo> Hashers;
+ FString MainDll_ErrorPath;
- #ifdef NEW_FOLDER_INTERFACE
- CCodecIcons InternalIcons;
- #endif
+ void CloseLibs();
+
+ class CReleaser
+ {
+ CLASS_NO_COPY(CReleaser);
+
+ /* CCodecsReleaser object releases CCodecs links.
+ 1) CCodecs is COM object that is deleted when all links to that object will be released/
+ 2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself.
+ To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */
+
+ CCodecs *_codecs;
+
+ public:
+ CReleaser(): _codecs(NULL) {}
+ void Set(CCodecs *codecs) { _codecs = codecs; }
+ ~CReleaser() { if (_codecs) _codecs->CloseLibs(); }
+ };
+
+ bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo
HRESULT LoadCodecs();
HRESULT LoadFormats();
- HRESULT LoadDll(const FString &path, bool needCheckDll);
+ HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL);
HRESULT LoadDllsFromFolder(const FString &folderPrefix);
- HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const
+ HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const
{
return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);
}
+
+ #endif
+
+ #ifdef NEW_FOLDER_INTERFACE
+ CCodecIcons InternalIcons;
#endif
-public:
CObjectVector<CArcInfoEx> Formats;
+
+ #ifdef EXTERNAL_CODECS
+ CRecordVector<CDllCodecInfo> Codecs;
+ CRecordVector<CDllHasherInfo> Hashers;
+ #endif
+
bool CaseSensitiveChange;
bool CaseSensitive;
- CCodecs(): CaseSensitiveChange(false), CaseSensitive(false) {}
+ CCodecs():
+ #ifdef EXTERNAL_CODECS
+ NeedSetLibCodecs(true),
+ #endif
+ CaseSensitiveChange(false),
+ CaseSensitive(false)
+ {}
+
+ ~CCodecs()
+ {
+ // OutputDebugStringA("~CCodecs");
+ }
- const wchar_t *GetFormatNamePtr(int formatIndex)
+ const wchar_t *GetFormatNamePtr(int formatIndex) const
{
return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name;
}
@@ -219,10 +322,10 @@ public:
MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)
- STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods);
+ STDMETHOD(GetNumMethods)(UInt32 *numMethods);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
- STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder);
- STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder);
+ STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder);
+ STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder);
STDMETHOD_(UInt32, GetNumHashers)();
STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);
@@ -234,16 +337,19 @@ public:
#endif // EXTERNAL_CODECS
+
#ifdef EXTERNAL_CODECS
- int GetCodecLibIndex(UInt32 index);
- bool GetCodecEncoderIsAssigned(UInt32 index);
- HRESULT GetCodecId(UInt32 index, UInt64 &id);
- UString GetCodecName(UInt32 index);
+ int GetCodec_LibIndex(UInt32 index) const;
+ bool GetCodec_DecoderIsAssigned(UInt32 index) const;
+ bool GetCodec_EncoderIsAssigned(UInt32 index) const;
+ UInt32 GetCodec_NumStreams(UInt32 index);
+ HRESULT GetCodec_Id(UInt32 index, UInt64 &id);
+ AString GetCodec_Name(UInt32 index);
int GetHasherLibIndex(UInt32 index);
UInt64 GetHasherId(UInt32 index);
- UString GetHasherName(UInt32 index);
+ AString GetHasherName(UInt32 index);
UInt32 GetHasherDigestSize(UInt32 index);
#endif
@@ -261,7 +367,7 @@ public:
COM_TRY_END
}
#ifdef EXTERNAL_CODECS
- return CreateArchiveHandler(ai, (void **)&archive, false);
+ return CreateArchiveHandler(ai, false, (void **)&archive);
#endif
}
@@ -279,8 +385,9 @@ public:
return S_OK;
COM_TRY_END
}
+
#ifdef EXTERNAL_CODECS
- return CreateArchiveHandler(ai, (void **)&archive, true);
+ return CreateArchiveHandler(ai, true, (void **)&archive);
#endif
}
@@ -291,7 +398,7 @@ public:
const CArcInfoEx &arc = Formats[i];
if (!arc.UpdateEnabled)
continue;
- if (arc.Name.IsEqualToNoCase(name))
+ if (arc.Name.IsEqualTo_NoCase(name))
return i;
}
return -1;
@@ -300,4 +407,18 @@ public:
#endif // _SFX
};
+#ifdef EXTERNAL_CODECS
+ #define CREATE_CODECS_OBJECT \
+ CCodecs *codecs = new CCodecs; \
+ CExternalCodecs __externalCodecs; \
+ __externalCodecs.GetCodecs = codecs; \
+ __externalCodecs.GetHashers = codecs; \
+ CCodecs::CReleaser codecsReleaser; \
+ codecsReleaser.Set(codecs);
+#else
+ #define CREATE_CODECS_OBJECT \
+ CCodecs *codecs = new CCodecs; \
+ CMyComPtr<IUnknown> __codecsRef = codecs;
+#endif
+
#endif
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index 2f5d816d..acc10876 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -195,17 +195,13 @@ public:
}
void AddUnknownItem(UInt64 next);
- int FindInsertPos(const CParseItem &item);
+ int FindInsertPos(const CParseItem &item) const;
void AddItem(const CParseItem &item);
- // void Init();
- CHandler()
- {
- _maxEndOffset = 0;
- }
+ CHandler(): _maxEndOffset(0) {}
};
-int CHandler::FindInsertPos(const CParseItem &item)
+int CHandler::FindInsertPos(const CParseItem &item) const
{
unsigned left = 0, right = _items.Size();
while (left != right)
@@ -368,6 +364,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
+
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
numItems = _items.Size();
@@ -429,7 +426,9 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStreamSpec->ReleaseStream();
RINOK(extractCallback->SetOperationResult(opRes));
}
+
return S_OK;
+
COM_TRY_END
}
@@ -458,7 +457,7 @@ HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bo
return S_OK;
}
-HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw()
+HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw()
{
return Archive_GetItemBoolProp(arc, index, kpidIsDir, result);
}
@@ -478,7 +477,7 @@ HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) thro
return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);
}
-static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result)
+static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) throw()
{
NCOM::CPropVariant prop;
result = false;
@@ -524,16 +523,22 @@ static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &res
return S_OK;
}
+#ifndef _SFX
+
HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const
{
if (!GetRawProps)
return E_FAIL;
+ if (index == parent)
+ return S_OK;
UInt32 curIndex = index;
+
+ UString s;
+
bool prevWasAltStream = false;
+
for (;;)
{
- UString s;
-
#ifdef MY_CPU_LE
const void *p;
UInt32 size;
@@ -546,31 +551,59 @@ HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &pa
{
NCOM::CPropVariant prop;
RINOK(Archive->GetProperty(curIndex, kpidName, &prop));
- if (prop.vt == VT_BSTR)
- s = prop.bstrVal;
+ if (prop.vt == VT_BSTR && prop.bstrVal)
+ s.SetFromBstr(prop.bstrVal);
else if (prop.vt == VT_EMPTY)
- s = L"[Content]";
+ s.Empty();
else
return E_FAIL;
}
-
- if (prevWasAltStream)
- parts[0] = s + L":" + parts[0];
- else
- parts.Insert(0, s);
UInt32 curParent = (UInt32)(Int32)-1;
UInt32 parentType = 0;
RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType));
+
+ if (parentType != NParentType::kAltStream)
+ {
+ for (;;)
+ {
+ int pos = s.ReverseFind_PathSepar();
+ if (pos < 0)
+ {
+ break;
+ }
+ parts.Insert(0, s.Ptr(pos + 1));
+ s.DeleteFrom(pos);
+ }
+ }
+
+ parts.Insert(0, s);
+
+ if (prevWasAltStream)
+ {
+ {
+ UString &s = parts[parts.Size() - 2];
+ s += L':';
+ s += parts.Back();
+ }
+ parts.DeleteBack();
+ }
+
if (parent == curParent)
return S_OK;
+
+ prevWasAltStream = false;
+ if (parentType == NParentType::kAltStream)
+ prevWasAltStream = true;
+
if (curParent == (UInt32)(Int32)-1)
return E_FAIL;
- prevWasAltStream = (parentType == NParentType::kAltStream);
curIndex = curParent;
}
}
+#endif
+
HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
{
#ifdef MY_CPU_LE
@@ -585,7 +618,7 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
propType == NPropDataType::kUtf16z)
{
unsigned len = size / 2 - 1;
- wchar_t *s = result.GetBuffer(len);
+ wchar_t *s = result.GetBuf(len);
for (unsigned i = 0; i < len; i++)
{
wchar_t c = GetUi16(p);
@@ -596,7 +629,8 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
#endif
*s++ = c;
}
- result.ReleaseBuffer(len);
+ *s = 0;
+ result.ReleaseBuf_SetLen(len);
if (len != 0)
return S_OK;
}
@@ -605,8 +639,10 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK &&
p && propType == NPropDataType::kUtf16z)
{
+ size -= 2;
UInt32 totalSize = size;
bool isOK = false;
+
{
UInt32 index2 = index;
for (;;)
@@ -617,13 +653,16 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
break;
if (parent == (UInt32)(Int32)-1)
{
+ if (parentType != 0)
+ totalSize += 2;
isOK = true;
break;
}
index2 = parent;
UInt32 size2;
const void *p2;
- if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)
+ if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK &&
+ p2 && propType == NPropDataType::kUtf16z)
break;
totalSize += size2;
}
@@ -631,9 +670,9 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
if (isOK)
{
- wchar_t *sz = result.GetBuffer(totalSize / 2);
+ wchar_t *sz = result.GetBuf_SetEnd(totalSize / 2);
UInt32 pos = totalSize - size;
- memcpy((Byte *)sz + pos, p, size - 2);
+ memcpy((Byte *)sz + pos, p, size);
UInt32 index2 = index;
for (;;)
{
@@ -642,7 +681,11 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)
break;
if (parent == (UInt32)(Int32)-1)
+ {
+ if (parentType != 0)
+ sz[pos / 2 - 1] = L':';
break;
+ }
index2 = parent;
UInt32 size2;
const void *p2;
@@ -652,7 +695,6 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
memcpy((Byte *)sz + pos, p2, size2);
sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':';
}
- result.ReleaseBuffer((totalSize - 2) / 2);
#ifdef _WIN32
// result.Replace(L'/', WCHAR_PATH_SEPARATOR);
#endif
@@ -666,8 +708,8 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
{
NCOM::CPropVariant prop;
RINOK(Archive->GetProperty(index, kpidPath, &prop));
- if (prop.vt == VT_BSTR)
- result = prop.bstrVal;
+ if (prop.vt == VT_BSTR && prop.bstrVal)
+ result.SetFromBstr(prop.bstrVal);
else if (prop.vt == VT_EMPTY)
result.Empty();
else
@@ -675,6 +717,16 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
}
if (result.IsEmpty())
+ return GetDefaultItemPath(index, result);
+ return S_OK;
+}
+
+HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const
+{
+ result.Empty();
+ bool isDir;
+ RINOK(Archive_IsItem_Dir(Archive, index, isDir));
+ if (!isDir)
{
result = DefaultName;
NCOM::CPropVariant prop;
@@ -703,6 +755,161 @@ HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const
return S_OK;
}
+#ifdef SUPPORT_ALT_STREAMS
+
+int FindAltStreamColon_in_Path(const wchar_t *path)
+{
+ unsigned i = 0;
+ int colonPos = -1;
+ for (;; i++)
+ {
+ wchar_t c = path[i];
+ if (c == 0)
+ return colonPos;
+ if (c == ':')
+ {
+ if (colonPos < 0)
+ colonPos = i;
+ continue;
+ }
+ if (c == WCHAR_PATH_SEPARATOR)
+ colonPos = -1;
+ }
+}
+
+#endif
+
+HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
+{
+ #ifdef SUPPORT_ALT_STREAMS
+ item.IsAltStream = false;
+ item.AltStreamName.Empty();
+ item.MainPath.Empty();
+ #endif
+
+ item.IsDir = false;
+ item.Path.Empty();
+ item.ParentIndex = (UInt32)(Int32)-1;
+
+ item.PathParts.Clear();
+
+ RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir));
+ item.MainIsDir = item.IsDir;
+
+ RINOK(GetItemPath2(index, item.Path));
+
+ #ifndef _SFX
+ UInt32 mainIndex = index;
+ #endif
+
+ #ifdef SUPPORT_ALT_STREAMS
+
+ item.MainPath = item.Path;
+ if (Ask_AltStream)
+ {
+ RINOK(Archive_IsItem_AltStream(Archive, index, item.IsAltStream));
+ }
+
+ bool needFindAltStream = false;
+
+ if (item.IsAltStream)
+ {
+ needFindAltStream = true;
+ if (GetRawProps)
+ {
+ UInt32 parentType = 0;
+ UInt32 parentIndex;
+ RINOK(GetRawProps->GetParent(index, &parentIndex, &parentType));
+ if (parentType == NParentType::kAltStream)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(Archive->GetProperty(index, kpidName, &prop));
+ if (prop.vt == VT_BSTR && prop.bstrVal)
+ item.AltStreamName.SetFromBstr(prop.bstrVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ else
+ {
+ // item.IsAltStream = false;
+ }
+ /*
+ if (item.AltStreamName.IsEmpty())
+ item.IsAltStream = false;
+ */
+
+ needFindAltStream = false;
+ item.ParentIndex = parentIndex;
+ mainIndex = parentIndex;
+
+ if (parentIndex == (UInt32)(Int32)-1)
+ {
+ item.MainPath.Empty();
+ item.MainIsDir = true;
+ }
+ else
+ {
+ RINOK(GetItemPath2(parentIndex, item.MainPath));
+ RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir));
+ }
+ }
+ }
+ }
+
+ if (item.WriteToAltStreamIfColon || needFindAltStream)
+ {
+ /* Good handler must support GetRawProps::GetParent for alt streams./
+ So the following code currently is not used */
+ int colon = FindAltStreamColon_in_Path(item.Path);
+ if (colon >= 0)
+ {
+ item.MainPath.DeleteFrom(colon);
+ item.AltStreamName = item.Path.Ptr(colon + 1);
+ item.MainIsDir = (colon == 0 || IsPathSepar(item.Path[colon - 1]));
+ item.IsAltStream = true;
+ }
+ }
+
+ #endif
+
+ #ifndef _SFX
+ if (item._use_baseParentFolder_mode)
+ {
+ RINOK(GetItemPathToParent(mainIndex, item._baseParentFolder, item.PathParts));
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty())
+ {
+ int colon;
+ {
+ UString &s = item.PathParts.Back();
+ colon = FindAltStreamColon_in_Path(s);
+ if (colon >= 0)
+ {
+ item.AltStreamName = s.Ptr(colon + 1);
+ item.MainIsDir = (colon == 0 || IsPathSepar(s[(unsigned)colon - 1]));
+ item.IsAltStream = true;
+ s.DeleteFrom(colon);
+ }
+ }
+ if (colon == 0)
+ item.PathParts.DeleteBack();
+ }
+ #endif
+
+ }
+ else
+ #endif
+ SplitPathToParts(
+ #ifdef SUPPORT_ALT_STREAMS
+ item.MainPath
+ #else
+ item.Path
+ #endif
+ , item.PathParts);
+
+ return S_OK;
+}
+
#ifndef _SFX
static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined)
@@ -824,10 +1031,10 @@ static void MakeCheckOrder(CCodecs *codecs,
static bool IsExeExt(const UString &ext)
{
- return ext.IsEqualToNoCase(L"exe");
+ return ext.IsEqualTo_Ascii_NoCase("exe");
}
-static const char *k_PreArcFormats[] =
+static const char * const k_PreArcFormats[] =
{
"pe"
, "elf"
@@ -836,7 +1043,7 @@ static const char *k_PreArcFormats[] =
, "te"
};
-static bool IsNameFromList(const UString &s, const char *names[], size_t num)
+static bool IsNameFromList(const UString &s, const char * const names[], size_t num)
{
for (unsigned i = 0; i < num; i++)
if (StringsAreEqualNoCase_Ascii(s, names[i]))
@@ -852,7 +1059,7 @@ static bool IsPreArcFormat(const CArcInfoEx &ai)
return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats));
}
-static const char *k_Formats_with_simple_signuature[] =
+static const char * const k_Formats_with_simple_signuature[] =
{
"7z"
, "xz"
@@ -984,14 +1191,14 @@ HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openR
NCOM::CPropVariant prop;
RINOK(archive->GetArchiveProperty(kpidError, &prop));
if (prop.vt != VT_EMPTY)
- ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";
+ ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown error");
}
{
NCOM::CPropVariant prop;
RINOK(archive->GetArchiveProperty(kpidWarning, &prop));
if (prop.vt != VT_EMPTY)
- ErrorInfo.WarningMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown warning";
+ ErrorInfo.WarningMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown warning");
}
if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())
@@ -1039,30 +1246,40 @@ static PrintNumber(const char *s, int n)
HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive)
{
- // OutputDebugStringW(L"a1");
+ // OutputDebugStringA("a1");
// PrintNumber("formatIndex", formatIndex);
RINOK(op.codecs->CreateInArchive(formatIndex, archive));
- // OutputDebugStringW(L"a2");
+ // OutputDebugStringA("a2");
if (!archive)
return S_OK;
#ifdef EXTERNAL_CODECS
+ if (op.codecs->NeedSetLibCodecs)
{
- CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
- archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
- if (setCompressCodecsInfo)
+ const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
+ if (ai.LibIndex >= 0 ?
+ !op.codecs->Libs[ai.LibIndex].SetCodecs :
+ !op.codecs->Libs.IsEmpty())
{
- RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs));
+ CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
+ archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+ if (setCompressCodecsInfo)
+ {
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs));
+ }
}
}
#endif
- // OutputDebugStringW(ai.Name);
- // OutputDebugStringW(L"a3");
#ifndef _SFX
+
const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
+
+ // OutputDebugStringW(ai.Name);
+ // OutputDebugStringA("a3");
+
if (ai.Flags_PreArc())
{
/* we notify parsers that extract executables, that they don't need
@@ -1072,6 +1289,7 @@ HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyCom
if (allowTail)
allowTail->AllowTail(BoolToInt(true));
}
+
if (op.props)
{
/*
@@ -1087,6 +1305,7 @@ HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyCom
*/
RINOK(SetProperties(archive, *op.props));
}
+
#endif
return S_OK;
}
@@ -1130,14 +1349,14 @@ static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NAr
RINOK(archive->GetArchiveProperty(kpidName, &prop));
if (prop.vt == VT_BSTR)
{
- pi.Name = prop.bstrVal;
+ pi.Name.SetFromBstr(prop.bstrVal);
pi.Extension.Empty();
}
else
{
RINOK(archive->GetArchiveProperty(kpidExtension, &prop));
if (prop.vt == VT_BSTR)
- pi.Extension = prop.bstrVal;
+ pi.Extension.SetFromBstr(prop.bstrVal);
}
}
@@ -1145,7 +1364,7 @@ static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NAr
NCOM::CPropVariant prop;
RINOK(archive->GetArchiveProperty(kpidShortComment, &prop));
if (prop.vt == VT_BSTR)
- pi.Comment = prop.bstrVal;
+ pi.Comment.SetFromBstr(prop.bstrVal);
}
@@ -1171,7 +1390,7 @@ static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NAr
}
bool isDir = false;
- Archive_IsItem_Folder(archive, i, isDir);
+ Archive_IsItem_Dir(archive, i, isDir);
if (isDir)
pi.NumSubDirs++;
else
@@ -1336,13 +1555,13 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
IsParseArc = false;
ArcStreamOffset = 0;
- // OutputDebugStringW(L"1");
+ // OutputDebugStringA("1");
// OutputDebugStringW(Path);
const UString fileName = ExtractFileNameFromPath(Path);
UString extension;
{
- int dotPos = fileName.ReverseFind(L'.');
+ int dotPos = fileName.ReverseFind_Dot();
if (dotPos >= 0)
extension = fileName.Ptr(dotPos + 1);
}
@@ -1378,7 +1597,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
isForced = true;
orderIndices.Add(formatIndex);
numMainTypes = 1;
- isMainFormatArr[formatIndex] = true;
+ isMainFormatArr[(unsigned)formatIndex] = true;
searchMarkerInHandler = true;
}
@@ -1443,7 +1662,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
{
// signature search was here
}
- else if (extension == L"000" || extension == L"001")
+ else if (extension.IsEqualTo("000") || extension.IsEqualTo("001"))
{
int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar");
if (i >= 0)
@@ -1517,6 +1736,10 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
#else // _SFX
numMainTypes = orderIndices.Size();
+
+ // we need correct numMainTypes for mutlivolume SFX (if some volume is missing)
+ if (numFinded != 0)
+ numMainTypes = numFinded;
#endif
}
@@ -1557,10 +1780,13 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
for (unsigned i = 0; i < numCheckTypes; i++)
{
FormatIndex = orderIndices[i];
- const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
- // OutputDebugStringW(ai.Name);
bool exactOnly = false;
+
+ #ifndef _SFX
+
+ const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
+ // OutputDebugStringW(ai.Name);
if (i >= numMainTypes)
{
if (!ai.Flags_BackwardOpen()
@@ -1569,9 +1795,13 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
continue;
exactOnly = true;
}
+
+ #endif
// Some handlers do not set total bytes. So we set it here
- RINOK(op.callback->SetTotal(NULL, &fileSize));
+ if (op.callback)
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+
if (op.stream)
{
RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
@@ -1607,7 +1837,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
#ifndef _SFX
// if it's archive, we allow another open attempt for parser
if (!mode.CanReturnParser || !isArc)
- skipFrontalFormat[FormatIndex] = true;
+ skipFrontalFormat[(unsigned)FormatIndex] = true;
#endif
if (exactOnly)
@@ -1650,7 +1880,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
#ifndef _SFX
- bool isMainFormat = isMainFormatArr[FormatIndex];
+ bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];
const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
bool thereIsTail = ErrorInfo.ThereIsTail;
@@ -1834,7 +2064,9 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
FormatIndex = sortedFormats[i];
const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
- RINOK(op.callback->SetTotal(NULL, &fileSize));
+ if (op.callback)
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+
RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
CMyComPtr<IInArchive> archive;
@@ -1856,7 +2088,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
if (result == S_FALSE)
{
- skipFrontalFormat[FormatIndex] = true;
+ skipFrontalFormat[(unsigned)FormatIndex] = true;
// FIXME: maybe we must use LenIsUnknown.
// printf(" OpenForSize Error");
continue;
@@ -1900,7 +2132,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
if (mode.CanReturnArc)
{
- bool isMainFormat = isMainFormatArr[FormatIndex];
+ bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];
const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
bool openCur = false;
@@ -1938,7 +2170,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
}
- skipFrontalFormat[FormatIndex] = true;
+ skipFrontalFormat[(unsigned)FormatIndex] = true;
// if (!mode.CanReturnArc)
@@ -2032,7 +2264,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
thereAreHandlersForSearch = true;
UInt32 v = HASH_VAL(sig, 0);
- unsigned sigIndex = arc2sig[index] + k;
+ unsigned sigIndex = arc2sig[(unsigned)index] + k;
prevs[sigIndex] = hash[v];
hash[v] = (Byte)sigIndex;
}
@@ -2065,7 +2297,9 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
#endif
- RINOK(op.callback->SetTotal(NULL, &fileSize));
+ if (op.callback)
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+
CByteBuffer &byteBuffer = limitedStreamSpec->Buffer;
byteBuffer.Alloc(kBufSize);
@@ -2607,11 +2841,12 @@ HRESULT CArc::OpenStream(const COpenOptions &op)
RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream));
RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux));
RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidReadOnly, IsReadOnly));
const UString fileName = ExtractFileNameFromPath(Path);
UString extension;
{
- int dotPos = fileName.ReverseFind(L'.');
+ int dotPos = fileName.ReverseFind_Dot();
if (dotPos >= 0)
extension = fileName.Ptr(dotPos + 1);
}
@@ -2621,7 +2856,7 @@ HRESULT CArc::OpenStream(const COpenOptions &op)
{
const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
if (ai.Exts.Size() == 0)
- DefaultName = GetDefaultName2(fileName, L"", L"");
+ DefaultName = GetDefaultName2(fileName, UString(), UString());
else
{
int subExtIndex = ai.FindExtension(extension);
@@ -2639,10 +2874,10 @@ HRESULT CArc::OpenStream(const COpenOptions &op)
#ifdef _SFX
#ifdef _WIN32
- static const wchar_t *k_ExeExt = L".exe";
+ static const char *k_ExeExt = ".exe";
static const unsigned k_ExeExt_Len = 4;
#else
- static const wchar_t *k_ExeExt = L"";
+ static const char *k_ExeExt = "";
static const unsigned k_ExeExt_Len = 0;
#endif
@@ -2653,6 +2888,7 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
CMyComPtr<IInStream> fileStream;
CMyComPtr<ISequentialInStream> seqStream;
CInFileStream *fileStreamSpec = NULL;
+
if (op.stdInMode)
{
seqStream = new CStdInFileStream;
@@ -2692,9 +2928,10 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
|| !op.callbackSpec
|| NonOpen_ErrorInfo.IsArc_After_NonOpen())
return res;
+
{
if (filePath.Len() > k_ExeExt_Len
- && MyStringCompareNoCase(filePath.RightPtr(k_ExeExt_Len), k_ExeExt) == 0)
+ && StringsAreEqualNoCase_Ascii(filePath.RightPtr(k_ExeExt_Len), k_ExeExt))
{
const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len);
FOR_VECTOR (i, op.codecs->Formats)
@@ -2703,9 +2940,10 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
if (ai.IsSplit())
continue;
UString path3 = path2;
- path3 += L".";
+ path3 += L'.';
path3 += ai.GetMainExt(); // "7z" for SFX.
- Path = path3 + L".001";
+ Path = path3;
+ Path.AddAscii(".001");
bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));
if (!isOk)
{
@@ -2733,8 +2971,9 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
void CArchiveLink::KeepModeForNextOpen()
{
- for (int i = Arcs.Size() - 1; i >= 0; i--)
+ for (unsigned i = Arcs.Size(); i != 0;)
{
+ i--;
CMyComPtr<IArchiveKeepModeForNextOpen> keep;
Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep);
if (keep)
@@ -2744,8 +2983,9 @@ void CArchiveLink::KeepModeForNextOpen()
HRESULT CArchiveLink::Close()
{
- for (int i = Arcs.Size() - 1; i >= 0; i--)
+ for (unsigned i = Arcs.Size(); i != 0;)
{
+ i--;
RINOK(Arcs[i].Close());
}
IsOpen = false;
@@ -2771,20 +3011,20 @@ void CArchiveLink::Set_ErrorsText()
if (!arc.ErrorFlagsText.IsEmpty())
{
if (!ErrorsText.IsEmpty())
- ErrorsText += L'\n';
+ ErrorsText.Add_LF();
ErrorsText += GetUnicodeString(arc.ErrorFlagsText);
}
if (!arc.ErrorMessage.IsEmpty())
{
if (!ErrorsText.IsEmpty())
- ErrorsText += L'\n';
+ ErrorsText.Add_LF();
ErrorsText += arc.ErrorMessage;
}
if (!arc.WarningMessage.IsEmpty())
{
if (!ErrorsText.IsEmpty())
- ErrorsText += L'\n';
+ ErrorsText.Add_LF();
ErrorsText += arc.WarningMessage;
}
}
@@ -2909,10 +3149,14 @@ HRESULT CArchiveLink::Open(COpenOptions &op)
bool zerosTailIsAllowed;
RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed));
- CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
- op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
- if (setSubArchiveName)
- setSubArchiveName->SetSubArchiveName(arc2.Path);
+
+ if (op.callback)
+ {
+ CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
+ op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
+ if (setSubArchiveName)
+ setSubArchiveName->SetSubArchiveName(arc2.Path);
+ }
arc2.SubfileIndex = mainSubfile;
@@ -2951,23 +3195,7 @@ HRESULT CArchiveLink::Open(COpenOptions &op)
return resSpec;
}
-static void SetCallback(const FString &filePath,
- IOpenCallbackUI *callbackUI,
- IArchiveOpenCallback *reOpenCallback,
- CMyComPtr<IArchiveOpenCallback> &callback)
-{
- COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
- callback = openCallbackSpec;
- openCallbackSpec->Callback = callbackUI;
- openCallbackSpec->ReOpenCallback = reOpenCallback;
-
- FString dirPrefix, fileName;
- NFile::NDir::GetFullPathAndSplit(filePath, dirPrefix, fileName);
- openCallbackSpec->Init(dirPrefix, fileName);
-}
-
-HRESULT CArchiveLink::Open2(COpenOptions &op,
- IOpenCallbackUI *callbackUI)
+HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI)
{
VolumesSize = 0;
COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
@@ -2975,6 +3203,7 @@ HRESULT CArchiveLink::Open2(COpenOptions &op,
openCallbackSpec->Callback = callbackUI;
FString prefix, name;
+
if (!op.stream && !op.stdInMode)
{
NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name);
@@ -2987,7 +3216,13 @@ HRESULT CArchiveLink::Open2(COpenOptions &op,
op.callback = callback;
op.callbackSpec = openCallbackSpec;
- RINOK(Open(op));
+
+ HRESULT res = Open(op);
+
+ PasswordWasAsked = openCallbackSpec->PasswordWasAsked;
+ // Password = openCallbackSpec->Password;
+
+ RINOK(res);
// VolumePaths.Add(fs2us(prefix + name));
FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed)
@@ -3044,6 +3279,15 @@ HRESULT CArc::ReOpen(const COpenOptions &op)
return res;
}
+HRESULT CArchiveLink::Open3(COpenOptions &op, IOpenCallbackUI *callbackUI)
+{
+ HRESULT res = Open2(op, callbackUI);
+ if (callbackUI)
+ {
+ RINOK(callbackUI->Open_Finished());
+ }
+ return res;
+}
HRESULT CArchiveLink::ReOpen(COpenOptions &op)
{
@@ -3060,8 +3304,17 @@ HRESULT CArchiveLink::ReOpen(COpenOptions &op)
if (Arcs.Size() == 0) // ???
return Open2(op, NULL);
- CMyComPtr<IArchiveOpenCallback> openCallbackNew;
- SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew);
+ COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
+ CMyComPtr<IArchiveOpenCallback> openCallbackNew = openCallbackSpec;
+
+ openCallbackSpec->Callback = NULL;
+ openCallbackSpec->ReOpenCallback = op.callback;
+ {
+ FString dirPrefix, fileName;
+ NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), dirPrefix, fileName);
+ openCallbackSpec->Init(dirPrefix, fileName);
+ }
+
CInFileStream *fileStreamSpec = new CInFileStream;
CMyComPtr<IInStream> stream(fileStreamSpec);
@@ -3071,6 +3324,10 @@ HRESULT CArchiveLink::ReOpen(COpenOptions &op)
CArc &arc = Arcs[0];
HRESULT res = arc.ReOpen(op);
+
+ PasswordWasAsked = openCallbackSpec->PasswordWasAsked;
+ // Password = openCallbackSpec->Password;
+
IsOpen = (res == S_OK);
return res;
}
@@ -3136,7 +3393,7 @@ static bool ParseTypeParams(const UString &s, COpenType &type)
bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
{
- int pos2 = s.Find(':');
+ int pos2 = s.Find(L':');
UString name;
if (pos2 < 0)
{
@@ -3174,7 +3431,7 @@ bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
for (unsigned i = pos2; i < s.Len();)
{
- int next = s.Find(':', i);
+ int next = s.Find(L':', i);
if (next < 0)
next = s.Len();
UString name = s.Mid(i, next - i);
@@ -3193,7 +3450,7 @@ bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType>
types.Clear();
for (unsigned pos = 0; pos < s.Len();)
{
- int pos2 = s.Find('.', pos);
+ int pos2 = s.Find(L'.', pos);
if (pos2 < 0)
pos2 = s.Len();
UString name = s.Mid(pos, pos2 - pos);
diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
index aab6669d..c62bf826 100644
--- a/CPP/7zip/UI/Common/OpenArchive.h
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -9,12 +9,22 @@
#include "LoadCodecs.h"
#include "Property.h"
+#ifndef _SFX
+
+#define SUPPORT_ALT_STREAMS
+
+#endif
+
HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
-HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw();
+HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw();
HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
+#ifdef SUPPORT_ALT_STREAMS
+int FindAltStreamColon_in_Path(const wchar_t *path);
+#endif
+
/*
struct COptionalOpenProperties
{
@@ -212,12 +222,53 @@ struct CArcErrorInfo
}
};
+struct CReadArcItem
+{
+ UString Path; // Path from root (including alt stream name, if alt stream)
+ UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode
+
+ #ifdef SUPPORT_ALT_STREAMS
+ UString MainPath;
+ /* MainPath = Path for non-AltStream,
+ MainPath = Path of parent, if there is parent for AltStream. */
+ UString AltStreamName;
+ bool IsAltStream;
+ bool WriteToAltStreamIfColon;
+ #endif
+
+ bool IsDir;
+ bool MainIsDir;
+ UInt32 ParentIndex; // use it, if IsAltStream
+
+ #ifndef _SFX
+ bool _use_baseParentFolder_mode;
+ int _baseParentFolder;
+ #endif
+
+ CReadArcItem()
+ {
+ #ifdef SUPPORT_ALT_STREAMS
+ WriteToAltStreamIfColon = false;
+ #endif
+
+ #ifndef _SFX
+ _use_baseParentFolder_mode = false;
+ _baseParentFolder = -1;
+ #endif
+ }
+};
+
class CArc
{
HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
HRESULT OpenStream2(const COpenOptions &options);
+ #ifndef _SFX
+ // parts.Back() can contain alt stream name "nams:AltName"
+ HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
+ #endif
+
public:
CMyComPtr<IInArchive> Archive;
CMyComPtr<IInStream> InStream;
@@ -256,6 +307,7 @@ public:
bool IsParseArc;
bool IsTree;
+ bool IsReadOnly;
bool Ask_Deleted;
bool Ask_AltStream;
@@ -269,6 +321,7 @@ public:
CArc():
MTimeDefined(false),
IsTree(false),
+ IsReadOnly(false),
Ask_Deleted(false),
Ask_AltStream(false),
Ask_Aux(false),
@@ -286,13 +339,13 @@ public:
return Archive->Close();
}
- // AltStream's name is concatenated with base file name in one string in parts.Back()
- HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
-
HRESULT GetItemPath(UInt32 index, UString &result) const;
+ HRESULT GetDefaultItemPath(UInt32 index, UString &result) const;
// GetItemPath2 adds [DELETED] dir prefix for deleted items.
HRESULT GetItemPath2(UInt32 index, UString &result) const;
+
+ HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;
HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;
@@ -315,6 +368,9 @@ struct CArchiveLink
UInt64 VolumesSize;
bool IsOpen;
+ bool PasswordWasAsked;
+ // UString Password;
+
// int NonOpenErrorFormatIndex; // - 1 means no Error.
UString NonOpen_ArcPath;
@@ -323,7 +379,12 @@ struct CArchiveLink
// UString ErrorsText;
// void Set_ErrorsText();
- CArchiveLink(): VolumesSize(0), IsOpen(false) {}
+ CArchiveLink():
+ VolumesSize(0),
+ IsOpen(false),
+ PasswordWasAsked(false)
+ {}
+
void KeepModeForNextOpen();
HRESULT Close();
void Release();
@@ -335,8 +396,8 @@ struct CArchiveLink
IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
HRESULT Open(COpenOptions &options);
-
HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
+ HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);
HRESULT ReOpen(COpenOptions &options);
};
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
index c2ceceae..32001624 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -7,7 +7,6 @@
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
-#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/PropVariantConv.h"
@@ -41,20 +40,53 @@ static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_";
16 VIRTUAL
*/
-void ConvertWinAttribToString(char *s, UInt32 wa)
+static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
+#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';
+
+static void ConvertPosixAttribToString(char *s, UInt32 a) throw()
+{
+ s[0] = kPosixTypes[(a >> 12) & 0xF];
+ for (int i = 6; i >= 0; i -= 3)
+ {
+ s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');
+ s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');
+ s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');
+ }
+ if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S');
+ if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S');
+ if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T');
+ s[10] = 0;
+
+ a &= ~(UInt32)0xFFFF;
+ if (a != 0)
+ {
+ s[10] = ' ';
+ ConvertUInt32ToHex8Digits(a, s + 11);
+ }
+}
+
+void ConvertWinAttribToString(char *s, UInt32 wa) throw()
{
for (int i = 0; i < 16; i++)
if ((wa & (1 << i)) && i != 7)
*s++ = g_WinAttribChars[i];
*s = 0;
-}
-static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
-#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';
+ // we support p7zip trick that stores posix attributes in high 16 bits, and 0x8000 flag
+ // we also support ZIP archives created in Unix, that store posix attributes in high 16 bits without 0x8000 flag
+
+ // if (wa & 0x8000)
+ if ((wa >> 16) != 0)
+ {
+ *s++ = ' ';
+ ConvertPosixAttribToString(s, wa >> 16);
+ }
+}
void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw()
{
*dest = 0;
+
if (prop.vt == VT_FILETIME)
{
FILETIME localFileTime;
@@ -65,6 +97,7 @@ void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID pr
ConvertFileTimeToString(localFileTime, dest, true, full);
return;
}
+
switch (propID)
{
case kpidCRC:
@@ -78,34 +111,21 @@ void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID pr
{
if (prop.vt != VT_UI4)
break;
- ConvertWinAttribToString(dest, prop.ulVal);
+ UInt32 a = prop.ulVal;
+
+ /*
+ if ((a & 0x8000) && (a & 0x7FFF) == 0)
+ ConvertPosixAttribToString(dest, a >> 16);
+ else
+ */
+ ConvertWinAttribToString(dest, a);
return;
}
case kpidPosixAttrib:
{
if (prop.vt != VT_UI4)
break;
- UString res;
- UInt32 a = prop.ulVal;
-
- dest[0] = kPosixTypes[(a >> 12) & 0xF];
- for (int i = 6; i >= 0; i -= 3)
- {
- dest[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');
- dest[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');
- dest[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');
- }
- if ((a & 0x800) != 0) dest[3] = ((a & (1 << 6)) ? 's' : 'S');
- if ((a & 0x400) != 0) dest[6] = ((a & (1 << 3)) ? 's' : 'S');
- if ((a & 0x200) != 0) dest[9] = ((a & (1 << 0)) ? 't' : 'T');
- dest[10] = 0;
-
- a &= ~(UInt32)0xFFFF;
- if (a != 0)
- {
- dest[10] = ' ';
- ConvertUInt32ToHex8Digits(a, dest + 11);
- }
+ ConvertPosixAttribToString(dest, prop.ulVal);
return;
}
case kpidINode:
@@ -132,6 +152,7 @@ void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID pr
break;
}
}
+
ConvertPropVariantToShortString(prop, dest);
}
@@ -139,29 +160,25 @@ void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID prop
{
if (prop.vt == VT_BSTR)
{
- dest = prop.bstrVal;
+ dest.SetFromBstr(prop.bstrVal);
return;
}
char temp[64];
ConvertPropertyToShortString(temp, prop, propID, full);
- int len = MyStringLen(temp);
- wchar_t *str = dest.GetBuffer(len);
- for (int i = 0; i < len; i++)
- str[i] = temp[i];
- dest.ReleaseBuffer(len);
+ dest.SetFromAscii(temp);
}
-static inline char GetHex(Byte value)
+static inline unsigned GetHex(unsigned v)
{
- return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+ return (v < 10) ? ('0' + v) : ('A' + (v - 10));
}
#ifndef _SFX
-static inline void AddHexToString(AString &res, Byte value)
+static inline void AddHexToString(AString &res, unsigned v)
{
- res += GetHex((Byte)(value >> 4));
- res += GetHex((Byte)(value & 0xF));
+ res += (char)GetHex(v >> 4);
+ res += (char)GetHex(v & 0xF);
res += ' ';
}
@@ -175,30 +192,30 @@ static AString Data_To_Hex(const Byte *data, size_t size)
}
*/
-static const char *sidNames[] =
+static const char * const sidNames[] =
{
- "0",
- "Dialup",
- "Network",
- "Batch",
- "Interactive",
- "Logon", // S-1-5-5-X-Y
- "Service",
- "Anonymous",
- "Proxy",
- "EnterpriseDC",
- "Self",
- "AuthenticatedUsers",
- "RestrictedCode",
- "TerminalServer",
- "RemoteInteractiveLogon",
- "ThisOrganization",
- "16",
- "IUserIIS",
- "LocalSystem",
- "LocalService",
- "NetworkService",
- "Domains"
+ "0"
+ , "Dialup"
+ , "Network"
+ , "Batch"
+ , "Interactive"
+ , "Logon" // S-1-5-5-X-Y
+ , "Service"
+ , "Anonymous"
+ , "Proxy"
+ , "EnterpriseDC"
+ , "Self"
+ , "AuthenticatedUsers"
+ , "RestrictedCode"
+ , "TerminalServer"
+ , "RemoteInteractiveLogon"
+ , "ThisOrganization"
+ , "16"
+ , "IUserIIS"
+ , "LocalSystem"
+ , "LocalService"
+ , "NetworkService"
+ , "Domains"
};
struct CSecID2Name
@@ -207,7 +224,7 @@ struct CSecID2Name
const char *sz;
};
-const CSecID2Name sid_32_Names[] =
+static const CSecID2Name sid_32_Names[] =
{
{ 544, "Administrators" },
{ 545, "Users" },
@@ -297,7 +314,7 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
if (v0 == 32 && num == 2)
{
UInt32 v1 = Get32(p + 12);
- for (int i = 0; i < ARRAY_SIZE(sid_32_Names); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(sid_32_Names); i++)
if (sid_32_Names[i].n == v1)
{
s += sid_32_Names[i].sz;
@@ -307,7 +324,7 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
if (v0 == 21 && num == 5)
{
UInt32 v4 = Get32(p + 8 + 4 * 4);
- for (int i = 0; i < ARRAY_SIZE(sid_21_Names); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(sid_21_Names); i++)
if (sid_21_Names[i].n == v4)
{
s += sid_21_Names[i].sz;
@@ -316,7 +333,7 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
}
if (v0 == 80 && num == 6)
{
- for (int i = 0; i < ARRAY_SIZE(services_to_name); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(services_to_name); i++)
{
const CServicesToName &sn = services_to_name[i];
int j;
@@ -385,10 +402,11 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
return;
if (Get16(p) != 2) // revision
return;
- // UInt32 aclSize = Get16(p + 2);
UInt32 num = Get32(p + 4);
AddUInt32ToString(s, num);
+
/*
+ UInt32 aclSize = Get16(p + 2);
if (num >= (1 << 16))
return;
if (aclSize > size)
@@ -409,14 +427,15 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
UInt32 sidSize = 0;
s += ' ';
- s += ParseSid(p, size, sidSize);
+ ParseSid(s, p, size, sidSize);
if (sidSize == 0)
return;
p += sidSize;
size -= sidSize;
}
- if (size != 0)
- s += " ERROR";
+
+ // the tail can contain zeros. So (size != 0) is not ERROR
+ // if (size != 0) s += " ERROR";
*/
}
@@ -461,7 +480,7 @@ void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
#ifdef _WIN32
-static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos)
+static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw()
{
if (pos >= size)
return false;
@@ -475,7 +494,7 @@ static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos)
return (8 + num * 4 <= size);
}
-static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset)
+static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) throw()
{
UInt32 control = Get16(p + 2);
if ((flags & control) == 0)
@@ -491,7 +510,7 @@ static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset)
return (aclSize <= size);
}
-bool CheckNtSecure(const Byte *data, UInt32 size)
+bool CheckNtSecure(const Byte *data, UInt32 size) throw()
{
if (size < 20)
return false;
@@ -515,11 +534,11 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
if (attr.Parse(data, size))
{
if (!attr.IsSymLink())
- s += L"Junction: ";
+ s.AddAscii("Junction: ");
s += attr.GetPath();
if (!attr.IsOkNamePair())
{
- s += L" : ";
+ s.AddAscii(" : ");
s += attr.PrintName;
}
return true;
@@ -536,16 +555,16 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
char hex[16];
ConvertUInt32ToHex8Digits(tag, hex);
- s.AddAsciiStr(hex);
- s += L' ';
+ s.AddAscii(hex);
+ s.Add_Space();
data += 8;
for (UInt32 i = 0; i < len; i++)
{
- Byte b = ((const Byte *)data)[i];
- s += (wchar_t)GetHex((Byte)((b >> 4) & 0xF));
- s += (wchar_t)GetHex((Byte)(b & 0xF));
+ unsigned b = ((const Byte *)data)[i];
+ s += (wchar_t)GetHex((b >> 4) & 0xF);
+ s += (wchar_t)GetHex(b & 0xF);
}
return true;
}
diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h
index 3ee2981d..1dea321e 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.h
+++ b/CPP/7zip/UI/Common/PropIDUtils.h
@@ -11,7 +11,8 @@ void ConvertPropertyToString(UString &dest, const PROPVARIANT &propVariant, PROP
bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s);
void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s);
-bool CheckNtSecure(const Byte *data, UInt32 size);
-void ConvertWinAttribToString(char *s, UInt32 wa);
+bool CheckNtSecure(const Byte *data, UInt32 size) throw();;
+
+void ConvertWinAttribToString(char *s, UInt32 wa) throw();
#endif
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
index d2895961..78eec82f 100644
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -42,6 +42,19 @@ using namespace NName;
static CFSTR kTempFolderPrefix = FTEXT("7zE");
+void CUpdateErrorInfo::SetFromLastError(const char *message)
+{
+ SystemError = ::GetLastError();
+ Message = message;
+}
+
+HRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &fileName)
+{
+ SetFromLastError(message);
+ FileNames.Add(fileName);
+ return Get_HRESULT_Error();
+}
+
static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)
{
NFind::CFileInfo fileInfo;
@@ -101,6 +114,8 @@ public:
bool SetMTime(const FILETIME *mTime);
HRESULT Close();
+ UInt64 GetSize() const { return _length; }
+
MY_UNKNOWN_IMP1(IOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
@@ -151,10 +166,10 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr
FChar temp[16];
ConvertUInt32ToString(_streamIndex + 1, temp);
- FString res = temp;
- while (res.Len() < 3)
- res = FString(FTEXT('0')) + res;
- FString name = Prefix + res;
+ FString name = temp;
+ while (name.Len() < 3)
+ name.InsertAtFront(FTEXT('0'));
+ name.Insert(0, Prefix);
altStream.StreamSpec = new COutFileStream;
altStream.Stream = altStream.StreamSpec;
if (!altStream.StreamSpec->Create(name, false))
@@ -279,7 +294,7 @@ void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)
return;
}
- int dotPos = Name.ReverseFind(L'.');
+ int dotPos = Name.ReverseFind_Dot();
if (dotPos < 0)
return;
if ((unsigned)dotPos == Name.Len() - 1)
@@ -289,7 +304,7 @@ void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)
return;
}
const UString ext = Name.Ptr(dotPos + 1);
- if (BaseExtension.IsEqualToNoCase(ext))
+ if (BaseExtension.IsEqualTo_NoCase(ext))
{
BaseExtension = ext;
Name.DeleteFrom(dotPos);
@@ -302,7 +317,10 @@ UString CArchivePath::GetFinalPath() const
{
UString path = GetPathWithoutExt();
if (!BaseExtension.IsEmpty())
- path += UString(L'.') + BaseExtension;
+ {
+ path += L'.';
+ path += BaseExtension;
+ }
return path;
}
@@ -310,27 +328,34 @@ UString CArchivePath::GetFinalVolPath() const
{
UString path = GetPathWithoutExt();
if (!BaseExtension.IsEmpty())
- path += UString(L'.') + VolExtension;
+ {
+ path += L'.';
+ path += VolExtension;
+ }
return path;
}
FString CArchivePath::GetTempPath() const
{
- FString path = TempPrefix + us2fs(Name);
+ FString path = TempPrefix;
+ path += us2fs(Name);
if (!BaseExtension.IsEmpty())
- path += FString(FTEXT('.')) + us2fs(BaseExtension);
- path += FTEXT(".tmp");
+ {
+ path += FTEXT('.');
+ path += us2fs(BaseExtension);
+ }
+ path.AddAscii(".tmp");
path += TempPostfix;
return path;
}
static const wchar_t *kDefaultArcType = L"7z";
static const wchar_t *kDefaultArcExt = L"7z";
-static const wchar_t *kSFXExtension =
+static const char *kSFXExtension =
#ifdef _WIN32
- L"exe";
+ "exe";
#else
- L"";
+ "";
#endif
bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs,
@@ -375,7 +400,7 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
}
UString ext = typeExt;
if (SfxMode)
- ext = kSFXExtension;
+ ext.SetFromAscii(kSFXExtension);
ArchivePath.BaseExtension = ext;
ArchivePath.VolExtension = typeExt;
ArchivePath.ParseFromPath(arcPath, ArcNameMode);
@@ -389,7 +414,6 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
return true;
}
-/*
struct CUpdateProduceCallbackImp: public IUpdateProduceCallback
{
const CObjectVector<CArcItem> *_arcItems;
@@ -397,14 +421,14 @@ struct CUpdateProduceCallbackImp: public IUpdateProduceCallback
CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,
IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}
- virtual HRESULT ShowDeleteFile(int arcIndex);
+ virtual HRESULT ShowDeleteFile(unsigned arcIndex);
};
-HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex)
+HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex)
{
- return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name);
+ const CArcItem &ai = (*_arcItems)[arcIndex];
+ return _callback->ShowDeleteFile(ai.Name, ai.IsDir);
}
-*/
bool CRenamePair::Prepare()
{
@@ -417,9 +441,9 @@ bool CRenamePair::Prepare()
extern bool g_CaseSensitive;
-static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2)
+static unsigned CompareTwoNames(const wchar_t *s1, const wchar_t *s2)
{
- for (int i = 0;; i++)
+ for (unsigned i = 0;; i++)
{
wchar_t c1 = s1[i];
wchar_t c2 = s2[i];
@@ -429,7 +453,7 @@ static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2)
continue;
if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2)))
continue;
- if (IsCharDirLimiter(c1) && IsCharDirLimiter(c2))
+ if (IsPathSepar(c1) && IsPathSepar(c2))
continue;
return i;
}
@@ -437,10 +461,10 @@ static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2)
bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const
{
- int num = CompareTwoNames(OldName, src);
+ unsigned num = CompareTwoNames(OldName, src);
if (OldName[num] == 0)
{
- if (src[num] != 0 && !IsCharDirLimiter(src[num]) && num != 0 && !IsCharDirLimiter(src[num - 1]))
+ if (src[num] != 0 && !IsPathSepar(src[num]) && num != 0 && !IsPathSepar(src[num - 1]))
return false;
}
else
@@ -449,28 +473,23 @@ bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) c
// OldName = "1\1a.txt"
// src = "1"
- if (!isFolder ||
- src[num] != 0 ||
- !IsCharDirLimiter(OldName[num]) ||
- OldName[num + 1] != 0)
+ if (!isFolder
+ || src[num] != 0
+ || !IsPathSepar(OldName[num])
+ || OldName[num + 1] != 0)
return false;
}
dest = NewName + src.Ptr(num);
return true;
}
-static int GetReverseSlashPos(const UString &name)
-{
- int slashPos = name.ReverseFind(L'/');
- #ifdef _WIN32
- int slash1Pos = name.ReverseFind(L'\\');
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
- return slashPos;
-}
+#ifdef SUPPORT_ALT_STREAMS
+int FindAltStreamColon_in_Path(const wchar_t *path);
+#endif
static HRESULT Compress(
const CUpdateOptions &options,
+ bool isUpdatingItself,
CCodecs *codecs,
const CActionSet &actionSet,
const CArc *arc,
@@ -481,10 +500,12 @@ static HRESULT Compress(
const CDirItem *parentDirItem,
CTempFiles &tempFiles,
CUpdateErrorInfo &errorInfo,
- IUpdateCallbackUI *callback)
+ IUpdateCallbackUI *callback,
+ CFinishArchiveStat &st)
{
CMyComPtr<IOutArchive> outArchive;
int formatIndex = options.MethodMode.Type.FormatIndex;
+
if (arc)
{
formatIndex = arc->FormatIndex;
@@ -510,22 +531,25 @@ static HRESULT Compress(
}
#endif
}
+
if (outArchive == 0)
throw kUpdateIsNotSupoorted;
NFileTimeType::EEnum fileTimeType;
- UInt32 value;
- RINOK(outArchive->GetFileTimeType(&value));
-
- switch (value)
{
- case NFileTimeType::kWindows:
- case NFileTimeType::kUnix:
- case NFileTimeType::kDOS:
- fileTimeType = (NFileTimeType::EEnum)value;
- break;
- default:
- return E_FAIL;
+ UInt32 value;
+ RINOK(outArchive->GetFileTimeType(&value));
+
+ switch (value)
+ {
+ case NFileTimeType::kWindows:
+ case NFileTimeType::kUnix:
+ case NFileTimeType::kDOS:
+ fileTimeType = (NFileTimeType::EEnum)value;
+ break;
+ default:
+ return E_FAIL;
+ }
}
{
@@ -559,9 +583,8 @@ static HRESULT Compress(
}
if (ai.IsAltStream)
{
- int colonPos = ai.Name.ReverseFind(':');
- int slashPosPos = GetReverseSlashPos(ai.Name);
- if (colonPos > slashPosPos)
+ int colonPos = FindAltStreamColon_in_Path(ai.Name);
+ if (colonPos >= 0)
{
UString mainName = ai.Name.Left(colonPos);
/*
@@ -571,7 +594,7 @@ static HRESULT Compress(
if (rp.GetNewPath(false, mainName, dest))
{
needRename = true;
- dest += ':';
+ dest += L':';
dest += ai.Name.Ptr(colonPos + 1);
break;
}
@@ -594,16 +617,18 @@ static HRESULT Compress(
{
CRecordVector<CUpdatePair> updatePairs;
GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!
- // CUpdateProduceCallbackImp upCallback(&arcItems, callback);
- UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */);
+ CUpdateProduceCallbackImp upCallback(&arcItems, callback);
+
+ UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL);
}
- UInt32 numFiles = 0;
- FOR_VECTOR (i, updatePairs2)
- if (updatePairs2[i].NewData)
- numFiles++;
-
- RINOK(callback->SetNumFiles(numFiles));
+ {
+ UInt32 numItems = 0;
+ FOR_VECTOR (i, updatePairs2)
+ if (updatePairs2[i].NewData)
+ numItems++;
+ RINOK(callback->SetNumItems(numItems));
+ }
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
@@ -616,8 +641,6 @@ static HRESULT Compress(
{
// we set Archive to allow to transfer GetProperty requests back to DLL.
updateCallbackSpec->Archive = arc->Archive;
- updateCallbackSpec->GetRawProps = arc->GetRawProps;
- updateCallbackSpec->GetRootProps = arc->GetRootProps;
}
updateCallbackSpec->DirItems = &dirItems;
@@ -627,6 +650,7 @@ static HRESULT Compress(
updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;
updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;
+ updateCallbackSpec->Arc = arc;
updateCallbackSpec->ArcItems = &arcItems;
updateCallbackSpec->UpdatePairs = &updatePairs2;
@@ -647,12 +671,16 @@ static HRESULT Compress(
}
COutFileStream *outStreamSpec = NULL;
+ CStdOutFileStream *stdOutFileStreamSpec = NULL;
COutMultiVolStream *volStreamSpec = NULL;
if (options.VolumesSizes.Size() == 0)
{
if (options.StdOutMode)
- outStream = new CStdOutFileStream;
+ {
+ stdOutFileStreamSpec = new CStdOutFileStream;
+ outStream = stdOutFileStreamSpec;
+ }
else
{
outStreamSpec = new COutFileStream;
@@ -660,7 +688,8 @@ static HRESULT Compress(
outStream = outSeekStream;
bool isOK = false;
FString realPath;
- for (int i = 0; i < (1 << 16); i++)
+
+ for (unsigned i = 0; i < (1 << 16); i++)
{
if (archivePath.Temp)
{
@@ -685,13 +714,9 @@ static HRESULT Compress(
if (!archivePath.Temp)
break;
}
+
if (!isOK)
- {
- errorInfo.SystemError = ::GetLastError();
- errorInfo.FileName = realPath;
- errorInfo.Message = L"7-Zip cannot open file";
- return E_FAIL;
- }
+ return errorInfo.SetFromLastError("cannot open file", realPath);
}
}
else
@@ -705,7 +730,8 @@ static HRESULT Compress(
outSeekStream = volStreamSpec;
outStream = outSeekStream;
volStreamSpec->Sizes = options.VolumesSizes;
- volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath() + L".");
+ volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath());
+ volStreamSpec->Prefix += FTEXT('.');
volStreamSpec->TempFiles = &tempFiles;
volStreamSpec->Init();
@@ -724,12 +750,7 @@ static HRESULT Compress(
CInFileStream *sfxStreamSpec = new CInFileStream;
CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
if (!sfxStreamSpec->Open(options.SfxModule))
- {
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"7-Zip cannot open SFX module";
- errorInfo.FileName = options.SfxModule;
- return E_FAIL;
- }
+ return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule);
CMyComPtr<ISequentialOutStream> sfxOutStream;
COutFileStream *outStreamSpec = NULL;
@@ -741,14 +762,17 @@ static HRESULT Compress(
sfxOutStream = outStreamSpec;
FString realPath = us2fs(archivePath.GetFinalPath());
if (!outStreamSpec->Create(realPath, false))
- {
- errorInfo.SystemError = ::GetLastError();
- errorInfo.FileName = realPath;
- errorInfo.Message = L"7-Zip cannot open file";
- return E_FAIL;
- }
+ return errorInfo.SetFromLastError("cannot open file", realPath);
}
+
+ {
+ UInt64 sfxSize;
+ RINOK(sfxStreamSpec->GetSize(&sfxSize));
+ RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize));
+ }
+
RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL));
+
if (outStreamSpec)
{
RINOK(outStreamSpec->Close());
@@ -778,9 +802,15 @@ static HRESULT Compress(
HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);
- callback->Finilize();
+ // callback->Finalize();
RINOK(result);
+ if (!updateCallbackSpec->AreAllFilesClosed())
+ {
+ errorInfo.Message = "There are unclosed input file:";
+ errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths;
+ return E_FAIL;
+ }
if (options.SetArcMTime)
{
@@ -810,6 +840,19 @@ static HRESULT Compress(
}
}
+ if (callback)
+ {
+ UInt64 size = 0;
+ if (outStreamSpec)
+ outStreamSpec->GetSize(&size);
+ else if (stdOutFileStreamSpec)
+ size = stdOutFileStreamSpec->GetSize();
+ else
+ size = volStreamSpec->GetSize();
+
+ st.OutArcFileSize = size;
+ }
+
if (outStreamSpec)
result = outStreamSpec->Close();
else if (volStreamSpec)
@@ -817,6 +860,24 @@ static HRESULT Compress(
return result;
}
+bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);
+
+static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item)
+{
+ bool finded = false;
+ FOR_VECTOR (i, censor.Pairs)
+ {
+ bool include;
+ if (CensorNode_CheckPath2(censor.Pairs[i].Head, item, include))
+ {
+ if (!include)
+ return false;
+ finded = true;
+ }
+ }
+ return finded;
+}
+
static HRESULT EnumerateInArchiveItems(
// bool storeStreamsMode,
const NWildcard::CCensor &censor,
@@ -828,18 +889,29 @@ static HRESULT EnumerateInArchiveItems(
IInArchive *archive = arc.Archive;
RINOK(archive->GetNumberOfItems(&numItems));
arcItems.ClearAndReserve(numItems);
+
+ CReadArcItem item;
+
for (UInt32 i = 0; i < numItems; i++)
{
CArcItem ai;
- RINOK(arc.GetItemPath(i, ai.Name));
- RINOK(Archive_IsItem_Folder(archive, i, ai.IsDir));
- RINOK(Archive_IsItem_AltStream(archive, i, ai.IsAltStream));
+ RINOK(arc.GetItem(i, item));
+ ai.Name = item.Path;
+ ai.IsDir = item.IsDir;
+ ai.IsAltStream =
+ #ifdef SUPPORT_ALT_STREAMS
+ item.IsAltStream;
+ #else
+ false;
+ #endif
+
/*
if (!storeStreamsMode && ai.IsAltStream)
continue;
*/
- ai.Censored = censor.CheckPath(ai.IsAltStream, ai.Name, !ai.IsDir);
+ ai.Censored = Censor_CheckPath(censor, item);
+
RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));
RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined));
@@ -867,15 +939,6 @@ static HRESULT EnumerateInArchiveItems(
return S_OK;
}
-struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
-{
- IUpdateCallbackUI2 *Callback;
- HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)
- {
- return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir);
- }
-};
-
#if defined(_WIN32) && !defined(UNDER_CE)
#include <mapi.h>
@@ -884,8 +947,8 @@ struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
struct CRefSortPair
{
- int Len;
- int Index;
+ unsigned Len;
+ unsigned Index;
};
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
@@ -896,18 +959,14 @@ static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, vo
return MyCompare(a1->Index, a2->Index);
}
-static int GetNumSlashes(const FChar *s)
+static unsigned GetNumSlashes(const FChar *s)
{
- for (int numSlashes = 0;;)
+ for (unsigned numSlashes = 0;;)
{
FChar c = *s++;
if (c == 0)
return numSlashes;
- if (
- #ifdef _WIN32
- c == FTEXT('\\') ||
- #endif
- c == FTEXT('/'))
+ if (IS_PATH_SEPAR(c))
numSlashes++;
}
}
@@ -963,12 +1022,11 @@ HRESULT UpdateArchive(
if (options.SfxMode)
{
CProperty property;
- property.Name = L"rsfx";
- property.Value = L"on";
+ property.Name.SetFromAscii("rsfx");
options.MethodMode.Properties.Add(property);
if (options.SfxModule.IsEmpty())
{
- errorInfo.Message = L"SFX file is not specified";
+ errorInfo.Message = "SFX file is not specified";
return E_FAIL;
}
bool found = false;
@@ -984,12 +1042,7 @@ HRESULT UpdateArchive(
if (!found)
{
if (!NFind::DoesFileExist(options.SfxModule))
- {
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"7-Zip cannot find specified SFX module";
- errorInfo.FileName = options.SfxModule;
- return E_FAIL;
- }
+ return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule);
}
}
@@ -1048,24 +1101,28 @@ HRESULT UpdateArchive(
op.stream = NULL;
op.filePath = arcPath;
- HRESULT result = arcLink.Open2(op, openCallback);
+ RINOK(callback->StartOpenArchive(arcPath));
+
+ HRESULT result = arcLink.Open3(op, openCallback);
if (result == E_ABORT)
return result;
- const wchar_t *errorArcType = NULL;
- if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex > 0)
- errorArcType = codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name;
- RINOK(callback->OpenResult(arcPath, result, errorArcType));
+ if (result == S_OK && arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
+ result = S_FALSE;
+
+ HRESULT res2 = callback->OpenResult(codecs, arcLink, arcPath, result);
/*
if (result == S_FALSE)
return E_FAIL;
*/
+ RINOK(res2);
RINOK(result);
+
if (arcLink.VolumePaths.Size() > 1)
{
errorInfo.SystemError = (DWORD)E_NOTIMPL;
- errorInfo.Message = L"Updating for multivolume archives is not implemented";
+ errorInfo.Message = "Updating for multivolume archives is not implemented";
return E_NOTIMPL;
}
@@ -1076,7 +1133,7 @@ HRESULT UpdateArchive(
if (arc.ErrorInfo.ThereIsTail)
{
errorInfo.SystemError = (DWORD)E_NOTIMPL;
- errorInfo.Message = L"There is some data block after the end of the archive";
+ errorInfo.Message = "There is some data block after the end of the archive";
return E_NOTIMPL;
}
if (options.MethodMode.Type.FormatIndex < 0)
@@ -1098,8 +1155,10 @@ HRESULT UpdateArchive(
bool thereIsInArchive = arcLink.IsOpen;
if (!thereIsInArchive && renameMode)
return E_FAIL;
-
+
CDirItems dirItems;
+ dirItems.Callback = callback;
+
CDirItem parentDirItem;
CDirItem *parentDirItem_Ptr = NULL;
@@ -1123,14 +1182,14 @@ HRESULT UpdateArchive(
else
{
bool needScanning = false;
+
if (!renameMode)
FOR_VECTOR (i, options.Commands)
if (options.Commands[i].ActionSet.NeedScanning())
needScanning = true;
+
if (needScanning)
{
- CEnumDirItemUpdateCallback enumCallback;
- enumCallback.Callback = callback;
RINOK(callback->StartScanning());
dirItems.SymLinks = options.SymLinks.Val;
@@ -1140,26 +1199,26 @@ HRESULT UpdateArchive(
#endif
dirItems.ScanAltStreams = options.AltStreams.Val;
+
HRESULT res = EnumerateItems(censor,
options.PathMode,
options.AddPathPrefix,
- dirItems, &enumCallback);
- FOR_VECTOR (i, dirItems.ErrorPaths)
- {
- RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i]));
- }
+ dirItems);
+
if (res != S_OK)
{
if (res != E_ABORT)
- errorInfo.Message = L"Scanning error";
+ errorInfo.Message = "Scanning error";
return res;
}
- RINOK(callback->FinishScanning());
+
+ RINOK(callback->FinishScanning(dirItems.Stat));
if (censor.Pairs.Size() == 1)
{
NFind::CFileInfo fi;
- FString prefix = us2fs(censor.Pairs[0].Prefix) + FTEXT(".");
+ FString prefix = us2fs(censor.Pairs[0].Prefix);
+ prefix += FTEXT('.');
// UString prefix = censor.Pairs[0].Prefix;
/*
if (prefix.Back() == WCHAR_PATH_SEPARATOR)
@@ -1242,10 +1301,10 @@ HRESULT UpdateArchive(
const FString path = us2fs(ap.GetFinalPath());
if (NFind::DoesFileOrDirExist(path))
{
- errorInfo.SystemError = 0;
- errorInfo.Message = L"The file already exists";
- errorInfo.FileName = path;
- return E_FAIL;
+ errorInfo.SystemError = ERROR_FILE_EXISTS;
+ errorInfo.Message = "The file already exists";
+ errorInfo.FileNames.Add(path);
+ return errorInfo.Get_HRESULT_Error();
}
}
}
@@ -1274,27 +1333,40 @@ HRESULT UpdateArchive(
processedItems[i] = 0;
}
+ /*
+ #ifndef _NO_CRYPTO
+ if (arcLink.PasswordWasAsked)
+ {
+ // We set password, if open have requested password
+ RINOK(callback->SetPassword(arcLink.Password));
+ }
+ #endif
+ */
+
for (i = 0; i < options.Commands.Size(); i++)
{
- const CArc *arc = thereIsInArchive ? arcLink.GetArc() : 0;
- // IInArchiveExtra *archiveExtra = thereIsInArchive ? arcLink.GetArchiveExtra() : 0;
- // IArchiveGetRootProps *archiveGetRootProps = thereIsInArchive ? arcLink.GetArchiveGetRootProps() : 0;
+ const CArc *arc = thereIsInArchive ? arcLink.GetArc() : NULL;
CUpdateArchiveCommand &command = options.Commands[i];
UString name;
bool isUpdating;
+
if (options.StdOutMode)
{
- name = L"stdout";
- isUpdating = arc != 0;
+ name.SetFromAscii("stdout");
+ isUpdating = thereIsInArchive;
}
else
{
name = command.ArchivePath.GetFinalPath();
- isUpdating = (i == 0 && options.UpdateArchiveItself && arc != 0);
+ isUpdating = (i == 0 && options.UpdateArchiveItself && thereIsInArchive);
}
+
RINOK(callback->StartArchive(name, isUpdating))
+ CFinishArchiveStat st;
+
RINOK(Compress(options,
+ isUpdating,
codecs,
command.ActionSet,
arc,
@@ -1306,9 +1378,9 @@ HRESULT UpdateArchive(
parentDirItem_Ptr,
tempFiles,
- errorInfo, callback));
+ errorInfo, callback, st));
- RINOK(callback->FinishArchive());
+ RINOK(callback->FinishArchive(st));
}
@@ -1325,21 +1397,16 @@ HRESULT UpdateArchive(
{
CArchivePath &ap = options.Commands[0].ArchivePath;
const FString &tempPath = ap.GetTempPath();
+
if (thereIsInArchive)
if (!DeleteFileAlways(us2fs(arcPath)))
- {
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"7-Zip cannot delete the file";
- errorInfo.FileName = us2fs(arcPath);
- return E_FAIL;
- }
+ return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
+
if (!MyMoveFile(tempPath, us2fs(arcPath)))
{
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"7-Zip cannot move the file";
- errorInfo.FileName = tempPath;
- errorInfo.FileName2 = us2fs(arcPath);
- return E_FAIL;
+ errorInfo.SetFromLastError("cannot move the file", tempPath);
+ errorInfo.FileNames.Add(us2fs(arcPath));
+ return errorInfo.Get_HRESULT_Error();
}
}
catch(...)
@@ -1350,48 +1417,47 @@ HRESULT UpdateArchive(
#if defined(_WIN32) && !defined(UNDER_CE)
+
if (options.EMailMode)
{
NDLL::CLibrary mapiLib;
if (!mapiLib.Load(FTEXT("Mapi32.dll")))
{
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"7-Zip cannot load Mapi32.dll";
- return E_FAIL;
+ errorInfo.SetFromLastError("cannot load Mapi32.dll");
+ return errorInfo.Get_HRESULT_Error();
}
/*
LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");
if (fnSend == 0)
{
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function";
- return E_FAIL;
+ errorInfo.SetFromLastError)("7-Zip cannot find MAPISendDocuments function");
+ return errorInfo.Get_HRESULT_Error();
}
*/
+
LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail");
if (sendMail == 0)
{
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"7-Zip cannot find MAPISendMail function";
- return E_FAIL;
+ errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function");
+ return errorInfo.Get_HRESULT_Error();;
}
FStringVector fullPaths;
unsigned i;
+
for (i = 0; i < options.Commands.Size(); i++)
{
CArchivePath &ap = options.Commands[i].ArchivePath;
+ FString finalPath = us2fs(ap.GetFinalPath());
FString arcPath;
- if (!MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath))
- {
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"GetFullPathName error";
- return E_FAIL;
- }
+ if (!MyGetFullPathName(finalPath, arcPath))
+ return errorInfo.SetFromLastError("GetFullPathName error", finalPath);
fullPaths.Add(arcPath);
}
+
CCurrentDirRestorer curDirRestorer;
+
for (i = 0; i < fullPaths.Size(); i++)
{
UString arcPath = fs2us(fullPaths[i]);
@@ -1426,16 +1492,18 @@ HRESULT UpdateArchive(
sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
}
}
+
#endif
if (options.DeleteAfterCompressing)
{
CRecordVector<CRefSortPair> pairs;
FStringVector foldersNames;
+
for (i = 0; i < dirItems.Items.Size(); i++)
{
const CDirItem &dirItem = dirItems.Items[i];
- FString phyPath = us2fs(dirItems.GetPhyPath(i));
+ FString phyPath = dirItems.GetPhyPath(i);
if (dirItem.IsDir())
{
CRefSortPair pair;
@@ -1447,6 +1515,7 @@ HRESULT UpdateArchive(
{
if (processedItems[i] != 0 || dirItem.Size == 0)
{
+ RINOK(callback->DeletingAfterArchiving(phyPath, false));
DeleteFileAlways(phyPath);
}
else
@@ -1454,7 +1523,7 @@ HRESULT UpdateArchive(
// file was skipped
/*
errorInfo.SystemError = 0;
- errorInfo.Message = L"file was not processed";
+ errorInfo.Message = "file was not processed";
errorInfo.FileName = phyPath;
return E_FAIL;
*/
@@ -1463,15 +1532,19 @@ HRESULT UpdateArchive(
}
pairs.Sort(CompareRefSortPair, NULL);
+
for (i = 0; i < pairs.Size(); i++)
{
- FString phyPath = us2fs(dirItems.GetPhyPath(pairs[i].Index));
+ FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
if (NFind::DoesDirExist(phyPath))
{
- // printf("delete %S\n", phyPath);
+ RINOK(callback->DeletingAfterArchiving(phyPath, true));
RemoveDir(phyPath);
}
}
+
+ RINOK(callback->FinishDeletingAfterArchiving());
}
+
return S_OK;
}
diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h
index 68e51d85..0301ae76 100644
--- a/CPP/7zip/UI/Common/Update.h
+++ b/CPP/7zip/UI/Common/Update.h
@@ -12,6 +12,8 @@
#include "UpdateAction.h"
#include "UpdateCallback.h"
+#include "DirItem.h"
+
enum EArcNameMode
{
k_ArcNameMode_Smart,
@@ -144,32 +146,40 @@ struct CUpdateOptions
CRecordVector<UInt64> VolumesSizes;
};
-struct CErrorInfo
+struct CUpdateErrorInfo
{
DWORD SystemError;
- FString FileName;
- FString FileName2;
- UString Message;
- // UStringVector ErrorPaths;
- // CRecordVector<DWORD> ErrorCodes;
- CErrorInfo(): SystemError(0) {};
+ AString Message;
+ FStringVector FileNames;
+
+ bool ThereIsError() const { return SystemError != 0 || !Message.IsEmpty() || !FileNames.IsEmpty(); }
+ HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); }
+ void SetFromLastError(const char *message);
+ HRESULT SetFromLastError(const char *message, const FString &fileName);
+
+ CUpdateErrorInfo(): SystemError(0) {};
};
-struct CUpdateErrorInfo: public CErrorInfo
+struct CFinishArchiveStat
{
+ UInt64 OutArcFileSize;
+
+ CFinishArchiveStat(): OutArcFileSize(0) {}
};
#define INTERFACE_IUpdateCallbackUI2(x) \
INTERFACE_IUpdateCallbackUI(x) \
- virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) x; \
+ INTERFACE_IDirItemsCallback(x) \
+ virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \
virtual HRESULT StartScanning() x; \
- virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \
- virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \
- virtual HRESULT FinishScanning() x; \
+ virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \
+ virtual HRESULT StartOpenArchive(const wchar_t *name) x; \
virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \
- virtual HRESULT FinishArchive() x; \
+ virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x; \
+ virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x; \
+ virtual HRESULT FinishDeletingAfterArchiving() x; \
-struct IUpdateCallbackUI2: public IUpdateCallbackUI
+struct IUpdateCallbackUI2: public IUpdateCallbackUI, public IDirItemsCallback
{
INTERFACE_IUpdateCallbackUI2(=0)
};
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
index 0115bda3..993ab266 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#ifndef _7ZIP_ST
+#include "../../../Windows/Synchronization.h"
+#endif
+
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
@@ -12,7 +16,6 @@
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/Synchronization.h"
-#include "../../Common/FileStreams.h"
#include "../../Common/StreamObjects.h"
#include "UpdateCallback.h"
@@ -25,25 +28,40 @@
using namespace NWindows;
using namespace NFile;
+#ifndef _7ZIP_ST
+static NSynchronization::CCriticalSection g_CriticalSection;
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+#define MT_LOCK
+#endif
+
+
#ifdef _USE_SECURITY_CODE
bool InitLocalPrivileges();
#endif
CArchiveUpdateCallback::CArchiveUpdateCallback():
- Callback(0),
- ShareForWrite(false),
- StdInMode(false),
- DirItems(0),
- ArcItems(0),
- UpdatePairs(0),
- NewNames(0),
- KeepOriginalItemNames(false),
- ProcessedItemsStatuses(NULL),
- ParentDirItem(NULL),
- StoreNtSecurity(false),
- StoreHardLinks(false),
- StoreSymLinks(false),
- _hardIndex_From((UInt32)(Int32)-1)
+ _hardIndex_From((UInt32)(Int32)-1),
+
+ Callback(NULL),
+
+ DirItems(NULL),
+ ParentDirItem(NULL),
+
+ Arc(NULL),
+ ArcItems(NULL),
+ UpdatePairs(NULL),
+ NewNames(NULL),
+
+ ShareForWrite(false),
+ StdInMode(false),
+
+ KeepOriginalItemNames(false),
+ StoreNtSecurity(false),
+ StoreHardLinks(false),
+ StoreSymLinks(false),
+
+ ProcessedItemsStatuses(NULL)
{
#ifdef _USE_SECURITY_CODE
_saclEnabled = InitLocalPrivileges();
@@ -175,8 +193,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID
return S_OK;
}
- if (GetRootProps)
- return GetRootProps->GetRootRawProp(propID, data, dataSize, propType);
+ if (Arc && Arc->GetRootProps)
+ return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType);
}
#endif
return S_OK;
@@ -198,8 +216,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, con
return S_OK;
const CUpdatePair2 &up = (*UpdatePairs)[index];
- if (up.UseArcProps && up.ExistInArchive() && GetRawProps)
- return GetRawProps->GetRawProp(
+ if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps)
+ return Arc->GetRawProps->GetRawProp(
ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex,
propID, data, dataSize, propType);
@@ -290,7 +308,7 @@ static UString GetRelativePath(const UString &to, const UString &from)
for (k = i; k < partsTo.Size(); k++)
{
if (k != i)
- s += WCHAR_PATH_SEPARATOR;
+ s.Add_PathSepar();
s += partsTo[k];
}
@@ -336,9 +354,9 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
prop = simpleName;
else
{
- const UString phyPath = DirItems->GetPhyPath(up.DirIndex);
+ const FString phyPath = DirItems->GetPhyPath(up.DirIndex);
FString fullPath;
- if (NDir::MyGetFullPathName(us2fs(phyPath), fullPath))
+ if (NDir::MyGetFullPathName(phyPath, fullPath))
{
prop = GetRelativePath(simpleName, fs2us(fullPath));
}
@@ -385,8 +403,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
{
// we can generate new ShortName here;
}
- else if ((up.UseArcProps
- || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream)))
+ else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream)))
&& up.ExistInArchive() && Archive)
return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value);
else if (up.ExistOnDisk())
@@ -414,7 +431,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
static NSynchronization::CCriticalSection CS;
-STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
+STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
{
COM_TRY_BEGIN
*inStream = NULL;
@@ -423,7 +440,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
return E_FAIL;
RINOK(Callback->CheckBreak());
- RINOK(Callback->Finilize());
+ // RINOK(Callback->Finalize());
bool isDir = IsDir(up);
@@ -434,7 +451,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
name = (*ArcItems)[up.ArcIndex].Name;
else if (up.DirIndex >= 0)
name = DirItems->GetLogPath(up.DirIndex);
- RINOK(Callback->GetStream(name, true));
+ RINOK(Callback->GetStream(name, isDir, true, mode));
/* 9.33: fixed. Handlers expect real stream object for files, even for anti-file.
so we return empty stream */
@@ -449,13 +466,17 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
return S_OK;
}
- RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false));
+ RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), isDir, false, mode));
if (isDir)
return S_OK;
if (StdInMode)
{
+ if (mode != NUpdateNotifyOp::kAdd &&
+ mode != NUpdateNotifyOp::kUpdate)
+ return S_OK;
+
CStdInFileStream *inStreamSpec = new CStdInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
*inStream = inStreamLoc.Detach();
@@ -466,20 +487,24 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
inStreamSpec->SupportHardLinks = StoreHardLinks;
+ inStreamSpec->Callback = this;
+ inStreamSpec->CallbackRef = index;
- const UString path = DirItems->GetPhyPath(up.DirIndex);
+ const FString path = DirItems->GetPhyPath(up.DirIndex);
+ _openFiles_Indexes.Add(index);
+ _openFiles_Paths.Add(path);
#if defined(_WIN32) && !defined(UNDER_CE)
if (DirItems->Items[up.DirIndex].AreReparseData())
{
- if (!inStreamSpec->File.OpenReparse(us2fs(path)))
+ if (!inStreamSpec->File.OpenReparse(path))
{
return Callback->OpenFileError(path, ::GetLastError());
}
}
else
#endif
- if (!inStreamSpec->OpenShared(us2fs(path), ShareForWrite))
+ if (!inStreamSpec->OpenShared(path, ShareForWrite))
{
return Callback->OpenFileError(path, ::GetLastError());
}
@@ -512,7 +537,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
if (ProcessedItemsStatuses)
{
NSynchronization::CCriticalSectionLock lock(CS);
- ProcessedItemsStatuses[up.DirIndex] = 1;
+ ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1;
}
*inStream = inStreamLoc.Detach();
}
@@ -521,10 +546,133 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
COM_TRY_END
}
-STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)
+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 opRes)
+{
+ COM_TRY_BEGIN
+ return Callback->SetOperationResult(opRes);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
{
COM_TRY_BEGIN
- return Callback->SetOperationResult(operationResult);
+ return GetStream2(index, inStream,
+ (*UpdatePairs)[index].ArcIndex < 0 ?
+ NUpdateNotifyOp::kAdd :
+ NUpdateNotifyOp::kUpdate);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 index, UInt32 op)
+{
+ COM_TRY_BEGIN
+
+ bool isDir = false;
+
+ if (indexType == NArchive::NEventIndexType::kOutArcIndex)
+ {
+ UString name;
+ if (index != (UInt32)(Int32)-1)
+ {
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ if (up.ExistOnDisk())
+ {
+ name = DirItems->GetLogPath(up.DirIndex);
+ isDir = DirItems->Items[up.DirIndex].IsDir();
+ }
+ }
+ return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);
+ }
+
+ wchar_t temp[16];
+ UString s2;
+ const wchar_t *s = NULL;
+
+ if (indexType == NArchive::NEventIndexType::kInArcIndex)
+ {
+ if (index != (UInt32)(Int32)-1)
+ {
+ if (ArcItems)
+ {
+ const CArcItem &ai = (*ArcItems)[index];
+ s = ai.Name;
+ isDir = ai.IsDir;
+ }
+ else if (Arc)
+ {
+ RINOK(Arc->GetItemPath(index, s2));
+ s = s2;
+ RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir));
+ }
+ }
+ }
+ else if (indexType == NArchive::NEventIndexType::kBlockIndex)
+ {
+ temp[0] = '#';
+ ConvertUInt32ToString(index, temp + 1);
+ s = temp;
+ }
+
+ if (!s)
+ s = L"";
+
+ return Callback->ReportUpdateOpeartion(op, s, isDir);
+
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)
+{
+ COM_TRY_BEGIN
+
+ bool isEncrypted = false;
+ wchar_t temp[16];
+ UString s2;
+ const wchar_t *s = NULL;
+
+ if (indexType == NArchive::NEventIndexType::kOutArcIndex)
+ {
+ /*
+ UString name;
+ if (index != (UInt32)(Int32)-1)
+ {
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ if (up.ExistOnDisk())
+ {
+ s2 = DirItems->GetLogPath(up.DirIndex);
+ s = s2;
+ }
+ }
+ */
+ return E_FAIL;
+ }
+
+ if (indexType == NArchive::NEventIndexType::kInArcIndex)
+ {
+ if (index != (UInt32)(Int32)-1)
+ {
+ if (ArcItems)
+ s = (*ArcItems)[index].Name;
+ else if (Arc)
+ {
+ RINOK(Arc->GetItemPath(index, s2));
+ s = s2;
+ }
+ if (Archive)
+ {
+ RINOK(Archive_GetItemBoolProp(Archive, index, kpidEncrypted, isEncrypted));
+ }
+ }
+ }
+ else if (indexType == NArchive::NEventIndexType::kBlockIndex)
+ {
+ temp[0] = '#';
+ ConvertUInt32ToString(index, temp + 1);
+ s = temp;
+ }
+
+ return Callback->ReportExtractResult(opRes, BoolToInt(isEncrypted), s);
+
COM_TRY_END
}
@@ -547,7 +695,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOu
while (res.Len() < 2)
res.InsertAtFront(FTEXT('0'));
FString fileName = VolName;
- fileName += L'.';
+ fileName += FTEXT('.');
fileName += res;
fileName += VolExt;
COutFileStream *streamSpec = new COutFileStream;
@@ -572,3 +720,38 @@ STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)
return Callback->CryptoGetTextPassword(password);
COM_TRY_END
}
+
+HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)
+{
+ if (error == ERROR_LOCK_VIOLATION)
+ {
+ MT_LOCK
+ UInt32 index = (UInt32)val;
+ FOR_VECTOR(i, _openFiles_Indexes)
+ {
+ if (_openFiles_Indexes[i] == index)
+ {
+ RINOK(Callback->ReadingFileError(_openFiles_Paths[i], error));
+ break;
+ }
+ }
+ }
+ return HRESULT_FROM_WIN32(error);
+}
+
+void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val)
+{
+ MT_LOCK
+ UInt32 index = (UInt32)val;
+ FOR_VECTOR(i, _openFiles_Indexes)
+ {
+ if (_openFiles_Indexes[i] == index)
+ {
+ _openFiles_Indexes.Delete(i);
+ _openFiles_Paths.Delete(i);
+ return;
+ }
+ }
+ throw 20141125;
+}
+
diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
index 3372e628..4ff4a7eb 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/CPP/7zip/UI/Common/UpdateCallback.h
@@ -5,26 +5,35 @@
#include "../../../Common/MyCom.h"
+#include "../../Common/FileStreams.h"
+
#include "../../IPassword.h"
#include "../../ICoder.h"
#include "../Common/UpdatePair.h"
#include "../Common/UpdateProduce.h"
+#include "OpenArchive.h"
+
#define INTERFACE_IUpdateCallbackUI(x) \
+ virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x; \
virtual HRESULT SetTotal(UInt64 size) x; \
virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \
virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \
virtual HRESULT CheckBreak() x; \
- virtual HRESULT Finilize() x; \
- virtual HRESULT SetNumFiles(UInt64 numFiles) x; \
- virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \
- virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \
- virtual HRESULT SetOperationResult(Int32 operationResult) x; \
+ /* virtual HRESULT Finalize() x; */ \
+ virtual HRESULT SetNumItems(UInt64 numItems) x; \
+ virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x; \
+ virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \
+ virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \
+ virtual HRESULT SetOperationResult(Int32 opRes) x; \
+ virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x; \
+ virtual HRESULT ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) x; \
+ /* virtual HRESULT SetPassword(const UString &password) x; */ \
virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \
virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \
- /* virtual HRESULT ShowDeleteFile(const wchar_t *name) x; */ \
- /* virtual HRESULT CloseProgress() { return S_OK; }; */
+ virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x; \
+ /* virtual HRESULT CloseProgress() { return S_OK; } */
struct IUpdateCallbackUI
{
@@ -48,11 +57,14 @@ struct CKeyKeyValPair
class CArchiveUpdateCallback:
public IArchiveUpdateCallback2,
+ public IArchiveUpdateCallbackFile,
+ public IArchiveExtractCallbackMessage,
public IArchiveGetRawProps,
public IArchiveGetRootProps,
public ICryptoGetTextPassword2,
public ICryptoGetTextPassword,
public ICompressProgressInfo,
+ public IInFileStream_Callback,
public CMyUnknownImp
{
#if defined(_WIN32) && !defined(UNDER_CE)
@@ -64,41 +76,53 @@ class CArchiveUpdateCallback:
UInt32 _hardIndex_To;
public:
- MY_UNKNOWN_IMP6(
- IArchiveUpdateCallback2,
- IArchiveGetRawProps,
- IArchiveGetRootProps,
- ICryptoGetTextPassword2,
- ICryptoGetTextPassword,
- ICompressProgressInfo)
+ MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2)
+ MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile)
+ MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)
+ MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
+ MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps)
+ MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword2)
+ MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
+ MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
INTERFACE_IArchiveUpdateCallback2(;)
+ INTERFACE_IArchiveUpdateCallbackFile(;)
+ INTERFACE_IArchiveExtractCallbackMessage(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IArchiveGetRootProps(;)
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+ CRecordVector<UInt32> _openFiles_Indexes;
+ FStringVector _openFiles_Paths;
+
+ bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); }
+ virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error);
+ virtual void InFileStream_On_Destroy(UINT_PTR val);
+
CRecordVector<UInt64> VolumesSizes;
FString VolName;
FString VolExt;
IUpdateCallbackUI *Callback;
- bool ShareForWrite;
- bool StdInMode;
-
const CDirItems *DirItems;
const CDirItem *ParentDirItem;
+ const CArc *Arc;
+ CMyComPtr<IInArchive> Archive;
const CObjectVector<CArcItem> *ArcItems;
const CRecordVector<CUpdatePair2> *UpdatePairs;
const UStringVector *NewNames;
- CMyComPtr<IInArchive> Archive;
- CMyComPtr<IArchiveGetRawProps> GetRawProps;
- CMyComPtr<IArchiveGetRootProps> GetRootProps;
+
+ bool ShareForWrite;
+ bool StdInMode;
bool KeepOriginalItemNames;
bool StoreNtSecurity;
@@ -107,6 +131,7 @@ public:
Byte *ProcessedItemsStatuses;
+
CArchiveUpdateCallback();
bool IsDir(const CUpdatePair2 &up) const
diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp
index aad4a402..68701400 100644
--- a/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -46,8 +46,8 @@ static void ThrowError(const char *message, const UString &s1, const UString &s2
{
UString m;
m.SetFromAscii(message);
- m += L'\n'; m += s1;
- m += L'\n'; m += s2;
+ m.Add_LF(); m += s1;
+ m.Add_LF(); m += s2;
throw m;
}
diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp
index 3089d73c..e6eabcf1 100644
--- a/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -24,15 +24,10 @@ void UpdateProduce(
up2.NewData = up2.NewProps = true;
up2.UseArcProps = false;
- switch (actionSet.StateActions[pair.State])
+ switch (actionSet.StateActions[(unsigned)pair.State])
{
case NPairAction::kIgnore:
- /*
- if (pair.State != NPairState::kOnlyOnDisk)
- IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]);
- // cout << "deleting";
- */
- if (callback)
+ if (pair.ArcIndex >= 0 && callback)
callback->ShowDeleteFile(pair.ArcIndex);
continue;
@@ -67,7 +62,9 @@ void UpdateProduce(
up2.UseArcProps = (pair.ArcIndex >= 0);
break;
}
+
operationChain.Add(up2);
}
+
operationChain.ReserveDown();
}
diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h
index f2adc771..64c58cc5 100644
--- a/CPP/7zip/UI/Common/UpdateProduce.h
+++ b/CPP/7zip/UI/Common/UpdateProduce.h
@@ -43,7 +43,7 @@ struct CUpdatePair2
struct IUpdateProduceCallback
{
- virtual HRESULT ShowDeleteFile(int arcIndex) = 0;
+ virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0;
};
void UpdateProduce(
diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp
index 9ad617f7..735cdda4 100644
--- a/CPP/7zip/UI/Common/WorkDir.cpp
+++ b/CPP/7zip/UI/Common/WorkDir.cpp
@@ -16,6 +16,7 @@ using namespace NDir;
FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName)
{
NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
+
#ifndef UNDER_CE
if (workDirInfo.ForRemovableOnly)
{
@@ -36,13 +37,15 @@ FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FStr
*/
}
#endif
- int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR) + 1;
+
+ int pos = path.ReverseFind_PathSepar() + 1;
fileName = path.Ptr(pos);
+
switch (mode)
{
case NWorkDir::NMode::kCurrent:
{
- return path.Left(pos);;
+ return path.Left(pos);
}
case NWorkDir::NMode::kSpecified:
{
diff --git a/CPP/7zip/UI/Console/BenchCon.cpp b/CPP/7zip/UI/Console/BenchCon.cpp
index 596f447b..a7c9e676 100644
--- a/CPP/7zip/UI/Console/BenchCon.cpp
+++ b/CPP/7zip/UI/Console/BenchCon.cpp
@@ -23,7 +23,7 @@ void CPrintBenchCallback::Print(const char *s)
void CPrintBenchCallback::NewLine()
{
- Print("\n");
+ fputc('\n', _file);
}
HRESULT CPrintBenchCallback::CheckBreak()
@@ -36,7 +36,6 @@ HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS
{
CPrintBenchCallback callback;
callback._file = f;
- callback.NewLine();
return Bench(EXTERNAL_CODECS_LOC_VARS
&callback, NULL, props, numIterations, true);
}
diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp
index c75f4b6e..84ee4a6f 100644
--- a/CPP/7zip/UI/Console/Console.dsp
+++ b/CPP/7zip/UI/Console/Console.dsp
@@ -44,7 +44,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAs /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAs /Yu"StdAfx.h" /FD /GF /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
@@ -69,7 +69,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
@@ -77,7 +77,8 @@ BSC32=bscmake.exe
# 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 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 /subsystem:console /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 /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /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 /subsystem:console /debug /machine:I386 /out:"C:\UTIL\7z.exe" /pdbtype:sept /ignore:4033
+# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "Console - Win32 ReleaseU"
@@ -94,7 +95,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c
-# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
@@ -120,7 +121,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /Gz /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
-# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
@@ -380,6 +381,10 @@ SOURCE=..\..\..\Common\CommandLineParser.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\Common.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\ComTry.h
# End Source File
# Begin Source File
diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp
index 5acae942..75bd9e51 100644
--- a/CPP/7zip/UI/Console/ConsoleClose.cpp
+++ b/CPP/7zip/UI/Console/ConsoleClose.cpp
@@ -4,11 +4,11 @@
#include "ConsoleClose.h"
-static int g_BreakCounter = 0;
-static const int kBreakAbortThreshold = 2;
-
namespace NConsoleClose {
+unsigned g_BreakCounter = 0;
+static const unsigned kBreakAbortThreshold = 2;
+
#if !defined(UNDER_CE) && defined(_WIN32)
static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
{
@@ -35,24 +35,13 @@ static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
}
#endif
-bool TestBreakSignal()
-{
- #ifdef UNDER_CE
- return false;
- #else
- /*
- if (g_BreakCounter > 0)
- return true;
- */
- return (g_BreakCounter > 0);
- #endif
-}
-
+/*
void CheckCtrlBreak()
{
if (TestBreakSignal())
throw CCtrlBreakException();
}
+*/
CCtrlHandlerSetter::CCtrlHandlerSetter()
{
diff --git a/CPP/7zip/UI/Console/ConsoleClose.h b/CPP/7zip/UI/Console/ConsoleClose.h
index 9019c4ce..11c1631c 100644
--- a/CPP/7zip/UI/Console/ConsoleClose.h
+++ b/CPP/7zip/UI/Console/ConsoleClose.h
@@ -1,11 +1,20 @@
-// ConsoleCloseUtils.h
+// ConsoleClose.h
-#ifndef __CONSOLECLOSEUTILS_H
-#define __CONSOLECLOSEUTILS_H
+#ifndef __CONSOLE_CLOSE_H
+#define __CONSOLE_CLOSE_H
namespace NConsoleClose {
-bool TestBreakSignal();
+extern unsigned g_BreakCounter;
+
+inline bool TestBreakSignal()
+{
+ #ifdef UNDER_CE
+ return false;
+ #else
+ return (g_BreakCounter != 0);
+ #endif
+}
class CCtrlHandlerSetter
{
@@ -17,7 +26,7 @@ public:
class CCtrlBreakException
{};
-void CheckCtrlBreak();
+// void CheckCtrlBreak();
}
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
index d3366a39..8dac7fbc 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -2,12 +2,6 @@
#include "StdAfx.h"
-// #undef sprintf
-
-#include "ConsoleClose.h"
-#include "ExtractCallbackConsole.h"
-#include "UserInputUtils.h"
-
#include "../../../Common/IntToString.h"
#include "../../../Common/Wildcard.h"
@@ -17,25 +11,146 @@
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/PropVariantConv.h"
+#ifndef _7ZIP_ST
+#include "../../../Windows/Synchronization.h"
+#endif
+
#include "../../Common/FilePathAutoRename.h"
#include "../Common/ExtractingFilePath.h"
+#include "ConsoleClose.h"
+#include "ExtractCallbackConsole.h"
+#include "UserInputUtils.h"
+
using namespace NWindows;
using namespace NFile;
using namespace NDir;
-static const char *kTestString = "Testing ";
-static const char *kExtractString = "Extracting ";
-static const char *kSkipString = "Skipping ";
+static HRESULT CheckBreak2()
+{
+ return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
+}
+
+static const char *kError = "ERROR: ";
+
+
+void CExtractScanConsole::StartScanning()
+{
+ if (NeedPercents())
+ _percent.Command = "Scan";
+}
+
+HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
+{
+ if (NeedPercents())
+ {
+ _percent.Files = st.NumDirs + st.NumFiles;
+ _percent.Completed = st.GetTotalBytes();
+ _percent.FileName = fs2us(path);
+ _percent.Print();
+ }
+
+ return CheckBreak2();
+}
+
+HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError)
+{
+ ClosePercentsAndFlush();
+
+ if (_se)
+ {
+ *_se << endl << kError << NError::MyFormatMessage(systemError) << endl <<
+ fs2us(path) << endl << endl;
+ _se->Flush();
+ }
+ return HRESULT_FROM_WIN32(systemError);
+}
+
+
+void Print_UInt64_and_String(AString &s, UInt64 val, const char *name)
+{
+ char temp[32];
+ ConvertUInt64ToString(val, temp);
+ s += temp;
+ s.Add_Space();
+ s += name;
+}
+
+void PrintSize_bytes_Smart(AString &s, UInt64 val)
+{
+ Print_UInt64_and_String(s, val, "bytes");
+
+ if (val == 0)
+ return;
+
+ unsigned numBits = 10;
+ char c = 'K';
+ char temp[4] = { 'K', 'i', 'B', 0 };
+ if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; }
+ else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; }
+ temp[0] = c;
+ s += " (";
+ Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);
+ s += ')';
+}
+
+void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
+{
+ if (st.NumDirs != 0)
+ {
+ Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? "folder" : "folders");
+ s += ", ";
+ }
+ Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files");
+ s += ", ";
+ PrintSize_bytes_Smart(s, st.FilesSize);
+ if (st.NumAltStreams != 0)
+ {
+ s.Add_LF();
+ Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams");
+ s += ", ";
+ PrintSize_bytes_Smart(s, st.AltStreamsSize);
+ }
+}
+
+void CExtractScanConsole::PrintStat(const CDirItemsStat &st)
+{
+ if (_so)
+ {
+ AString s;
+ Print_DirItemsStat(s, st);
+ *_so << s << endl;
+ }
+}
+
+
+
+
+
+
+
+#ifndef _7ZIP_ST
+static NSynchronization::CCriticalSection g_CriticalSection;
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+#define MT_LOCK
+#endif
+
+
+static const char *kTestString = "T";
+static const char *kExtractString = "-";
+static const char *kSkipString = ".";
// static const char *kCantAutoRename = "can not create file with auto name\n";
// static const char *kCantRenameFile = "can not rename existing file\n";
// static const char *kCantDeleteOutputFile = "can not delete output file ";
-static const char *kError = "ERROR: ";
+
static const char *kMemoryExceptionMessage = "Can't allocate required memory!";
-static const char *kProcessing = "Processing archive: ";
+static const char *kExtracting = "Extracting archive: ";
+static const char *kTesting = "Testing archive: ";
+
static const char *kEverythingIsOk = "Everything is Ok";
static const char *kNoFiles = "No files to process";
@@ -49,8 +164,9 @@ static const char *kUnexpectedEnd = "Unexpected end of data";
static const char *kDataAfterEnd = "There are some data after the end of the payload data";
static const char *kIsNotArc = "Is not archive";
static const char *kHeadersError = "Headers Error";
+static const char *kWrongPassword = "Wrong password";
-static const char *k_ErrorFlagsMessages[] =
+static const char * const k_ErrorFlagsMessages[] =
{
"Is not archive"
, "Headers Error"
@@ -65,31 +181,72 @@ static const char *k_ErrorFlagsMessages[] =
, "CRC Error"
};
+STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size)
+{
+ MT_LOCK
+
+ if (NeedPercents())
+ {
+ _percent.Total = size;
+ _percent.Print();
+ }
+ return CheckBreak2();
+}
-STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)
+STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
+ MT_LOCK
+
+ if (NeedPercents())
+ {
+ if (completeValue)
+ _percent.Completed = *completeValue;
+ _percent.Print();
+ }
+ return CheckBreak2();
}
-STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)
+static const char *kTab = " ";
+
+static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)
{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
+ *_so << kTab << "Path: " << path << endl;
+ if (size)
+ {
+ AString s;
+ PrintSize_bytes_Smart(s, *size);
+ *_so << kTab << "Size: " << s << endl;
+ }
+ if (ft)
+ {
+ char temp[64];
+ FILETIME locTime;
+ if (FileTimeToLocalFileTime(ft, &locTime))
+ if (ConvertFileTimeToString(locTime, temp, true, true))
+ *_so << kTab << "Modified: " << temp << endl;
+ }
}
STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
- const wchar_t *existName, const FILETIME *, const UInt64 *,
- const wchar_t *newName, const FILETIME *, const UInt64 *,
+ const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
+ const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
Int32 *answer)
{
- (*OutStream) << "file " << existName << endl <<
- "already exists. Overwrite with" << endl <<
- newName;
+ MT_LOCK
- NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);
+ RINOK(CheckBreak2());
+
+ ClosePercentsAndFlush();
+
+ if (_so)
+ {
+ *_so << endl << "Would you like to replace the existing file:\n";
+ PrintFileInfo(_so, existName, existTime, existSize);
+ *_so << "with the file from archive:\n";
+ PrintFileInfo(_so, newName, newTime, newSize);
+ }
+
+ NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so);
switch (overwriteAnswer)
{
@@ -101,86 +258,192 @@ STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;
default: return E_FAIL;
}
- return S_OK;
+
+ if (_so)
+ {
+ *_so << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
+
+ return CheckBreak2();
}
-STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position)
+STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 *position)
{
+ MT_LOCK
+
+ _currentName = name;
+
const char *s;
+ unsigned requiredLevel = 1;
+
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;
case NArchive::NExtract::NAskMode::kTest: s = kTestString; break;
- case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; break;
- default: s = ""; // return E_FAIL;
+ case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; requiredLevel = 2; break;
+ default: s = "???"; requiredLevel = 2;
};
- (*OutStream) << s << name;
- if (position != 0)
- (*OutStream) << " <" << *position << ">";
- return S_OK;
+
+ bool show2 = (LogLevel >= requiredLevel && _so);
+
+ if (show2)
+ {
+ ClosePercents_for_so();
+
+ _tempA = s;
+ if (name)
+ _tempA.Add_Space();
+ *_so << _tempA;
+
+ _tempU.Empty();
+ if (name)
+ _tempU = name;
+ _so->PrintUString(_tempU, _tempA);
+ if (position)
+ *_so << " <" << *position << ">";
+ *_so << endl;
+
+ if (NeedFlush)
+ _so->Flush();
+ }
+
+ if (NeedPercents())
+ {
+ if (PercentsNameLevel >= 1)
+ {
+ _percent.FileName.Empty();
+ _percent.Command.Empty();
+ if (PercentsNameLevel > 1 || !show2)
+ {
+ _percent.Command = s;
+ if (name)
+ _percent.FileName = name;
+ }
+ }
+ _percent.Print();
+ }
+
+ return CheckBreak2();
}
STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
{
- (*OutStream) << message << endl;
- NumFileErrorsInCurrent++;
+ MT_LOCK
+
+ RINOK(CheckBreak2());
+
+ NumFileErrors_in_Current++;
NumFileErrors++;
- return S_OK;
+
+ ClosePercentsAndFlush();
+ if (_se)
+ {
+ *_se << kError << message << endl;
+ _se->Flush();
+ }
+
+ return CheckBreak2();
}
-STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)
{
- switch (operationResult)
+ dest.Empty();
+ const char *s = NULL;
+
+ switch (opRes)
+ {
+ case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
+ s = kUnsupportedMethod;
+ break;
+ case NArchive::NExtract::NOperationResult::kCRCError:
+ s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);
+ break;
+ case NArchive::NExtract::NOperationResult::kDataError:
+ s = (encrypted ? kDataErrorEncrypted : kDataError);
+ break;
+ case NArchive::NExtract::NOperationResult::kUnavailable:
+ s = kUnavailableData;
+ break;
+ case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
+ s = kUnexpectedEnd;
+ break;
+ case NArchive::NExtract::NOperationResult::kDataAfterEnd:
+ s = kDataAfterEnd;
+ break;
+ case NArchive::NExtract::NOperationResult::kIsNotArc:
+ s = kIsNotArc;
+ break;
+ case NArchive::NExtract::NOperationResult::kHeadersError:
+ s = kHeadersError;
+ break;
+ case NArchive::NExtract::NOperationResult::kWrongPassword:
+ s = kWrongPassword;
+ break;
+ }
+
+ dest += kError;
+ if (s)
+ dest += s;
+ else
+ {
+ char temp[16];
+ ConvertUInt32ToString(opRes, temp);
+ dest += "Error #";
+ dest += temp;
+ }
+}
+
+STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted)
+{
+ MT_LOCK
+
+ if (opRes == NArchive::NExtract::NOperationResult::kOK)
{
- case NArchive::NExtract::NOperationResult::kOK:
- break;
- default:
+ if (NeedPercents())
{
- NumFileErrorsInCurrent++;
- NumFileErrors++;
- (*OutStream) << " : ";
- const char *s = NULL;
- switch (operationResult)
- {
- case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
- s = kUnsupportedMethod;
- break;
- case NArchive::NExtract::NOperationResult::kCRCError:
- s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);
- break;
- case NArchive::NExtract::NOperationResult::kDataError:
- s = (encrypted ? kDataErrorEncrypted : kDataError);
- break;
- case NArchive::NExtract::NOperationResult::kUnavailable:
- s = kUnavailableData;
- break;
- case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
- s = kUnexpectedEnd;
- break;
- case NArchive::NExtract::NOperationResult::kDataAfterEnd:
- s = kDataAfterEnd;
- break;
- case NArchive::NExtract::NOperationResult::kIsNotArc:
- s = kIsNotArc;
- break;
- case NArchive::NExtract::NOperationResult::kHeadersError:
- s = kHeadersError;
- break;
- }
- if (s)
- (*OutStream) << "Error : " << s;
- else
- {
- char temp[16];
- ConvertUInt32ToString(operationResult, temp);
- (*OutStream) << "Error #" << temp;
- }
+ _percent.Command.Empty();
+ _percent.FileName.Empty();
+ _percent.Files++;
}
}
- (*OutStream) << endl;
- return S_OK;
+ else
+ {
+ NumFileErrors_in_Current++;
+ NumFileErrors++;
+
+ if (_se)
+ {
+ ClosePercentsAndFlush();
+
+ AString s;
+ SetExtractErrorMessage(opRes, encrypted, s);
+
+ *_se << s;
+ if (!_currentName.IsEmpty())
+ *_se << " : " << _currentName;
+ *_se << endl;
+ _se->Flush();
+ }
+ }
+
+ return CheckBreak2();
}
+STDMETHODIMP CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)
+{
+ if (opRes != NArchive::NExtract::NOperationResult::kOK)
+ {
+ _currentName = name;
+ return SetOperationResult(opRes, encrypted);
+ }
+
+ return CheckBreak2();
+}
+
+
+
#ifndef _NO_CRYPTO
HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
@@ -192,55 +455,39 @@ HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
{
- if (!PasswordIsDefined)
- {
- Password = GetPassword(OutStream);
- PasswordIsDefined = true;
- }
- return StringToBstr(Password, password);
+ COM_TRY_BEGIN
+ MT_LOCK
+ return Open_CryptoGetTextPassword(password);
+ COM_TRY_END
}
#endif
-HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)
+HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)
{
+ RINOK(CheckBreak2());
+
NumTryArcs++;
- ThereIsErrorInCurrent = false;
- ThereIsWarningInCurrent = false;
- NumFileErrorsInCurrent = 0;
- (*OutStream) << endl << kProcessing << name << endl;
- return S_OK;
-}
+ ThereIsError_in_Current = false;
+ ThereIsWarning_in_Current = false;
+ NumFileErrors_in_Current = 0;
+
+ ClosePercents_for_so();
+ if (_so)
+ *_so << endl << (testMode ? kTesting : kExtracting) << name << endl;
-HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted)
-{
- (*OutStream) << endl;
- if (result != S_OK)
- {
- (*OutStream) << "Error: ";
- if (result == S_FALSE)
- {
- (*OutStream) << (encrypted ?
- "Can not open encrypted archive. Wrong password?" :
- "Can not open file as archive");
- }
- else
- {
- if (result == E_OUTOFMEMORY)
- (*OutStream) << "Can't allocate required memory";
- else
- (*OutStream) << NError::MyFormatMessage(result);
- }
- (*OutStream) << endl;
- NumCantOpenArcs++;
- ThereIsErrorInCurrent = true;
- }
+ if (NeedPercents())
+ _percent.Command = "Open";
return S_OK;
}
-AString GetOpenArcErrorMessage(UInt32 errorFlags)
+HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
+HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
+
+static AString GetOpenArcErrorMessage(UInt32 errorFlags)
{
AString s;
+
for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++)
{
UInt32 f = (1 << i);
@@ -248,10 +495,11 @@ AString GetOpenArcErrorMessage(UInt32 errorFlags)
continue;
const char *m = k_ErrorFlagsMessages[i];
if (!s.IsEmpty())
- s += '\n';
+ s.Add_LF();
s += m;
errorFlags &= ~f;
}
+
if (errorFlags != 0)
{
char sz[16];
@@ -259,125 +507,258 @@ AString GetOpenArcErrorMessage(UInt32 errorFlags)
sz[1] = 'x';
ConvertUInt32ToHex(errorFlags, sz + 2);
if (!s.IsEmpty())
- s += '\n';
+ s.Add_LF();
s += sz;
}
+
return s;
}
+void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags)
+{
+ if (errorFlags == 0)
+ return;
+ so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;
+}
+
+void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType)
+{
+ s.Add_LF();
+ s.AddAscii(pre);
+ s.AddAscii(" as [");
+ s += arcType;
+ s.AddAscii("] archive");
+}
-HRESULT CExtractCallbackConsole::SetError(int level, const wchar_t *name,
- UInt32 errorFlags, const wchar_t *errors,
- UInt32 warningFlags, const wchar_t *warnings)
+void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc)
{
- if (level != 0)
+ const CArcErrorInfo &er = arc.ErrorInfo;
+
+ UString s = L"WARNING:\n";
+ s += arc.Path;
+ if (arc.FormatIndex == er.ErrorFormatIndex)
{
- (*OutStream) << name << endl;
+ s.Add_LF();
+ s.AddAscii("The archive is open with offset");
}
-
- if (errorFlags != 0)
+ else
{
- (*OutStream) << "Errors: ";
- (*OutStream) << endl;
- (*OutStream) << GetOpenArcErrorMessage(errorFlags);
- (*OutStream) << endl;
- NumOpenArcErrors++;
- ThereIsErrorInCurrent = true;
+ Add_Messsage_Pre_ArcType(s, "Can not open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex));
+ Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex));
}
+
+ *_so << s << endl << endl;
+}
+
+
+HRESULT CExtractCallbackConsole::OpenResult(
+ const CCodecs *codecs, const CArchiveLink &arcLink,
+ const wchar_t *name, HRESULT result)
+{
+ ClosePercents();
- if (errors && wcslen(errors) != 0)
+ if (NeedPercents())
{
- (*OutStream) << "Errors: ";
- (*OutStream) << endl;
- (*OutStream) << errors;
- (*OutStream) << endl;
- NumOpenArcErrors++;
- ThereIsErrorInCurrent = true;
+ _percent.Files = 0;
+ _percent.Command.Empty();
+ _percent.FileName.Empty();
}
- if (warningFlags != 0)
+
+ ClosePercentsAndFlush();
+
+ FOR_VECTOR (level, arcLink.Arcs)
{
- (*OutStream) << "Warnings: ";
- (*OutStream) << endl;
- (*OutStream) << GetOpenArcErrorMessage(warningFlags);
- (*OutStream) << endl;
- NumOpenArcWarnings++;
- ThereIsWarningInCurrent = true;
- }
+ const CArc &arc = arcLink.Arcs[level];
+ const CArcErrorInfo &er = arc.ErrorInfo;
+
+ UInt32 errorFlags = er.GetErrorFlags();
+
+ if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
+ {
+ if (_se)
+ {
+ *_se << endl;
+ if (level != 0)
+ *_se << arc.Path << endl;
+ }
+
+ if (errorFlags != 0)
+ {
+ if (_se)
+ PrintErrorFlags(*_se, "ERRORS:", errorFlags);
+ NumOpenArcErrors++;
+ ThereIsError_in_Current = true;
+ }
+
+ if (!er.ErrorMessage.IsEmpty())
+ {
+ if (_se)
+ *_se << "ERRORS:" << endl << er.ErrorMessage << endl;
+ NumOpenArcErrors++;
+ ThereIsError_in_Current = true;
+ }
+
+ if (_se)
+ {
+ *_se << endl;
+ _se->Flush();
+ }
+ }
+
+ UInt32 warningFlags = er.GetWarningFlags();
+
+ if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
+ {
+ if (_so)
+ {
+ *_so << endl;
+ if (level != 0)
+ *_so << arc.Path << endl;
+ }
+
+ if (warningFlags != 0)
+ {
+ if (_so)
+ PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
+ NumOpenArcWarnings++;
+ ThereIsWarning_in_Current = true;
+ }
+
+ if (!er.WarningMessage.IsEmpty())
+ {
+ if (_so)
+ *_so << "WARNINGS:" << endl << er.WarningMessage << endl;
+ NumOpenArcWarnings++;
+ ThereIsWarning_in_Current = true;
+ }
+
+ if (_so)
+ {
+ *_so << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
+ }
- if (warnings && wcslen(warnings) != 0)
+
+ if (er.ErrorFormatIndex >= 0)
+ {
+ if (_so)
+ {
+ Print_ErrorFormatIndex_Warning(_so, codecs, arc);
+ if (NeedFlush)
+ _so->Flush();
+ }
+ ThereIsWarning_in_Current = true;
+ }
+ }
+
+ if (result == S_OK)
{
- (*OutStream) << "Warnings: ";
- (*OutStream) << endl;
- (*OutStream) << warnings;
- (*OutStream) << endl;
- NumOpenArcWarnings++;
- ThereIsWarningInCurrent = true;
+ if (_so)
+ {
+ RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
+ *_so << endl;
+ }
}
-
- (*OutStream) << endl;
- return S_OK;
+ else
+ {
+ NumCantOpenArcs++;
+ if (_so)
+ _so->Flush();
+ if (_se)
+ {
+ *_se << kError << name << endl;
+ HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
+ RINOK(res);
+ if (result == S_FALSE)
+ {
+ }
+ else
+ {
+ if (result == E_OUTOFMEMORY)
+ *_se << "Can't allocate required memory";
+ else
+ *_se << NError::MyFormatMessage(result);
+ *_se << endl;
+ }
+ _se->Flush();
+ }
+ }
+
+
+ return CheckBreak2();
}
HRESULT CExtractCallbackConsole::ThereAreNoFiles()
{
- (*OutStream) << endl << kNoFiles << endl;
- return S_OK;
+ ClosePercents_for_so();
+
+ if (_so)
+ {
+ *_so << endl << kNoFiles << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
+ return CheckBreak2();
}
HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
{
- if (result == S_OK)
+ MT_LOCK
+
+ if (NeedPercents())
{
- (*OutStream) << endl;
+ _percent.ClosePrint(true);
+ _percent.Command.Empty();
+ _percent.FileName.Empty();
+ }
- if (NumFileErrorsInCurrent == 0 && !ThereIsErrorInCurrent)
+ if (_so)
+ _so->Flush();
+
+ if (result == S_OK)
+ {
+ if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current)
{
- if (ThereIsWarningInCurrent)
+ if (ThereIsWarning_in_Current)
NumArcsWithWarnings++;
else
NumOkArcs++;
- (*OutStream) << kEverythingIsOk << endl;
+ if (_so)
+ *_so << kEverythingIsOk << endl;
}
else
{
NumArcsWithError++;
- if (NumFileErrorsInCurrent != 0)
- (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrent << endl;
+ if (_so)
+ {
+ *_so << endl;
+ if (NumFileErrors_in_Current != 0)
+ *_so << "Sub items Errors: " << NumFileErrors_in_Current << endl;
+ }
}
- return S_OK;
+ if (_so && NeedFlush)
+ _so->Flush();
}
-
- NumArcsWithError++;
- if (result == E_ABORT || result == ERROR_DISK_FULL)
- return result;
- (*OutStream) << endl << kError;
- if (result == E_OUTOFMEMORY)
- (*OutStream) << kMemoryExceptionMessage;
else
- (*OutStream) << NError::MyFormatMessage(result);
- (*OutStream) << endl;
- return S_OK;
-}
-
-HRESULT CExtractCallbackConsole::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType)
-{
- UString s = L"Warning:\n";
- if (wcscmp(okType, errorType) == 0)
{
- s += L"The archive is open with offset";
- }
- else
- {
- s += name;
- s += L"\nCan not open the file as [";
- s += errorType;
- s += L"] archive\n";
- s += L"The file is open as [";
- s += okType;
- s += L"] archive";
+ NumArcsWithError++;
+ if (result == E_ABORT || result == ERROR_DISK_FULL)
+ return result;
+
+ if (_se)
+ {
+ *_se << endl << kError;
+ if (result == E_OUTOFMEMORY)
+ *_se << kMemoryExceptionMessage;
+ else
+ *_se << NError::MyFormatMessage(result);
+ *_se << endl;
+ _se->Flush();
+ }
}
- (*OutStream) << s << endl << endl;
- ThereIsWarningInCurrent = true;
- return S_OK;
+
+ return CheckBreak2();
}
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
index 9a0afdc9..dc659521 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.h
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.h
@@ -1,28 +1,95 @@
// ExtractCallbackConsole.h
-#ifndef __EXTRACTCALLBACKCONSOLE_H
-#define __EXTRACTCALLBACKCONSOLE_H
+#ifndef __EXTRACT_CALLBACK_CONSOLE_H
+#define __EXTRACT_CALLBACK_CONSOLE_H
-#include "../../../Common/MyString.h"
#include "../../../Common/StdOutStream.h"
-#include "../../Common/FileStreams.h"
-
#include "../../IPassword.h"
#include "../../Archive/IArchive.h"
#include "../Common/ArchiveExtractCallback.h"
+#include "PercentPrinter.h"
+
+#include "OpenCallbackConsole.h"
+
+class CExtractScanConsole: public IDirItemsCallback
+{
+ CStdOutStream *_so;
+ CStdOutStream *_se;
+ CPercentPrinter _percent;
+
+ bool NeedPercents() const { return _percent._so != NULL; }
+
+ void ClosePercentsAndFlush()
+ {
+ if (NeedPercents())
+ _percent.ClosePrint(true);
+ if (_so)
+ _so->Flush();
+ }
+
+public:
+ void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
+ {
+ _so = outStream;
+ _se = errorStream;
+ _percent._so = percentStream;
+ }
+
+ void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
+
+ void StartScanning();
+
+ INTERFACE_IDirItemsCallback(;)
+
+ void CloseScanning()
+ {
+ if (NeedPercents())
+ _percent.ClosePrint(true);
+ }
+
+ void PrintStat(const CDirItemsStat &st);
+};
+
+
+
+
class CExtractCallbackConsole:
public IExtractCallbackUI,
+ // public IArchiveExtractCallbackMessage,
+ public IFolderArchiveExtractCallback2,
#ifndef _NO_CRYPTO
public ICryptoGetTextPassword,
#endif
+ public COpenCallbackConsole,
public CMyUnknownImp
{
+ AString _tempA;
+ UString _tempU;
+
+ UString _currentName;
+
+ void ClosePercents_for_so()
+ {
+ if (NeedPercents() && _so == _percent._so)
+ _percent.ClosePrint(false);
+ }
+
+ void ClosePercentsAndFlush()
+ {
+ if (NeedPercents())
+ _percent.ClosePrint(true);
+ if (_so)
+ _so->Flush();
+ }
+
public:
MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
+ // MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)
+ MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
#ifndef _NO_CRYPTO
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
@@ -32,57 +99,55 @@ public:
STDMETHOD(SetTotal)(UInt64 total);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
- // IFolderArchiveExtractCallback
- STDMETHOD(AskOverwrite)(
- const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
- const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
- Int32 *answer);
- STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);
-
- STDMETHOD(MessageError)(const wchar_t *message);
- STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);
+ INTERFACE_IFolderArchiveExtractCallback(;)
- HRESULT BeforeOpen(const wchar_t *name);
- HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);
- HRESULT SetError(int level, const wchar_t *name,
- UInt32 errorFlags, const wchar_t *errors,
- UInt32 warningFlags, const wchar_t *warnings);
+ INTERFACE_IExtractCallbackUI(;)
+ // INTERFACE_IArchiveExtractCallbackMessage(;)
+ INTERFACE_IFolderArchiveExtractCallback2(;)
- HRESULT ThereAreNoFiles();
- HRESULT ExtractResult(HRESULT result);
- HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType);
-
-
#ifndef _NO_CRYPTO
- HRESULT SetPassword(const UString &password);
- STDMETHOD(CryptoGetTextPassword)(BSTR *password);
- bool PasswordIsDefined;
- UString Password;
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
#endif
UInt64 NumTryArcs;
- bool ThereIsErrorInCurrent;
- bool ThereIsWarningInCurrent;
+
+ bool ThereIsError_in_Current;
+ bool ThereIsWarning_in_Current;
- UInt64 NumCantOpenArcs;
UInt64 NumOkArcs;
+ UInt64 NumCantOpenArcs;
UInt64 NumArcsWithError;
UInt64 NumArcsWithWarnings;
- UInt64 NumProblemArcsLevs;
UInt64 NumOpenArcErrors;
UInt64 NumOpenArcWarnings;
UInt64 NumFileErrors;
- UInt64 NumFileErrorsInCurrent;
+ UInt64 NumFileErrors_in_Current;
- CStdOutStream *OutStream;
+ bool NeedFlush;
+ unsigned PercentsNameLevel;
+ unsigned LogLevel;
- void Init()
+ CExtractCallbackConsole():
+ NeedFlush(false),
+ PercentsNameLevel(1),
+ LogLevel(0)
+ {}
+
+ void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
+
+ void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
{
+ COpenCallbackConsole::Init(outStream, errorStream, percentStream);
+
NumTryArcs = 0;
+
+ ThereIsError_in_Current = false;
+ ThereIsWarning_in_Current = false;
+
NumOkArcs = 0;
NumCantOpenArcs = 0;
NumArcsWithError = 0;
@@ -90,10 +155,10 @@ public:
NumOpenArcErrors = 0;
NumOpenArcWarnings = 0;
+
NumFileErrors = 0;
- NumFileErrorsInCurrent = 0;
+ NumFileErrors_in_Current = 0;
}
-
};
#endif
diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp
index 273f21c8..a71e4b50 100644
--- a/CPP/7zip/UI/Console/HashCon.cpp
+++ b/CPP/7zip/UI/Console/HashCon.cpp
@@ -3,9 +3,6 @@
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
-#include "../../../Common/StringConvert.h"
-
-#include "../../../Windows/ErrorMsg.h"
#include "ConsoleClose.h"
#include "HashCon.h"
@@ -14,53 +11,85 @@ static const wchar_t *kEmptyFileAlias = L"[Content]";
static const char *kScanningMessage = "Scanning";
-HRESULT CHashCallbackConsole::CheckBreak()
+static HRESULT CheckBreak2()
{
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
}
+HRESULT CHashCallbackConsole::CheckBreak()
+{
+ return CheckBreak2();
+}
+
HRESULT CHashCallbackConsole::StartScanning()
{
- (*OutStream) << kScanningMessage;
- return CheckBreak();
+ if (PrintHeaders && _so)
+ *_so << kScanningMessage << endl;
+ if (NeedPercents())
+ {
+ _percent.ClearCurState();
+ _percent.Command = "Scan";
+ }
+ return CheckBreak2();
}
-HRESULT CHashCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */)
+HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
{
- return CheckBreak();
+ if (NeedPercents())
+ {
+ _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
+ _percent.Completed = st.GetTotalBytes();
+ _percent.FileName = fs2us(path);
+ _percent.Print();
+ }
+ return CheckBreak2();
}
-HRESULT CHashCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)
+HRESULT CHashCallbackConsole::ScanError(const FString &path, DWORD systemError)
{
- return CanNotFindError_Base(name, systemError);
+ return ScanError_Base(path, systemError);
}
-HRESULT CHashCallbackConsole::FinishScanning()
+void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
+
+HRESULT CHashCallbackConsole::FinishScanning(const CDirItemsStat &st)
{
- (*OutStream) << endl << endl;
- return CheckBreak();
+ if (NeedPercents())
+ {
+ _percent.ClosePrint(true);
+ _percent.ClearCurState();
+ }
+ if (PrintHeaders && _so)
+ {
+ Print_DirItemsStat(_s, st);
+ *_so << _s << endl << endl;
+ }
+ return CheckBreak2();
}
HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */)
{
- return CheckBreak();
+ return CheckBreak2();
}
HRESULT CHashCallbackConsole::SetTotal(UInt64 size)
{
- if (EnablePercents)
- m_PercentPrinter.SetTotal(size);
- return CheckBreak();
+ if (NeedPercents())
+ {
+ _percent.Total = size;
+ _percent.Print();
+ }
+ return CheckBreak2();
}
HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
- if (completeValue && EnablePercents)
+ if (completeValue && NeedPercents())
{
- m_PercentPrinter.SetRatio(*completeValue);
- m_PercentPrinter.PrintRatio();
+ _percent.Completed = *completeValue;
+ _percent.Print();
}
- return CheckBreak();
+ return CheckBreak2();
}
static void AddMinuses(AString &s, unsigned num)
@@ -69,171 +98,228 @@ static void AddMinuses(AString &s, unsigned num)
s += '-';
}
-static void SetSpaces(char *s, int num)
+static void AddSpaces_if_Positive(AString &s, int num)
{
for (int i = 0; i < num; i++)
- s[i] = ' ';
+ s.Add_Space();
}
-static void SetSpacesAndNul(char *s, int num)
+static void SetSpacesAndNul(char *s, unsigned num)
{
- SetSpaces(s, num);
+ for (unsigned i = 0; i < num; i++)
+ s[i] = ' ';
s[num] = 0;
}
-static void AddSpaces(UString &s, int num)
-{
- for (int i = 0; i < num; i++)
- s += ' ';
-}
+static const unsigned kSizeField_Len = 13;
+static const unsigned kNameField_Len = 12;
-static const int kSizeField_Len = 13;
-static const int kNameField_Len = 12;
+static const unsigned kHashColumnWidth_Min = 4 * 2;
static unsigned GetColumnWidth(unsigned digestSize)
{
unsigned width = digestSize * 2;
- const unsigned kMinColumnWidth = 8;
- return width < kMinColumnWidth ? kMinColumnWidth: width;
+ return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width;
}
void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers)
{
- AString s;
+ _s.Empty();
+
for (unsigned i = 0; i < hashers.Size(); i++)
{
+ if (i != 0)
+ _s.Add_Space();
const CHasherState &h = hashers[i];
- AddMinuses(s, GetColumnWidth(h.DigestSize));
- s += ' ';
+ AddMinuses(_s, GetColumnWidth(h.DigestSize));
+ }
+
+ if (PrintSize)
+ {
+ _s.Add_Space();
+ AddMinuses(_s, kSizeField_Len);
}
- AddMinuses(s, kSizeField_Len);
- s += " ";
- AddMinuses(s, kNameField_Len);
- m_PercentPrinter.PrintString(s);
- m_PercentPrinter.PrintNewLine();
+
+ if (PrintName)
+ {
+ AddSpacesBeforeName();
+ AddMinuses(_s, kNameField_Len);
+ }
+
+ *_so << _s << endl;
}
HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb)
{
- UString s;
- FOR_VECTOR (i, hb.Hashers)
+ if (PrintHeaders && _so)
{
- const CHasherState &h = hb.Hashers[i];
- s += h.Name;
- AddSpaces(s, (int)GetColumnWidth(h.DigestSize) - h.Name.Len() + 1);
+ _s.Empty();
+ ClosePercents_for_so();
+
+ FOR_VECTOR (i, hb.Hashers)
+ {
+ if (i != 0)
+ _s.Add_Space();
+ const CHasherState &h = hb.Hashers[i];
+ _s += h.Name;
+ AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len());
+ }
+
+ if (PrintSize)
+ {
+ _s.Add_Space();
+ const AString s2 = "Size";
+ AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len());
+ _s += s2;
+ }
+
+ if (PrintName)
+ {
+ AddSpacesBeforeName();
+ _s += "Name";
+ }
+
+ *_so << _s << endl;
+ PrintSeparatorLine(hb.Hashers);
}
- UString s2 = L"Size";
- AddSpaces(s, kSizeField_Len - s2.Len());
- s += s2;
- s += L" ";
- s += L"Name";
- m_PercentPrinter.PrintString(s);
- m_PercentPrinter.PrintNewLine();
- PrintSeparatorLine(hb.Hashers);
- return CheckBreak();
+
+ return CheckBreak2();
}
-HRESULT CHashCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)
+HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
{
- FailedCodes.Add(systemError);
- FailedFiles.Add(name);
- // if (systemError == ERROR_SHARING_VIOLATION)
- {
- m_PercentPrinter.PrintString(name);
- m_PercentPrinter.PrintString(": WARNING: ");
- m_PercentPrinter.PrintString(NWindows::NError::MyFormatMessage(systemError));
- return S_FALSE;
- }
- // return systemError;
+ return OpenFileError_Base(path, systemError);
}
HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */)
{
- m_FileName = name;
- return CheckBreak();
+ _fileName = name;
+
+ if (NeedPercents())
+ {
+ if (PrintNameInPercents)
+ {
+ _percent.FileName.Empty();
+ if (name)
+ _percent.FileName = name;
+ }
+ _percent.Print();
+ }
+ return CheckBreak2();
}
void CHashCallbackConsole::PrintResultLine(UInt64 fileSize,
const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash)
{
+ ClosePercents_for_so();
+
+ _s.Empty();
+
FOR_VECTOR (i, hashers)
{
const CHasherState &h = hashers[i];
-
char s[k_HashCalc_DigestSize_Max * 2 + 64];
s[0] = 0;
if (showHash)
AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
- SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s) + 1);
- m_PercentPrinter.PrintString(s);
+ SetSpacesAndNul(s + strlen(s), (int)GetColumnWidth(h.DigestSize) - (int)strlen(s));
+ if (i != 0)
+ _s.Add_Space();
+ _s += s;
}
- char s[64];
- s[0] = 0;
- char *p = s;
- if (showHash && fileSize != 0)
+
+ if (PrintSize)
{
- p = s + 32;
- ConvertUInt64ToString(fileSize, p);
- int numSpaces = kSizeField_Len - (int)strlen(p);
- if (numSpaces > 0)
+ _s.Add_Space();
+
+ char s[kSizeField_Len + 32];
+ char *p = s;
+
+ if (showHash)
{
- p -= numSpaces;
- SetSpaces(p, numSpaces);
+ p = s + kSizeField_Len;
+ ConvertUInt64ToString(fileSize, p);
+ int numSpaces = kSizeField_Len - (int)strlen(p);
+ if (numSpaces > 0)
+ {
+ p -= (unsigned)numSpaces;
+ for (unsigned i = 0; i < (unsigned)numSpaces; i++)
+ p[i] = ' ';
+ }
}
+ else
+ SetSpacesAndNul(s, kSizeField_Len);
+
+ _s += p;
}
- else
- SetSpacesAndNul(s, kSizeField_Len - (int)strlen(s));
- unsigned len = (unsigned)strlen(p);
- p[len] = ' ';
- p[len + 1] = ' ';
- p[len + 2] = 0;
- m_PercentPrinter.PrintString(p);
+
+ if (PrintName)
+ AddSpacesBeforeName();
+
+ *_so << _s;
}
HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash)
{
- PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash);
- if (m_FileName.IsEmpty())
- m_PercentPrinter.PrintString(kEmptyFileAlias);
- else
- m_PercentPrinter.PrintString(m_FileName);
- m_PercentPrinter.PrintNewLine();
- return S_OK;
+ if (_so)
+ {
+ PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash);
+ if (PrintName)
+ {
+ if (_fileName.IsEmpty())
+ *_so << kEmptyFileAlias;
+ else
+ *_so << _fileName;
+ }
+ *_so << endl;
+ }
+
+ if (NeedPercents())
+ {
+ _percent.Files++;
+ _percent.Print();
+ }
+
+ return CheckBreak2();
}
static const char *k_DigestTitles[] =
{
- " :"
+ " : "
, " for data: "
, " for data and names: "
, " for streams and names: "
};
-static void PrintSum(CStdOutStream &p, const CHasherState &h, unsigned digestIndex)
+static void PrintSum(CStdOutStream &so, const CHasherState &h, unsigned digestIndex)
{
+ so << h.Name;
+
+ {
+ AString temp;
+ AddSpaces_if_Positive(temp, 6 - (int)h.Name.Len());
+ so << temp;
+ }
+
+ so << k_DigestTitles[digestIndex];
+
char s[k_HashCalc_DigestSize_Max * 2 + 64];
- UString name = h.Name;
- AddSpaces(name, 6 - (int)name.Len());
- p << name;
- p << k_DigestTitles[digestIndex];
s[0] = 0;
AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
- p << s;
- p << "\n";
+ so << s << endl;
}
-
-void PrintHashStat(CStdOutStream &p, const CHashBundle &hb)
+void PrintHashStat(CStdOutStream &so, const CHashBundle &hb)
{
FOR_VECTOR (i, hb.Hashers)
{
const CHasherState &h = hb.Hashers[i];
- p << "\n";
- PrintSum(p, h, k_HashCalc_Index_DataSum);
+ PrintSum(so, h, k_HashCalc_Index_DataSum);
if (hb.NumFiles != 1 || hb.NumDirs != 0)
- PrintSum(p, h, k_HashCalc_Index_NamesSum);
+ PrintSum(so, h, k_HashCalc_Index_NamesSum);
if (hb.NumAltStreams != 0)
- PrintSum(p, h, k_HashCalc_Index_StreamsSum);
+ PrintSum(so, h, k_HashCalc_Index_StreamsSum);
+ so << endl;
}
}
@@ -243,32 +329,39 @@ void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value)
s[0] = ':';
s[1] = ' ';
ConvertUInt64ToString(value, s + 2);
- m_PercentPrinter.PrintString(name);
- m_PercentPrinter.PrintString(s);
- m_PercentPrinter.PrintNewLine();
+ *_so << name << s << endl;
}
HRESULT CHashCallbackConsole::AfterLastFile(const CHashBundle &hb)
{
- PrintSeparatorLine(hb.Hashers);
-
- PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true);
- m_PercentPrinter.PrintNewLine();
- m_PercentPrinter.PrintNewLine();
+ ClosePercents2();
- if (hb.NumFiles != 1 || hb.NumDirs != 0)
- {
- if (hb.NumDirs != 0)
- PrintProperty("Folders", hb.NumDirs);
- PrintProperty("Files", hb.NumFiles);
- }
- PrintProperty("Size", hb.FilesSize);
- if (hb.NumAltStreams != 0)
+ if (PrintHeaders && _so)
{
- PrintProperty("AltStreams", hb.NumAltStreams);
- PrintProperty("AltStreams size", hb.AltStreamsSize);
+ PrintSeparatorLine(hb.Hashers);
+
+ PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true);
+
+ *_so << endl << endl;
+
+ if (hb.NumFiles != 1 || hb.NumDirs != 0)
+ {
+ if (hb.NumDirs != 0)
+ PrintProperty("Folders", hb.NumDirs);
+ PrintProperty("Files", hb.NumFiles);
+ }
+
+ PrintProperty("Size", hb.FilesSize);
+
+ if (hb.NumAltStreams != 0)
+ {
+ PrintProperty("Alternate streams", hb.NumAltStreams);
+ PrintProperty("Alternate streams size", hb.AltStreamsSize);
+ }
+
+ *_so << endl;
+ PrintHashStat(*_so, hb);
}
- PrintHashStat(*m_PercentPrinter.OutStream, hb);
- m_PercentPrinter.PrintNewLine();
+
return S_OK;
}
diff --git a/CPP/7zip/UI/Console/HashCon.h b/CPP/7zip/UI/Console/HashCon.h
index 7d3c72fd..5b30b69a 100644
--- a/CPP/7zip/UI/Console/HashCon.h
+++ b/CPP/7zip/UI/Console/HashCon.h
@@ -9,18 +9,40 @@
class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase
{
- UString m_FileName;
+ UString _fileName;
+ AString _s;
+
+ void AddSpacesBeforeName()
+ {
+ _s.Add_Space();
+ _s.Add_Space();
+ }
void PrintSeparatorLine(const CObjectVector<CHasherState> &hashers);
void PrintResultLine(UInt64 fileSize,
const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash);
void PrintProperty(const char *name, UInt64 value);
+
public:
+ bool PrintNameInPercents;
+
+ bool PrintHeaders;
+
+ bool PrintSize;
+ bool PrintName;
+
+ CHashCallbackConsole():
+ PrintNameInPercents(true),
+ PrintHeaders(false),
+ PrintSize(true),
+ PrintName(true)
+ {}
+
~CHashCallbackConsole() { }
INTERFACE_IHashCallbackUI(;)
};
-void PrintHashStat(CStdOutStream &stdStream, const CHashBundle &hb);
+void PrintHashStat(CStdOutStream &so, const CHashBundle &hb);
#endif
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
index f02296ea..64abb1fb 100644
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -23,9 +23,10 @@
using namespace NWindows;
using namespace NCOM;
+extern CStdOutStream *g_StdStream;
+extern CStdOutStream *g_ErrStream;
-
-static const char *kPropIdToName[] =
+static const char * const kPropIdToName[] =
{
"0"
, "1"
@@ -120,6 +121,8 @@ static const char *kPropIdToName[] =
, "Hard Link"
, "iNode"
, "Stream ID"
+ , "Read-only"
+ , "Out Name"
};
static const char kEmptyAttribChar = '.';
@@ -131,6 +134,8 @@ static const char *kString_Dirs = "folders";
static const char *kString_AltStreams = "alternate streams";
static const char *kString_Streams = "streams";
+static const char *kError = "ERROR: ";
+
static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s)
{
if (isDir)
@@ -163,8 +168,8 @@ struct CFieldInfo
AString NameA;
EAdjustment TitleAdjustment;
EAdjustment TextAdjustment;
- int PrefixSpacesWidth;
- int Width;
+ unsigned PrefixSpacesWidth;
+ unsigned Width;
};
struct CFieldInfoInit
@@ -173,8 +178,8 @@ struct CFieldInfoInit
const char *Name;
EAdjustment TitleAdjustment;
EAdjustment TextAdjustment;
- int PrefixSpacesWidth;
- int Width;
+ unsigned PrefixSpacesWidth;
+ unsigned Width;
};
static const CFieldInfoInit kStandardFieldTable[] =
@@ -186,71 +191,105 @@ static const CFieldInfoInit kStandardFieldTable[] =
{ kpidPath, "Name", kLeft, kLeft, 2, 24 }
};
-const int kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width
+const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width
static const char *g_Spaces =
" " ;
-static void PrintSpaces(int numSpaces)
+static void PrintSpaces(unsigned numSpaces)
{
if (numSpaces > 0 && numSpaces <= kNumSpacesMax)
g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces);
}
-static void PrintSpacesToString(char *dest, int numSpaces)
+static void PrintSpacesToString(char *dest, unsigned numSpaces)
{
- int i;
+ unsigned i;
for (i = 0; i < numSpaces; i++)
dest[i] = ' ';
dest[i] = 0;
}
-static void PrintString(EAdjustment adj, int width, const UString &textString)
+// extern int g_CodePage;
+
+static void PrintUString(EAdjustment adj, unsigned width, const UString &s, AString &temp)
{
- const int numSpaces = width - textString.Len();
- int numLeftSpaces = 0;
- switch (adj)
+ /*
+ // we don't need multibyte align.
+ int codePage = g_CodePage;
+ if (codePage == -1)
+ codePage = CP_OEMCP;
+ if (codePage == CP_UTF8)
+ ConvertUnicodeToUTF8(s, temp);
+ else
+ UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
+ */
+
+ unsigned numSpaces = 0;
+
+ if (width > s.Len())
{
- case kLeft: numLeftSpaces = 0; break;
- case kCenter: numLeftSpaces = numSpaces / 2; break;
- case kRight: numLeftSpaces = numSpaces; break;
+ numSpaces = width - s.Len();
+ unsigned numLeftSpaces = 0;
+ switch (adj)
+ {
+ case kLeft: numLeftSpaces = 0; break;
+ case kCenter: numLeftSpaces = numSpaces / 2; break;
+ case kRight: numLeftSpaces = numSpaces; break;
+ }
+ PrintSpaces(numLeftSpaces);
+ numSpaces -= numLeftSpaces;
}
- PrintSpaces(numLeftSpaces);
- g_StdOut << textString;
- PrintSpaces(numSpaces - numLeftSpaces);
+
+ g_StdOut.PrintUString(s, temp);
+ PrintSpaces(numSpaces);
}
-static void PrintString(EAdjustment adj, int width, const char *textString)
+static void PrintString(EAdjustment adj, unsigned width, const char *s)
{
- const int numSpaces = width - (int)strlen(textString);
- int numLeftSpaces = 0;
- switch (adj)
+ unsigned numSpaces = 0;
+ unsigned len = (unsigned)strlen(s);
+
+ if (width > len)
{
- case kLeft: numLeftSpaces = 0; break;
- case kCenter: numLeftSpaces = numSpaces / 2; break;
- case kRight: numLeftSpaces = numSpaces; break;
+ numSpaces = width - len;
+ unsigned numLeftSpaces = 0;
+ switch (adj)
+ {
+ case kLeft: numLeftSpaces = 0; break;
+ case kCenter: numLeftSpaces = numSpaces / 2; break;
+ case kRight: numLeftSpaces = numSpaces; break;
+ }
+ PrintSpaces(numLeftSpaces);
+ numSpaces -= numLeftSpaces;
}
- PrintSpaces(numLeftSpaces);
- g_StdOut << textString;
- PrintSpaces(numSpaces - numLeftSpaces);
+
+ g_StdOut << s;
+ PrintSpaces(numSpaces);
}
-static void PrintStringToString(char *dest, EAdjustment adj, int width, const char *textString)
+static void PrintStringToString(char *dest, EAdjustment adj, unsigned width, const char *textString)
{
- int len = (int)strlen(textString);
- const int numSpaces = width - len;
- int numLeftSpaces = 0;
- switch (adj)
+ unsigned numSpaces = 0;
+ unsigned len = (unsigned)strlen(textString);
+
+ if (width > len)
{
- case kLeft: numLeftSpaces = 0; break;
- case kCenter: numLeftSpaces = numSpaces / 2; break;
- case kRight: numLeftSpaces = numSpaces; break;
- }
- PrintSpacesToString(dest, numLeftSpaces);
- if (numLeftSpaces > 0)
+ numSpaces = width - len;
+ unsigned numLeftSpaces = 0;
+ switch (adj)
+ {
+ case kLeft: numLeftSpaces = 0; break;
+ case kCenter: numLeftSpaces = numSpaces / 2; break;
+ case kRight: numLeftSpaces = numSpaces; break;
+ }
+ PrintSpacesToString(dest, numLeftSpaces);
dest += numLeftSpaces;
+ numSpaces -= numLeftSpaces;
+ }
+
memcpy(dest, textString, len);
dest += len;
- PrintSpacesToString(dest, numSpaces - numLeftSpaces);
+ PrintSpacesToString(dest, numSpaces);
}
struct CListUInt64Def
@@ -287,12 +326,12 @@ struct CListStat
UInt64 NumFiles;
CListStat(): NumFiles(0) {}
- void Update(const CListStat &stat)
+ void Update(const CListStat &st)
{
- Size.Add(stat.Size);
- PackSize.Add(stat.PackSize);
- MTime.Update(stat.MTime);
- NumFiles += stat.NumFiles;
+ Size.Add(st.Size);
+ PackSize.Add(st.PackSize);
+ MTime.Update(st.MTime);
+ NumFiles += st.NumFiles;
}
void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; }
};
@@ -305,11 +344,11 @@ struct CListStat2
CListStat2(): NumDirs(0) {}
- void Update(const CListStat2 &stat)
+ void Update(const CListStat2 &st)
{
- MainFiles.Update(stat.MainFiles);
- AltStreams.Update(stat.AltStreams);
- NumDirs += stat.NumDirs;
+ MainFiles.Update(st.MainFiles);
+ AltStreams.Update(st.AltStreams);
+ NumDirs += st.NumDirs;
}
const UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; }
CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; }
@@ -319,34 +358,34 @@ class CFieldPrinter
{
CObjectVector<CFieldInfo> _fields;
- void AddProp(BSTR name, PROPID propID, bool isRawProp);
+ void AddProp(const wchar_t *name, PROPID propID, bool isRawProp);
public:
const CArc *Arc;
bool TechMode;
UString FilePath;
AString TempAString;
UString TempWString;
- bool IsFolder;
+ bool IsDir;
AString LinesString;
void Clear() { _fields.Clear(); LinesString.Empty(); }
- void Init(const CFieldInfoInit *standardFieldTable, int numItems);
+ void Init(const CFieldInfoInit *standardFieldTable, unsigned numItems);
HRESULT AddMainProps(IInArchive *archive);
HRESULT AddRawProps(IArchiveGetRawProps *getRawProps);
void PrintTitle();
void PrintTitleLines();
- HRESULT PrintItemInfo(UInt32 index, const CListStat &stat);
- void PrintSum(const CListStat &stat, UInt64 numDirs, const char *str);
- void PrintSum(const CListStat2 &stat);
+ HRESULT PrintItemInfo(UInt32 index, const CListStat &st);
+ void PrintSum(const CListStat &st, UInt64 numDirs, const char *str);
+ void PrintSum(const CListStat2 &stat2);
};
-void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
+void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, unsigned numItems)
{
Clear();
- for (int i = 0; i < numItems; i++)
+ for (unsigned i = 0; i < numItems; i++)
{
CFieldInfo &f = _fields.AddNew();
const CFieldInfoInit &fii = standardFieldTable[i];
@@ -358,9 +397,9 @@ void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
f.PrefixSpacesWidth = fii.PrefixSpacesWidth;
f.Width = fii.Width;
- int k;
+ unsigned k;
for (k = 0; k < fii.PrefixSpacesWidth; k++)
- LinesString += ' ';
+ LinesString.Add_Space();
for (k = 0; k < fii.Width; k++)
LinesString += '-';
}
@@ -383,13 +422,13 @@ static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UStr
}
}
-void CFieldPrinter::AddProp(BSTR name, PROPID propID, bool isRawProp)
+void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp)
{
CFieldInfo f;
f.PropID = propID;
f.IsRawProp = isRawProp;
GetPropName(propID, name, f.NameA, f.NameU);
- f.NameU += L" = ";
+ f.NameU.AddAscii(" = ");
if (!f.NameA.IsEmpty())
f.NameA += " = ";
else
@@ -486,9 +525,9 @@ static void HexToString(char *dest, const Byte *data, UInt32 size)
#endif
-#define MY_ENDL '\n'
+#define MY_ENDL endl
-HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat)
+HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
{
char temp[128];
size_t tempPos = 0;
@@ -530,7 +569,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat)
continue;
}
- int width = f.Width;
+ const unsigned width = f.Width;
if (f.IsRawProp)
{
@@ -561,7 +600,7 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat)
if (ConvertNtReparseToString((const Byte *)data, dataSize, s))
{
needPrint = false;
- g_StdOut << s;
+ g_StdOut.PrintUString(s, TempAString);
}
}
@@ -593,15 +632,15 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat)
CPropVariant prop;
switch (f.PropID)
{
- case kpidSize: if (stat.Size.Def) prop = stat.Size.Val; break;
- case kpidPackSize: if (stat.PackSize.Def) prop = stat.PackSize.Val; break;
- case kpidMTime: if (stat.MTime.Def) prop = stat.MTime.Val; break;
+ case kpidSize: if (st.Size.Def) prop = st.Size.Val; break;
+ case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break;
+ case kpidMTime: if (st.MTime.Def) prop = st.MTime.Val; break;
default:
RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop));
}
if (f.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))
{
- GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsFolder, techMode, temp + tempPos);
+ GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsDir, techMode, temp + tempPos);
if (techMode)
g_StdOut << temp + tempPos;
else
@@ -626,24 +665,22 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat)
tempPos += len;
if (len < (unsigned)f.Width)
{
- len = (size_t)f.Width - len;
- PrintSpacesToString(temp + tempPos, (int)len);
+ len = f.Width - len;
+ PrintSpacesToString(temp + tempPos, (unsigned)len);
tempPos += len;
}
}
}
else if (prop.vt == VT_BSTR)
{
+ TempWString.SetFromBstr(prop.bstrVal);
if (techMode)
{
- int len = (int)wcslen(prop.bstrVal);
- MyStringCopy(TempWString.GetBuffer(len), prop.bstrVal);
// replace CR/LF here.
- TempWString.ReleaseBuffer(len);
g_StdOut.PrintUString(TempWString, TempAString);
}
else
- PrintString(f.TextAdjustment, width, prop.bstrVal);
+ PrintUString(f.TextAdjustment, width, TempWString, TempAString);
}
else
{
@@ -665,55 +702,48 @@ HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &stat)
return S_OK;
}
-static void PrintNumber(EAdjustment adj, int width, const CListUInt64Def &value)
+static void PrintNumber(EAdjustment adj, unsigned width, const CListUInt64Def &value)
{
- wchar_t s[32];
+ char s[32];
s[0] = 0;
if (value.Def)
ConvertUInt64ToString(value.Val, s);
PrintString(adj, width, s);
}
-static void PrintNumberAndString(AString &s, UInt64 value, const char *text)
-{
- char t[32];
- ConvertUInt64ToString(value, t);
- s += t;
- s += ' ';
- s += text;
-}
+void Print_UInt64_and_String(AString &s, UInt64 val, const char *name);
-void CFieldPrinter::PrintSum(const CListStat &stat, UInt64 numDirs, const char *str)
+void CFieldPrinter::PrintSum(const CListStat &st, UInt64 numDirs, const char *str)
{
FOR_VECTOR (i, _fields)
{
const CFieldInfo &f = _fields[i];
PrintSpaces(f.PrefixSpacesWidth);
if (f.PropID == kpidSize)
- PrintNumber(f.TextAdjustment, f.Width, stat.Size);
+ PrintNumber(f.TextAdjustment, f.Width, st.Size);
else if (f.PropID == kpidPackSize)
- PrintNumber(f.TextAdjustment, f.Width, stat.PackSize);
+ PrintNumber(f.TextAdjustment, f.Width, st.PackSize);
else if (f.PropID == kpidMTime)
{
char s[64];
s[0] = 0;
- if (stat.MTime.Def)
- PrintTime(s, &stat.MTime.Val);
+ if (st.MTime.Def)
+ PrintTime(s, &st.MTime.Val);
PrintString(f.TextAdjustment, f.Width, s);
}
else if (f.PropID == kpidPath)
{
AString s;
- PrintNumberAndString(s, stat.NumFiles, str);
+ Print_UInt64_and_String(s, st.NumFiles, str);
if (numDirs != 0)
{
s += ", ";
- PrintNumberAndString(s, numDirs, kString_Dirs);
+ Print_UInt64_and_String(s, numDirs, kString_Dirs);
}
PrintString(f.TextAdjustment, 0, s);
}
else
- PrintString(f.TextAdjustment, f.Width, L"");
+ PrintString(f.TextAdjustment, f.Width, "");
}
g_StdOut << endl;
}
@@ -724,9 +754,9 @@ void CFieldPrinter::PrintSum(const CListStat2 &stat2)
if (stat2.AltStreams.NumFiles != 0)
{
PrintSum(stat2.AltStreams, 0, kString_AltStreams);;
- CListStat stat = stat2.MainFiles;
- stat.Update(stat2.AltStreams);
- PrintSum(stat, 0, kString_Streams);
+ CListStat st = stat2.MainFiles;
+ st.Update(stat2.AltStreams);
+ PrintSum(st, 0, kString_Streams);
}
}
@@ -757,12 +787,12 @@ static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef
return S_OK;
}
-static void PrintPropNameAndNumber(const char *name, UInt64 val)
+static void PrintPropNameAndNumber(CStdOutStream &so, const char *name, UInt64 val)
{
- g_StdOut << name << ": " << val << endl;
+ so << name << ": " << val << endl;
}
-static void PrintPropName_and_Eq(PROPID propID)
+static void PrintPropName_and_Eq(CStdOutStream &so, PROPID propID)
{
const char *s;
char temp[16];
@@ -773,28 +803,28 @@ static void PrintPropName_and_Eq(PROPID propID)
ConvertUInt32ToString(propID, temp);
s = temp;
}
- g_StdOut << s << " = ";
+ so << s << " = ";
}
-static void PrintPropNameAndNumber(PROPID propID, UInt64 val)
+static void PrintPropNameAndNumber(CStdOutStream &so, PROPID propID, UInt64 val)
{
- PrintPropName_and_Eq(propID);
- g_StdOut << val << endl;
+ PrintPropName_and_Eq(so, propID);
+ so << val << endl;
}
-static void PrintPropNameAndNumber_Signed(PROPID propID, Int64 val)
+static void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int64 val)
{
- PrintPropName_and_Eq(propID);
- g_StdOut << val << endl;
+ PrintPropName_and_Eq(so, propID);
+ so << val << endl;
}
-static void PrintPropPair(const char *name, const wchar_t *val)
+static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val)
{
- g_StdOut << name << " = " << val << endl;
+ so << name << " = " << val << endl;
}
-static void PrintPropertyPair2(PROPID propID, const wchar_t *name, const CPropVariant &prop)
+static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop)
{
UString s;
ConvertPropertyToString(s, prop, propID);
@@ -804,23 +834,23 @@ static void PrintPropertyPair2(PROPID propID, const wchar_t *name, const CPropVa
UString nameU;
GetPropName(propID, name, nameA, nameU);
if (!nameA.IsEmpty())
- PrintPropPair(nameA, s);
+ PrintPropPair(so, nameA, s);
else
- g_StdOut << nameU << " = " << s << endl;
+ so << nameU << " = " << s << endl;
}
}
-static HRESULT PrintArcProp(IInArchive *archive, PROPID propID, const wchar_t *name)
+static HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propID, const wchar_t *name)
{
CPropVariant prop;
RINOK(archive->GetArchiveProperty(propID, &prop));
- PrintPropertyPair2(propID, name, prop);
+ PrintPropertyPair2(so, propID, name, prop);
return S_OK;
}
-static void PrintArcTypeError(const UString &type, bool isWarning)
+static void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning)
{
- g_StdOut << "Open " << (isWarning ? "Warning" : "Error")
+ so << "Open " << (isWarning ? "WARNING" : "ERROR")
<< ": Can not open the file as ["
<< type
<< "] archive"
@@ -829,25 +859,109 @@ static void PrintArcTypeError(const UString &type, bool isWarning)
int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name);
-AString GetOpenArcErrorMessage(UInt32 errorFlags);
+void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
-static void PrintErrorFlags(const char *s, UInt32 errorFlags)
+static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er)
{
- g_StdOut << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;
+ PrintErrorFlags(so, "ERRORS:", er.GetErrorFlags());
+ if (!er.ErrorMessage.IsEmpty())
+ PrintPropPair(so, "ERROR", er.ErrorMessage);
+
+ PrintErrorFlags(so, "WARNINGS:", er.GetWarningFlags());
+ if (!er.WarningMessage.IsEmpty())
+ PrintPropPair(so, "WARNING", er.WarningMessage);
}
-static void ErrorInfo_Print(const CArcErrorInfo &er)
+HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)
{
- if (er.AreThereErrors())
- PrintErrorFlags("Errors:", er.GetErrorFlags());
- if (!er.ErrorMessage.IsEmpty())
- PrintPropPair("Error", er.ErrorMessage);
- if (er.AreThereWarnings())
- PrintErrorFlags("Warnings:", er.GetWarningFlags());
- if (!er.WarningMessage.IsEmpty())
- PrintPropPair("Warning", er.WarningMessage);
+ FOR_VECTOR (r, arcLink.Arcs)
+ {
+ const CArc &arc = arcLink.Arcs[r];
+ const CArcErrorInfo &er = arc.ErrorInfo;
+
+ so << "--\n";
+ PrintPropPair(so, "Path", arc.Path);
+ if (er.ErrorFormatIndex >= 0)
+ {
+ if (er.ErrorFormatIndex == arc.FormatIndex)
+ so << "Warning: The archive is open with offset" << endl;
+ else
+ PrintArcTypeError(so, codecs->GetFormatNamePtr(er.ErrorFormatIndex), true);
+ }
+ PrintPropPair(so, "Type", codecs->GetFormatNamePtr(arc.FormatIndex));
+
+ ErrorInfo_Print(so, er);
+
+ Int64 offset = arc.GetGlobalOffset();
+ if (offset != 0)
+ PrintPropNameAndNumber_Signed(so, kpidOffset, offset);
+ IInArchive *archive = arc.Archive;
+ RINOK(PrintArcProp(so, archive, kpidPhySize, NULL));
+ if (er.TailSize != 0)
+ PrintPropNameAndNumber(so, kpidTailSize, er.TailSize);
+ UInt32 numProps;
+ RINOK(archive->GetNumberOfArchiveProperties(&numProps));
+
+ {
+ for (UInt32 j = 0; j < numProps; j++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ VARTYPE vt;
+ RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));
+ RINOK(PrintArcProp(so, archive, propID, name));
+ }
+ }
+
+ if (r != arcLink.Arcs.Size() - 1)
+ {
+ UInt32 numProps;
+ so << "----\n";
+ if (archive->GetNumberOfProperties(&numProps) == S_OK)
+ {
+ UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex;
+ for (UInt32 j = 0; j < numProps; j++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ VARTYPE vt;
+ RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));
+ CPropVariant prop;
+ RINOK(archive->GetProperty(mainIndex, propID, &prop));
+ PrintPropertyPair2(so, propID, name, prop);
+ }
+ }
+ }
+ }
+ return S_OK;
+}
+
+HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)
+{
+ #ifndef _NO_CRYPTO
+ if (arcLink.PasswordWasAsked)
+ so << "Can not open encrypted archive. Wrong password?";
+ else
+ #endif
+ {
+ if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
+ {
+ so << arcLink.NonOpen_ArcPath << endl;
+ PrintArcTypeError(so, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
+ }
+ else
+ so << "Can not open the file as archive";
+ }
+
+ so << endl;
+ so << endl;
+ ErrorInfo_Print(so, arcLink.NonOpen_ErrorInfo);
+
+ return S_OK;
}
+bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
+
HRESULT ListArchives(CCodecs *codecs,
const CObjectVector<COpenType> &types,
const CIntVector &excludedFormats,
@@ -865,7 +979,7 @@ HRESULT ListArchives(CCodecs *codecs,
UInt64 &numErrors,
UInt64 &numWarnings)
{
- bool AllFilesAreAllowed = wildcardCensor.AreAllAllowed();
+ bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
numErrors = 0;
numWarnings = 0;
@@ -874,7 +988,7 @@ HRESULT ListArchives(CCodecs *codecs,
if (!techMode)
fp.Init(kStandardFieldTable, ARRAY_SIZE(kStandardFieldTable));
- CListStat2 stat2;
+ CListStat2 stat2total;
CBoolArr skipArcs(arcPaths.Size());
unsigned arcIndex;
@@ -884,18 +998,34 @@ HRESULT ListArchives(CCodecs *codecs,
UInt64 numArcs = 0;
UInt64 totalArcSizes = 0;
+ HRESULT lastError = 0;
+
for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)
{
if (skipArcs[arcIndex])
continue;
- const UString &archiveName = arcPaths[arcIndex];
+ const UString &arcPath = arcPaths[arcIndex];
UInt64 arcPackSize = 0;
+
if (!stdInMode)
{
NFile::NFind::CFileInfo fi;
- if (!fi.Find(us2fs(archiveName)) || fi.IsDir())
+ if (!fi.Find(us2fs(arcPath)))
{
- g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;
+ DWORD errorCode = GetLastError();
+ if (errorCode == 0)
+ errorCode = ERROR_FILE_NOT_FOUND;
+ lastError = HRESULT_FROM_WIN32(lastError);;
+ g_StdOut.Flush();
+ *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) <<
+ endl << arcPath << endl << endl;
+ numErrors++;
+ continue;
+ }
+ if (fi.IsDir())
+ {
+ g_StdOut.Flush();
+ *g_ErrStream << endl << kError << arcPath << " is not a file" << endl << endl;
numErrors++;
continue;
}
@@ -906,7 +1036,7 @@ HRESULT ListArchives(CCodecs *codecs,
CArchiveLink arcLink;
COpenCallbackConsole openCallback;
- openCallback.OutStream = &g_StdOut;
+ openCallback.Init(&g_StdOut, g_ErrStream, NULL);
#ifndef _NO_CRYPTO
@@ -930,40 +1060,39 @@ HRESULT ListArchives(CCodecs *codecs,
options.excludedFormats = &excludedFormats;
options.stdInMode = stdInMode;
options.stream = NULL;
- options.filePath = archiveName;
- HRESULT result = arcLink.Open2(options, &openCallback);
+ options.filePath = arcPath;
+
+ if (enableHeaders)
+ {
+ g_StdOut << endl << kListing << arcPath << endl << endl;
+ }
+
+ HRESULT result = arcLink.Open3(options, &openCallback);
if (result != S_OK)
{
if (result == E_ABORT)
return result;
- g_StdOut << endl << "Error: " << archiveName << ": ";
+ g_StdOut.Flush();
+ *g_ErrStream << endl << kError << arcPath << " : ";
if (result == S_FALSE)
{
- #ifndef _NO_CRYPTO
- if (openCallback.Open_WasPasswordAsked())
- g_StdOut << "Can not open encrypted archive. Wrong password?";
- else
- #endif
- {
- if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
- {
- PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
- }
- else
- g_StdOut << "Can not open the file as archive";
- }
- g_StdOut << endl;
- ErrorInfo_Print(arcLink.NonOpen_ErrorInfo);
+ Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink);
}
- else if (result == E_OUTOFMEMORY)
- g_StdOut << "Can't allocate required memory";
else
- g_StdOut << NError::MyFormatMessage(result);
- g_StdOut << endl;
+ {
+ lastError = result;
+ *g_ErrStream << "opening : ";
+ if (result == E_OUTOFMEMORY)
+ *g_ErrStream << "Can't allocate required memory";
+ else
+ *g_ErrStream << NError::MyFormatMessage(result);
+ }
+ *g_ErrStream << endl;
numErrors++;
continue;
}
+
{
if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
numErrors++;
@@ -998,72 +1127,15 @@ HRESULT ListArchives(CCodecs *codecs,
{
int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);
if (index >= 0 && (unsigned)index > arcIndex)
- skipArcs[index] = true;
+ skipArcs[(unsigned)index] = true;
}
}
if (enableHeaders)
{
- g_StdOut << endl << kListing << archiveName << endl << endl;
+ RINOK(Print_OpenArchive_Props(g_StdOut, codecs, arcLink));
- FOR_VECTOR (r, arcLink.Arcs)
- {
- const CArc &arc = arcLink.Arcs[r];
- const CArcErrorInfo &er = arc.ErrorInfo;
-
- g_StdOut << "--\n";
- PrintPropPair("Path", arc.Path);
- if (er.ErrorFormatIndex >= 0)
- {
- if (er.ErrorFormatIndex == arc.FormatIndex)
- g_StdOut << "Warning: The archive is open with offset" << endl;
- else
- PrintArcTypeError(codecs->GetFormatNamePtr(er.ErrorFormatIndex), true);
- }
- PrintPropPair("Type", codecs->GetFormatNamePtr(arc.FormatIndex));
-
- ErrorInfo_Print(er);
-
- Int64 offset = arc.GetGlobalOffset();
- if (offset != 0)
- PrintPropNameAndNumber_Signed(kpidOffset, offset);
- IInArchive *archive = arc.Archive;
- RINOK(PrintArcProp(archive, kpidPhySize, NULL));
- if (er.TailSize != 0)
- PrintPropNameAndNumber(kpidTailSize, er.TailSize);
- UInt32 numProps;
- RINOK(archive->GetNumberOfArchiveProperties(&numProps));
- {
- for (UInt32 j = 0; j < numProps; j++)
- {
- CMyComBSTR name;
- PROPID propID;
- VARTYPE vt;
- RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));
- RINOK(PrintArcProp(archive, propID, name));
- }
- }
- if (r != arcLink.Arcs.Size() - 1)
- {
- UInt32 numProps;
- g_StdOut << "----\n";
- if (archive->GetNumberOfProperties(&numProps) == S_OK)
- {
- UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex;
- for (UInt32 j = 0; j < numProps; j++)
- {
- CMyComBSTR name;
- PROPID propID;
- VARTYPE vt;
- RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));
- CPropVariant prop;
- RINOK(archive->GetProperty(mainIndex, propID, &prop));
- PrintPropertyPair2(propID, name, prop);
- }
- }
- }
- }
g_StdOut << endl;
if (techMode)
g_StdOut << "----------\n";
@@ -1091,10 +1163,14 @@ HRESULT ListArchives(CCodecs *codecs,
}
}
- CListStat2 stat;
+ CListStat2 stat2;
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
+
+ CReadArcItem item;
+ UStringVector pathParts;
+
for (UInt32 i = 0; i < numItems; i++)
{
if (NConsoleClose::TestBreakSignal())
@@ -1122,12 +1198,25 @@ HRESULT ListArchives(CCodecs *codecs,
continue;
}
- RINOK(Archive_IsItem_Folder(archive, i, fp.IsFolder));
+ RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir));
- if (!AllFilesAreAllowed)
+ if (!allFilesAreAllowed)
{
- if (!wildcardCensor.CheckPath(isAltStream, fp.FilePath, !fp.IsFolder))
- continue;
+ if (isAltStream)
+ {
+ RINOK(arc.GetItem(i, item));
+ if (!CensorNode_CheckPath(wildcardCensor, item))
+ continue;
+ }
+ else
+ {
+ SplitPathToParts(fp.FilePath, pathParts);;
+ bool include;
+ if (!wildcardCensor.CheckPathVect(pathParts, !fp.IsDir, include))
+ continue;
+ if (!include)
+ continue;
+ }
}
CListStat st;
@@ -1136,33 +1225,35 @@ HRESULT ListArchives(CCodecs *codecs,
RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize));
RINOK(GetItemMTime(archive, i, st.MTime));
- if (fp.IsFolder)
- stat.NumDirs++;
+ if (fp.IsDir)
+ stat2.NumDirs++;
else
st.NumFiles = 1;
- stat.GetStat(isAltStream).Update(st);
+ stat2.GetStat(isAltStream).Update(st);
if (isAltStream && !showAltStreams)
continue;
RINOK(fp.PrintItemInfo(i, st));
}
- UInt64 numStreams = stat.GetNumStreams();
+ UInt64 numStreams = stat2.GetNumStreams();
if (!stdInMode
- && !stat.MainFiles.PackSize.Def
- && !stat.AltStreams.PackSize.Def)
+ && !stat2.MainFiles.PackSize.Def
+ && !stat2.AltStreams.PackSize.Def)
{
if (arcLink.VolumePaths.Size() != 0)
arcPackSize += arcLink.VolumesSize;
- stat.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize);
+ stat2.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize);
}
- stat.MainFiles.SetSizeDefIfNoFiles();
- stat.AltStreams.SetSizeDefIfNoFiles();
+
+ stat2.MainFiles.SetSizeDefIfNoFiles();
+ stat2.AltStreams.SetSizeDefIfNoFiles();
+
if (enableHeaders && !techMode)
{
fp.PrintTitleLines();
g_StdOut << endl;
- fp.PrintSum(stat);
+ fp.PrintSum(stat2);
}
if (enableHeaders)
@@ -1170,23 +1261,30 @@ HRESULT ListArchives(CCodecs *codecs,
if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
{
g_StdOut << "----------\n";
- PrintPropPair("Path", arcLink.NonOpen_ArcPath);
- PrintArcTypeError(codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
+ PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath);
+ PrintArcTypeError(g_StdOut, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
}
}
- stat2.Update(stat);
- fflush(stdout);
+
+ stat2total.Update(stat2);
+
+ g_StdOut.Flush();
}
+
if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1))
{
g_StdOut << endl;
fp.PrintTitleLines();
g_StdOut << endl;
- fp.PrintSum(stat2);
+ fp.PrintSum(stat2total);
g_StdOut << endl;
- PrintPropNameAndNumber("Archives", numArcs);
- PrintPropNameAndNumber("Volumes", numVolumes);
- PrintPropNameAndNumber("Total archives size", totalArcSizes);
+ PrintPropNameAndNumber(g_StdOut, "Archives", numArcs);
+ PrintPropNameAndNumber(g_StdOut, "Volumes", numVolumes);
+ PrintPropNameAndNumber(g_StdOut, "Total archives size", totalArcSizes);
}
+
+ if (numErrors == 1 && lastError != 0)
+ return lastError;
+
return S_OK;
}
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index 2f56fecb..83e6ef5b 100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -4,6 +4,8 @@
#include <Psapi.h>
+#include "../../../../C/CpuArch.h"
+
#if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES)
#include "../../../../C/Alloc.h"
#endif
@@ -15,25 +17,26 @@
#include "../../../Common/MyException.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
+#include "../../../Common/UTFConvert.h"
#include "../../../Windows/ErrorMsg.h"
+
#ifdef _WIN32
#include "../../../Windows/MemoryLock.h"
#endif
-#ifndef _7ZIP_ST
-#include "../../../Windows/Synchronization.h"
-#endif
-
#include "../../../Windows/TimeUtils.h"
#include "../Common/ArchiveCommandLine.h"
#include "../Common/ExitCode.h"
#include "../Common/Extract.h"
+
#ifdef EXTERNAL_CODECS
#include "../Common/LoadCodecs.h"
#endif
+#include "../../Common/RegisterCodec.h"
+
#include "BenchCon.h"
#include "ConsoleClose.h"
#include "ExtractCallbackConsole.h"
@@ -56,7 +59,15 @@ using namespace NCommandLineParser;
#ifdef _WIN32
HINSTANCE g_hInstance = 0;
#endif
+
extern CStdOutStream *g_StdStream;
+extern CStdOutStream *g_ErrStream;
+
+extern unsigned g_NumCodecs;
+extern const CCodecInfo *g_Codecs[];
+
+extern unsigned g_NumHashers;
+extern const CHasherInfo *g_Hashers[];
static const char *kCopyrightString = "\n7-Zip"
#ifndef EXTERNAL_CODECS
@@ -67,14 +78,16 @@ static const char *kCopyrightString = "\n7-Zip"
#endif
#endif
-#ifdef _WIN64
+#ifdef MY_CPU_64BIT
" [64]"
+#elif defined MY_CPU_32BIT
+" [32]"
#endif
-" " MY_VERSION_COPYRIGHT_DATE "\n";
+" " MY_VERSION_COPYRIGHT_DATE "\n\n";
static const char *kHelpString =
- "\nUsage: 7z"
+ "Usage: 7z"
#ifndef EXTERNAL_CODECS
#ifdef PROG_VARIANT_R
"r"
@@ -91,6 +104,7 @@ static const char *kHelpString =
" d : Delete files from archive\n"
" e : Extract files from archive (without using directory names)\n"
" h : Calculate hash values for files\n"
+ " i : Show information about supported formats\n"
" l : List contents of archive\n"
// " l[a|t][f] : List contents of archive\n"
// " a - with Additional fields\n"
@@ -113,6 +127,7 @@ static const char *kHelpString =
#endif
" -r[-|0] : Recurse subdirectories\n"
" -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"
+ " -sdel : Delete files after compression\n"
" -sfx[{name}] : Create SFX archive\n"
" -si[{name}] : read data from stdin\n"
" -slt : show technical information for l (List) command\n"
@@ -137,9 +152,10 @@ static const char *kUnsupportedArcTypeMessage = "Unsupported archive type";
static CFSTR kDefaultSfxModule = FTEXT("7zCon.sfx");
-static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)
+static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code)
{
- s << endl << "Error: " << message << endl;
+ if (g_ErrStream)
+ *g_ErrStream << endl << "ERROR: " << message << endl;
throw code;
}
@@ -155,48 +171,47 @@ static void GetArguments(int numArgs, const char *args[], UStringVector &parts)
}
#endif
-static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp)
+static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp)
{
- s << kCopyrightString;
- // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n";
+ if (!so)
+ return;
+ *so << kCopyrightString;
+ // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl;
if (needHelp)
- s << kHelpString;
+ *so << kHelpString;
}
-#ifdef EXTERNAL_CODECS
-static void PrintString(CStdOutStream &stdStream, const AString &s, int size)
+static void PrintStringRight(CStdOutStream &so, const AString &s, unsigned size)
{
- int len = s.Len();
- for (int i = len; i < size; i++)
- stdStream << ' ';
- stdStream << s;
+ unsigned len = s.Len();
+ for (unsigned i = len; i < size; i++)
+ so << ' ';
+ so << s;
}
-static void PrintUInt32(CStdOutStream &stdStream, UInt32 val, int size)
+static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size)
{
char s[16];
ConvertUInt32ToString(val, s);
- PrintString(stdStream, s, size);
+ PrintStringRight(so, s, size);
}
-static void PrintLibIndex(CStdOutStream &stdStream, int libIndex)
+static void PrintLibIndex(CStdOutStream &so, int libIndex)
{
if (libIndex >= 0)
- PrintUInt32(stdStream, libIndex, 2);
+ PrintUInt32(so, libIndex, 2);
else
- stdStream << " ";
- stdStream << ' ';
+ so << " ";
+ so << ' ';
}
-#endif
-
-static void PrintString(CStdOutStream &stdStream, const UString &s, int size)
+static void PrintString(CStdOutStream &so, const UString &s, unsigned size)
{
- int len = s.Len();
- stdStream << s;
- for (int i = len; i < size; i++)
- stdStream << ' ';
+ unsigned len = s.Len();
+ so << s;
+ for (unsigned i = len; i < size; i++)
+ so << ' ';
}
static inline char GetHex(unsigned val)
@@ -204,82 +219,78 @@ static inline char GetHex(unsigned val)
return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10)));
}
+static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
+{
+ FOR_VECTOR(i, pc.Paths)
+ {
+ so << pc.Paths[i] << " : ";
+ so << NError::MyFormatMessage(pc.Codes[i]) << endl;
+ }
+ so << "----------------" << endl;
+}
+
static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
- const CErrorInfo &errorInfo, CStdOutStream &stdStream)
+ const CUpdateErrorInfo &errorInfo, CStdOutStream &so, bool showHeaders)
{
int exitCode = NExitCode::kSuccess;
- if (callback.CantFindFiles.Size() > 0)
+ if (callback.ScanErrors.Paths.Size() != 0)
{
- stdStream << endl;
- stdStream << "WARNINGS for files:" << endl << endl;
- unsigned numErrors = callback.CantFindFiles.Size();
- for (unsigned i = 0; i < numErrors; i++)
- {
- stdStream << callback.CantFindFiles[i] << " : ";
- stdStream << NError::MyFormatMessage(callback.CantFindCodes[i]) << endl;
- }
- stdStream << "----------------" << endl;
- stdStream << "WARNING: Cannot find " << numErrors << " file";
- if (numErrors > 1)
- stdStream << "s";
- stdStream << endl;
+ so << endl;
+ so << "Scan WARNINGS for files and folders:" << endl << endl;
+ PrintWarningsPaths(callback.ScanErrors, so);
+ so << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
+ so << endl;
exitCode = NExitCode::kWarning;
}
- if (result != S_OK)
+ if (result != S_OK || errorInfo.ThereIsError())
{
UString message;
if (!errorInfo.Message.IsEmpty())
{
- message += errorInfo.Message;
- message += L"\n";
+ message.AddAscii(errorInfo.Message);
+ message.Add_LF();
}
- if (!errorInfo.FileName.IsEmpty())
{
- message += fs2us(errorInfo.FileName);
- message += L"\n";
- }
- if (!errorInfo.FileName2.IsEmpty())
- {
- message += fs2us(errorInfo.FileName2);
- message += L"\n";
+ FOR_VECTOR(i, errorInfo.FileNames)
+ {
+ message += fs2us(errorInfo.FileNames[i]);
+ message.Add_LF();
+ }
}
if (errorInfo.SystemError != 0)
{
message += NError::MyFormatMessage(errorInfo.SystemError);
- message += L"\n";
+ message.Add_LF();
}
if (!message.IsEmpty())
- stdStream << L"\nError:\n" << message;
+ so << L"\nError:\n" << message;
// we will work with (result) later
// throw CSystemException(result);
return NExitCode::kFatalError;
}
- unsigned numErrors = callback.FailedFiles.Size();
+ unsigned numErrors = callback.FailedFiles.Paths.Size();
if (numErrors == 0)
{
- if (callback.CantFindFiles.Size() == 0)
- stdStream << kEverythingIsOk << endl;
+ if (showHeaders)
+ if (callback.ScanErrors.Paths.Size() == 0)
+ so << kEverythingIsOk << endl;
}
else
{
- stdStream << endl;
- stdStream << "WARNINGS for files:" << endl << endl;
- for (unsigned i = 0; i < numErrors; i++)
- {
- stdStream << callback.FailedFiles[i] << " : ";
- stdStream << NError::MyFormatMessage(callback.FailedCodes[i]) << endl;
- }
- stdStream << "----------------" << endl;
- stdStream << "WARNING: Cannot open " << numErrors << " file";
+ so << endl;
+ so << "WARNINGS for files:" << endl << endl;
+ PrintWarningsPaths(callback.FailedFiles, so);
+ so << "WARNING: Cannot open " << numErrors << " file";
if (numErrors > 1)
- stdStream << "s";
- stdStream << endl;
+ so << 's';
+ so << endl;
exitCode = NExitCode::kWarning;
}
+
return exitCode;
}
@@ -413,6 +424,13 @@ static void PrintStat()
*g_StdStream << endl;
}
+static void PrintHexId(CStdOutStream &so, UInt64 id)
+{
+ char s[32];
+ ConvertUInt64ToHex(id, s);
+ PrintStringRight(so, s, 8);
+}
+
int Main2(
#ifndef _WIN32
int numArgs, const char *args[]
@@ -424,6 +442,7 @@ int Main2(
#endif
UStringVector commandStrings;
+
#ifdef _WIN32
NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
#else
@@ -432,7 +451,7 @@ int Main2(
if (commandStrings.Size() == 1)
{
- ShowCopyrightAndHelp(g_StdOut, true);
+ ShowCopyrightAndHelp(g_StdStream, true);
return 0;
}
@@ -444,15 +463,30 @@ int Main2(
parser.Parse1(commandStrings, options);
+
+ if (options.Number_for_Out != k_OutStream_stdout)
+ g_StdStream = (options.Number_for_Out == k_OutStream_stderr ? &g_StdErr : NULL);
+
+ if (options.Number_for_Errors != k_OutStream_stderr)
+ g_ErrStream = (options.Number_for_Errors == k_OutStream_stdout ? &g_StdOut : NULL);
+
+ CStdOutStream *percentsStream = NULL;
+ if (options.Number_for_Percents != k_OutStream_disabled)
+ percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;;
+
+ CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
+
+
if (options.HelpMode)
{
- ShowCopyrightAndHelp(g_StdOut, true);
+ ShowCopyrightAndHelp(g_StdStream, true);
return 0;
}
#if defined(_WIN32) && !defined(UNDER_CE)
NSecurity::EnablePrivilege_SymLink();
#endif
+
#ifdef _7ZIP_LARGE_PAGES
if (options.LargePages)
{
@@ -463,22 +497,38 @@ int Main2(
}
#endif
- CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut;
- g_StdStream = &stdStream;
-
if (options.EnableHeaders)
- ShowCopyrightAndHelp(stdStream, false);
+ ShowCopyrightAndHelp(g_StdStream, false);
parser.Parse2(options);
- CCodecs *codecs = new CCodecs;
- #ifdef EXTERNAL_CODECS
- CExternalCodecs __externalCodecs;
- __externalCodecs.GetCodecs = codecs;
- __externalCodecs.GetHashers = codecs;
- #else
- CMyComPtr<IUnknown> compressCodecsInfo = codecs;
- #endif
+ unsigned percentsNameLevel = 1;
+ if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out)
+ percentsNameLevel = 2;
+
+ unsigned consoleWidth = 80;
+
+ if (percentsStream)
+ {
+ #ifdef _WIN32
+
+ #if !defined(UNDER_CE)
+ CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
+ if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo))
+ consoleWidth = consoleInfo.dwSize.X;
+ #endif
+
+ #else
+
+ struct winsize w;
+ if (ioctl(0, TIOCGWINSZ, &w) == )
+ consoleWidth = w.ws_col;
+
+ #endif
+ }
+
+ CREATE_CODECS_OBJECT
+
codecs->CaseSensitiveChange = options.CaseSensitiveChange;
codecs->CaseSensitive = options.CaseSensitive;
ThrowException_if_Error(codecs->Load());
@@ -489,7 +539,18 @@ int Main2(
(isExtractGroupCommand
|| options.Command.CommandType == NCommandType::kList
|| options.Command.IsFromUpdateGroup()))
+ {
+ #ifdef EXTERNAL_CODECS
+ if (!codecs->MainDll_ErrorPath.IsEmpty())
+ {
+ UString s = L"Can't load module ";
+ s += fs2us(codecs->MainDll_ErrorPath);
+ throw s;
+ }
+ #endif
+
throw kNoFormats;
+ }
CObjectVector<COpenType> types;
if (!ParseOpenTypes(*codecs, options.ArcType, types))
@@ -511,16 +572,19 @@ int Main2(
if (isExtractGroupCommand
|| options.Command.CommandType == NCommandType::kHash
|| options.Command.CommandType == NCommandType::kBenchmark)
- ThrowException_if_Error(__externalCodecs.LoadCodecs());
+ ThrowException_if_Error(__externalCodecs.Load());
#endif
int retCode = NExitCode::kSuccess;
HRESULT hresultMain = S_OK;
- bool showStat = true;
+ // bool showStat = options.ShowTime;
+
+ /*
if (!options.EnableHeaders ||
options.TechMode)
showStat = false;
+ */
if (options.Command.CommandType == NCommandType::kInfo)
@@ -528,15 +592,15 @@ int Main2(
unsigned i;
#ifdef EXTERNAL_CODECS
- stdStream << endl << "Libs:" << endl;
+ so << endl << "Libs:" << endl;
for (i = 0; i < codecs->Libs.Size(); i++)
{
- PrintLibIndex(stdStream, i);
- stdStream << ' ' << codecs->Libs[i].Path << endl;
+ PrintLibIndex(so, i);
+ so << ' ' << codecs->Libs[i].Path << endl;
}
#endif
- stdStream << endl << "Formats:" << endl;
+ so << endl << "Formats:" << endl;
const char *kArcFlags = "KSNFMGOPBELH";
const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags);
@@ -544,26 +608,30 @@ int Main2(
for (i = 0; i < codecs->Formats.Size(); i++)
{
const CArcInfoEx &arc = codecs->Formats[i];
+
#ifdef EXTERNAL_CODECS
- PrintLibIndex(stdStream, arc.LibIndex);
+ PrintLibIndex(so, arc.LibIndex);
#else
- stdStream << " ";
+ so << " ";
#endif
- stdStream << (char)(arc.UpdateEnabled ? 'C' : ' ');
+
+ so << (char)(arc.UpdateEnabled ? 'C' : ' ');
+
for (unsigned b = 0; b < kNumArcFlags; b++)
{
- stdStream << (char)
+ so << (char)
((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' ');
}
- stdStream << ' ';
- PrintString(stdStream, arc.Name, 8);
- stdStream << ' ';
+ so << ' ';
+ PrintString(so, arc.Name, 8);
+ so << ' ';
UString s;
+
FOR_VECTOR (t, arc.Exts)
{
if (t != 0)
- s += L' ';
+ s.Add_Space();
const CArcExtInfo &ext = arc.Exts[t];
s += ext.Ext;
if (!ext.AddExt.IsEmpty())
@@ -573,68 +641,112 @@ int Main2(
s += L')';
}
}
- PrintString(stdStream, s, 13);
- stdStream << ' ';
+
+ PrintString(so, s, 13);
+ so << ' ';
+
if (arc.SignatureOffset != 0)
- stdStream << "offset=" << arc.SignatureOffset << ' ';
+ so << "offset=" << arc.SignatureOffset << ' ';
FOR_VECTOR(si, arc.Signatures)
{
if (si != 0)
- stdStream << " || ";
+ so << " || ";
const CByteBuffer &sig = arc.Signatures[si];
for (size_t j = 0; j < sig.Size(); j++)
{
if (j != 0)
- stdStream << ' ';
+ so << ' ';
Byte b = sig[j];
if (b > 0x20 && b < 0x80)
{
- stdStream << (char)b;
+ so << (char)b;
}
else
{
- stdStream << GetHex((b >> 4) & 0xF);
- stdStream << GetHex(b & 0xF);
+ so << GetHex((b >> 4) & 0xF);
+ so << GetHex(b & 0xF);
}
}
}
- stdStream << endl;
+ so << endl;
+ }
+
+ so << endl << "Codecs:" << endl; // << "Lib ID Name" << endl;
+
+ for (i = 0; i < g_NumCodecs; i++)
+ {
+ const CCodecInfo &cod = *g_Codecs[i];
+
+ PrintLibIndex(so, -1);
+
+ if (cod.NumStreams == 1)
+ so << ' ';
+ else
+ so << cod.NumStreams;
+
+ so << (char)(cod.CreateEncoder ? 'E' : ' ');
+ so << (char)(cod.CreateDecoder ? 'D' : ' ');
+
+ so << ' ';
+ PrintHexId(so, cod.Id);
+ so << ' ' << cod.Name << endl;
}
+
#ifdef EXTERNAL_CODECS
- stdStream << endl << "Codecs:" << endl << "Lib ID Name" << endl;
UInt32 numMethods;
- if (codecs->GetNumberOfMethods(&numMethods) == S_OK)
+ if (codecs->GetNumMethods(&numMethods) == S_OK)
for (UInt32 j = 0; j < numMethods; j++)
{
- PrintLibIndex(stdStream, codecs->GetCodecLibIndex(j));
- stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' ');
+ PrintLibIndex(so, codecs->GetCodec_LibIndex(j));
+
+ UInt32 numStreams = codecs->GetCodec_NumStreams(j);
+ if (numStreams == 1)
+ so << ' ';
+ else
+ so << numStreams;
+
+ so << (char)(codecs->GetCodec_EncoderIsAssigned(j) ? 'E' : ' ');
+ so << (char)(codecs->GetCodec_DecoderIsAssigned(j) ? 'D' : ' ');
+
+ so << ' ';
UInt64 id;
- stdStream << " ";
- HRESULT res = codecs->GetCodecId(j, id);
+ HRESULT res = codecs->GetCodec_Id(j, id);
if (res != S_OK)
id = (UInt64)(Int64)-1;
- char s[32];
- ConvertUInt64ToHex(id, s);
- PrintString(stdStream, s, 8);
- stdStream << " " << codecs->GetCodecName(j) << endl;
+ PrintHexId(so, id);
+ so << ' ' << codecs->GetCodec_Name(j) << endl;
+ }
+
+ #endif
+
+
+ so << endl << "Hashers:" << endl; // << " L Size ID Name" << endl;
+
+ for (i = 0; i < g_NumHashers; i++)
+ {
+ const CHasherInfo &codec = *g_Hashers[i];
+ PrintLibIndex(so, -1);
+ PrintUInt32(so, codec.DigestSize, 4);
+ so << ' ';
+ PrintHexId(so, codec.Id);
+ so << ' ' << codec.Name << endl;
}
+
+ #ifdef EXTERNAL_CODECS
- stdStream << endl << "Hashers:" << endl << " L Size ID Name" << endl;
numMethods = codecs->GetNumHashers();
for (UInt32 j = 0; j < numMethods; j++)
{
- PrintLibIndex(stdStream, codecs->GetHasherLibIndex(j));
- PrintUInt32(stdStream, codecs->GetHasherDigestSize(j), 4);
- stdStream << ' ';
- char s[32];
- ConvertUInt64ToHex(codecs->GetHasherId(j), s);
- PrintString(stdStream, s, 6);
- stdStream << " " << codecs->GetHasherName(j) << endl;
+ PrintLibIndex(so, codecs->GetHasherLibIndex(j));
+ PrintUInt32(so, codecs->GetHasherDigestSize(j), 4);
+ so << ' ';
+ PrintHexId(so, codecs->GetHasherId(j));
+ so << ' ' << codecs->GetHasherName(j) << endl;
}
#endif
@@ -642,41 +754,102 @@ int Main2(
}
else if (options.Command.CommandType == NCommandType::kBenchmark)
{
- hresultMain = BenchCon(EXTERNAL_CODECS_VARS
- options.Properties, options.NumIterations, (FILE *)stdStream);
+ hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
+ options.Properties, options.NumIterations, (FILE *)so);
if (hresultMain == S_FALSE)
{
- stdStream << "\nDecoding Error\n";
+ if (g_ErrStream)
+ *g_ErrStream << "\nDecoding ERROR\n";
retCode = NExitCode::kFatalError;
hresultMain = S_OK;
}
}
else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
{
+ UStringVector ArchivePathsSorted;
+ UStringVector ArchivePathsFullSorted;
+
+ if (options.StdInMode)
+ {
+ ArchivePathsSorted.Add(options.ArcName_for_StdInMode);
+ ArchivePathsFullSorted.Add(options.ArcName_for_StdInMode);
+ }
+ else
+ {
+ CExtractScanConsole scan;
+
+ scan.Init(options.EnableHeaders ? g_StdStream : NULL, g_ErrStream, percentsStream);
+ scan.SetWindowWidth(consoleWidth);
+
+ if (g_StdStream && options.EnableHeaders)
+ *g_StdStream << "Scanning the drive for archives:" << endl;
+
+ CDirItemsStat st;
+
+ scan.StartScanning();
+
+ hresultMain = EnumerateDirItemsAndSort(
+ options.arcCensor,
+ NWildcard::k_RelatPath,
+ UString(), // addPathPrefix
+ ArchivePathsSorted,
+ ArchivePathsFullSorted,
+ st,
+ &scan);
+
+ scan.CloseScanning();
+
+ if (hresultMain == S_OK)
+ {
+ if (options.EnableHeaders)
+ scan.PrintStat(st);
+ }
+ else
+ {
+ /*
+ if (res != E_ABORT)
+ {
+ throw CSystemException(res);
+ // errorInfo.Message = "Scanning error";
+ }
+ return res;
+ */
+ }
+ }
+
+ if (hresultMain == S_OK)
if (isExtractGroupCommand)
{
CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
- ecs->OutStream = &stdStream;
-
#ifndef _NO_CRYPTO
ecs->PasswordIsDefined = options.PasswordEnabled;
ecs->Password = options.Password;
#endif
- ecs->Init();
+ ecs->Init(g_StdStream, g_ErrStream, percentsStream);
+ ecs->MutiArcMode = (ArchivePathsSorted.Size() > 1);
+
+ ecs->LogLevel = options.LogLevel;
+ ecs->PercentsNameLevel = percentsNameLevel;
+
+ if (percentsStream)
+ ecs->SetWindowWidth(consoleWidth);
+ /*
COpenCallbackConsole openCallback;
- openCallback.OutStream = &stdStream;
+ openCallback.Init(g_StdStream, g_ErrStream);
#ifndef _NO_CRYPTO
openCallback.PasswordIsDefined = options.PasswordEnabled;
openCallback.Password = options.Password;
#endif
+ */
CExtractOptions eo;
(CExtractOptionsBase &)eo = options.ExtractOptions;
+
eo.StdInMode = options.StdInMode;
eo.StdOutMode = options.StdOutMode;
eo.YesToAll = options.YesToAll;
@@ -694,58 +867,63 @@ int Main2(
if (!options.HashMethods.IsEmpty())
{
hashCalc = &hb;
- ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods));
+ ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods));
hb.Init();
}
+
hresultMain = Extract(
codecs,
types,
excludedFormats,
- options.ArchivePathsSorted,
- options.ArchivePathsFullSorted,
+ ArchivePathsSorted,
+ ArchivePathsFullSorted,
options.Censor.Pairs.Front().Head,
- eo, &openCallback, ecs, hashCalc, errorMessage, stat);
+ eo, ecs, ecs, hashCalc, errorMessage, stat);
+
+ ecs->ClosePercents();
+
if (!errorMessage.IsEmpty())
{
- stdStream << endl << "Error: " << errorMessage;
+ if (g_ErrStream)
+ *g_ErrStream << endl << "ERROR:" << endl << errorMessage << endl;
if (hresultMain == S_OK)
hresultMain = E_FAIL;
}
- stdStream << endl;
+ so << endl;
if (ecs->NumTryArcs > 1)
{
- stdStream << "Archives: " << ecs->NumTryArcs << endl;
- stdStream << "OK archives: " << ecs->NumOkArcs << endl;
+ so << "Archives: " << ecs->NumTryArcs << endl;
+ so << "OK archives: " << ecs->NumOkArcs << endl;
}
bool isError = false;
if (ecs->NumCantOpenArcs != 0)
{
isError = true;
- stdStream << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
+ so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
}
if (ecs->NumArcsWithError != 0)
{
isError = true;
- stdStream << "Archives with Errors: " << ecs->NumArcsWithError << endl;
+ so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
}
if (ecs->NumArcsWithWarnings != 0)
- stdStream << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
+ so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
if (ecs->NumOpenArcWarnings != 0)
{
- stdStream << endl;
+ so << endl;
if (ecs->NumOpenArcWarnings != 0)
- stdStream << "Warnings: " << ecs->NumOpenArcWarnings << endl;
+ so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
}
if (ecs->NumOpenArcErrors != 0)
{
isError = true;
- stdStream << endl;
+ so << endl;
if (ecs->NumOpenArcErrors != 0)
- stdStream << "Open Errors: " << ecs->NumOpenArcErrors << endl;
+ so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
}
if (isError)
@@ -755,29 +933,31 @@ int Main2(
{
// if (ecs->NumArchives > 1)
{
- stdStream << endl;
+ so << endl;
if (ecs->NumFileErrors != 0)
- stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;
+ so << "Sub items Errors: " << ecs->NumFileErrors << endl;
}
}
else if (hresultMain == S_OK)
{
-
- if (stat.NumFolders != 0)
- stdStream << "Folders: " << stat.NumFolders << endl;
- if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
- stdStream << "Files: " << stat.NumFiles << endl;
- if (stat.NumAltStreams != 0)
- {
- stdStream << "Alternate Streams: " << stat.NumAltStreams << endl;
- stdStream << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
- }
-
- stdStream
- << "Size: " << stat.UnpackSize << endl
- << "Compressed: " << stat.PackSize << endl;
- if (hashCalc)
- PrintHashStat(stdStream, hb);
+ if (stat.NumFolders != 0)
+ so << "Folders: " << stat.NumFolders << endl;
+ if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
+ so << "Files: " << stat.NumFiles << endl;
+ if (stat.NumAltStreams != 0)
+ {
+ so << "Alternate Streams: " << stat.NumAltStreams << endl;
+ so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
+ }
+
+ so
+ << "Size: " << stat.UnpackSize << endl
+ << "Compressed: " << stat.PackSize << endl;
+ if (hashCalc)
+ {
+ so << endl;
+ PrintHashStat(so, hb);
+ }
}
}
else
@@ -792,8 +972,8 @@ int Main2(
types,
excludedFormats,
options.StdInMode,
- options.ArchivePathsSorted,
- options.ArchivePathsFullSorted,
+ ArchivePathsSorted,
+ ArchivePathsFullSorted,
options.ExtractOptions.NtOptions.AltStreams.Val,
options.AltStreams.Val, // we don't want to show AltStreams by default
options.Censor.Pairs.Front().Head,
@@ -806,9 +986,10 @@ int Main2(
&options.Properties,
numErrors, numWarnings);
- if (options.EnableHeaders)
- if (numWarnings > 0)
- g_StdOut << endl << "Warnings: " << numWarnings << endl;
+ if (options.EnableHeaders)
+ if (numWarnings > 0)
+ g_StdOut << endl << "Warnings: " << numWarnings << endl;
+
if (numErrors > 0)
{
if (options.EnableHeaders)
@@ -824,25 +1005,32 @@ int Main2(
uo.SfxModule = kDefaultSfxModule;
COpenCallbackConsole openCallback;
- openCallback.OutStream = &stdStream;
+ openCallback.Init(g_StdStream, g_ErrStream, percentsStream);
#ifndef _NO_CRYPTO
bool passwordIsDefined =
- options.PasswordEnabled && !options.Password.IsEmpty();
+ (options.PasswordEnabled && !options.Password.IsEmpty());
openCallback.PasswordIsDefined = passwordIsDefined;
openCallback.Password = options.Password;
#endif
CUpdateCallbackConsole callback;
- callback.EnablePercents = options.EnablePercents;
+ callback.LogLevel = options.LogLevel;
+ callback.PercentsNameLevel = percentsNameLevel;
+
+ if (percentsStream)
+ callback.SetWindowWidth(consoleWidth);
#ifndef _NO_CRYPTO
callback.PasswordIsDefined = passwordIsDefined;
- callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();
+ callback.AskPassword = (options.PasswordEnabled && options.Password.IsEmpty());
callback.Password = options.Password;
#endif
+
callback.StdOutMode = uo.StdOutMode;
- callback.Init(&stdStream);
+ callback.Init(
+ // NULL,
+ g_StdStream, g_ErrStream, percentsStream);
CUpdateErrorInfo errorInfo;
@@ -856,29 +1044,36 @@ int Main2(
options.Censor,
uo,
errorInfo, &openCallback, &callback, true);
- retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream);
+
+ callback.ClosePercents2();
+
+ retCode = WarningsCheck(hresultMain, callback, errorInfo, so,
+ // options.EnableHeaders
+ true);
}
else if (options.Command.CommandType == NCommandType::kHash)
{
const CHashOptions &uo = options.HashOptions;
CHashCallbackConsole callback;
- callback.EnablePercents = options.EnablePercents;
-
- callback.Init(&stdStream);
+ if (percentsStream)
+ callback.SetWindowWidth(consoleWidth);
+
+ callback.Init(g_StdStream, g_ErrStream, percentsStream);
+ callback.PrintHeaders = options.EnableHeaders;
- UString errorInfoString;
- hresultMain = HashCalc(EXTERNAL_CODECS_VARS
+ AString errorInfoString;
+ hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L
options.Censor, uo,
errorInfoString, &callback);
- CErrorInfo errorInfo;
+ CUpdateErrorInfo errorInfo;
errorInfo.Message = errorInfoString;
- retCode = WarningsCheck(hresultMain, callback, errorInfo, stdStream);
+ retCode = WarningsCheck(hresultMain, callback, errorInfo, so, options.EnableHeaders);
}
else
- ShowMessageAndThrowException(stdStream, kUserErrorMessage, NExitCode::kUserError);
+ ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
- if (showStat)
+ if (options.ShowTime && g_StdStream)
PrintStat();
ThrowException_if_Error(hresultMain);
diff --git a/CPP/7zip/UI/Console/MainAr.cpp b/CPP/7zip/UI/Console/MainAr.cpp
index 1cb01689..f3f977f5 100644
--- a/CPP/7zip/UI/Console/MainAr.cpp
+++ b/CPP/7zip/UI/Console/MainAr.cpp
@@ -15,7 +15,8 @@
using namespace NWindows;
-CStdOutStream *g_StdStream = 0;
+CStdOutStream *g_StdStream = NULL;
+CStdOutStream *g_ErrStream = NULL;
extern int Main2(
#ifndef _WIN32
@@ -23,14 +24,27 @@ extern int Main2(
#endif
);
-static const char *kException_CmdLine_Error_Message = "\n\nCommand Line Error:\n";
-static const char *kExceptionErrorMessage = "\n\nError:\n";
-static const char *kUserBreak = "\nBreak signaled\n";
-static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n";
-static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n";
+static const char *kException_CmdLine_Error_Message = "Command Line Error:";
+static const char *kExceptionErrorMessage = "ERROR:";
+static const char *kUserBreakMessage = "Break signaled";
+static const char *kMemoryExceptionMessage = "ERROR: Can't allocate required memory!";
+static const char *kUnknownExceptionMessage = "Unknown Error";
static const char *kInternalExceptionMessage = "\n\nInternal Error #";
-#define NT_CHECK_FAIL_ACTION (*g_StdStream) << "Unsupported Windows version"; return NExitCode::kFatalError;
+static void FlushStreams()
+{
+ if (g_StdStream)
+ g_StdStream->Flush();
+}
+
+static void PrintError(const char *message)
+{
+ FlushStreams();
+ if (g_ErrStream)
+ *g_ErrStream << "\n\n" << message << endl;
+}
+
+#define NT_CHECK_FAIL_ACTION *g_StdStream << "Unsupported Windows version"; return NExitCode::kFatalError;
int MY_CDECL main
(
@@ -39,12 +53,14 @@ int MY_CDECL main
#endif
)
{
+ g_ErrStream = &g_StdErr;
g_StdStream = &g_StdOut;
NT_CHECK
NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
int res = 0;
+
try
{
res = Main2(
@@ -55,71 +71,97 @@ int MY_CDECL main
}
catch(const CNewException &)
{
- (*g_StdStream) << kMemoryExceptionMessage;
+ PrintError(kMemoryExceptionMessage);
return (NExitCode::kMemoryError);
}
catch(const NConsoleClose::CCtrlBreakException &)
{
- (*g_StdStream) << endl << kUserBreak;
+ PrintError(kUserBreakMessage);
return (NExitCode::kUserBreak);
}
catch(const CArcCmdLineException &e)
{
- (*g_StdStream) << kException_CmdLine_Error_Message << e << endl;
+ PrintError(kException_CmdLine_Error_Message);
+ if (g_ErrStream)
+ *g_ErrStream << e << endl;
return (NExitCode::kUserError);
}
catch(const CSystemException &systemError)
{
if (systemError.ErrorCode == E_OUTOFMEMORY)
{
- (*g_StdStream) << kMemoryExceptionMessage;
+ PrintError(kMemoryExceptionMessage);
return (NExitCode::kMemoryError);
}
if (systemError.ErrorCode == E_ABORT)
{
- (*g_StdStream) << endl << kUserBreak;
+ PrintError(kUserBreakMessage);
return (NExitCode::kUserBreak);
}
- (*g_StdStream) << endl << endl << "System error:" << endl <<
- NError::MyFormatMessage(systemError.ErrorCode) << endl;
+ if (g_ErrStream)
+ {
+ PrintError("System ERROR:");
+ *g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl;
+ }
return (NExitCode::kFatalError);
}
catch(NExitCode::EEnum &exitCode)
{
- (*g_StdStream) << kInternalExceptionMessage << exitCode << endl;
+ FlushStreams();
+ if (g_ErrStream)
+ *g_ErrStream << kInternalExceptionMessage << exitCode << endl;
return (exitCode);
}
- /*
- catch(const NExitCode::CMultipleErrors &multipleErrors)
- {
- (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl;
- return (NExitCode::kFatalError);
- }
- */
catch(const UString &s)
{
- (*g_StdStream) << kExceptionErrorMessage << s << endl;
+ if (g_ErrStream)
+ {
+ PrintError(kExceptionErrorMessage);
+ *g_ErrStream << s << endl;
+ }
return (NExitCode::kFatalError);
}
catch(const AString &s)
{
- (*g_StdStream) << kExceptionErrorMessage << s << endl;
+ if (g_ErrStream)
+ {
+ PrintError(kExceptionErrorMessage);
+ *g_ErrStream << s << endl;
+ }
return (NExitCode::kFatalError);
}
catch(const char *s)
{
- (*g_StdStream) << kExceptionErrorMessage << s << endl;
+ if (g_ErrStream)
+ {
+ PrintError(kExceptionErrorMessage);
+ *g_ErrStream << s << endl;
+ }
return (NExitCode::kFatalError);
}
- catch(int t)
+ catch(const wchar_t *s)
{
- (*g_StdStream) << kInternalExceptionMessage << t << endl;
+ if (g_ErrStream)
+ {
+ PrintError(kExceptionErrorMessage);
+ *g_ErrStream << s << endl;
+ }
return (NExitCode::kFatalError);
}
+ catch(int t)
+ {
+ if (g_ErrStream)
+ {
+ FlushStreams();
+ *g_ErrStream << kInternalExceptionMessage << t << endl;
+ return (NExitCode::kFatalError);
+ }
+ }
catch(...)
{
- (*g_StdStream) << kUnknownExceptionMessage;
+ PrintError(kUnknownExceptionMessage);
return (NExitCode::kFatalError);
}
+
return res;
}
diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
index f64fd493..5b2377be 100644
--- a/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
@@ -7,37 +7,89 @@
#include "ConsoleClose.h"
#include "UserInputUtils.h"
+static HRESULT CheckBreak2()
+{
+ return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
+}
+
HRESULT COpenCallbackConsole::Open_CheckBreak()
{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
+ return CheckBreak2();
}
-HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *)
+HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)
{
- return Open_CheckBreak();
+ if (!MutiArcMode && NeedPercents())
+ {
+ if (files)
+ {
+ _totalFilesDefined = true;
+ // _totalFiles = *files;
+ _percent.Total = *files;
+ }
+ else
+ _totalFilesDefined = false;
+
+ if (bytes)
+ {
+ _totalBytesDefined = true;
+ // _totalBytes = *bytes;
+ if (!files)
+ _percent.Total = *bytes;
+ }
+ else
+ _totalBytesDefined = false;
+ }
+
+ return CheckBreak2();
}
-HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *)
+HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)
{
- return Open_CheckBreak();
+ if (!MutiArcMode && NeedPercents())
+ {
+ if (files)
+ {
+ _percent.Files = *files;
+ if (_totalFilesDefined)
+ _percent.Completed = *files;
+ }
+
+ if (bytes)
+ {
+ if (!_totalFilesDefined)
+ _percent.Completed = *bytes;
+ }
+ _percent.Print();
+ }
+
+ return CheckBreak2();
}
-
+
+HRESULT COpenCallbackConsole::Open_Finished()
+{
+ ClosePercents();
+ return S_OK;
+}
+
+
#ifndef _NO_CRYPTO
HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)
{
- PasswordWasAsked = true;
- RINOK(Open_CheckBreak());
+ *password = NULL;
+ RINOK(CheckBreak2());
+
if (!PasswordIsDefined)
{
- Password = GetPassword(OutStream);
+ ClosePercents();
+ Password = GetPassword(_so);
PasswordIsDefined = true;
}
return StringToBstr(Password, password);
}
+/*
HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
{
passwordIsDefined = PasswordIsDefined;
@@ -50,9 +102,10 @@ bool COpenCallbackConsole::Open_WasPasswordAsked()
return PasswordWasAsked;
}
-void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag()
+void COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag ()
{
PasswordWasAsked = false;
}
+*/
#endif
diff --git a/CPP/7zip/UI/Console/OpenCallbackConsole.h b/CPP/7zip/UI/Console/OpenCallbackConsole.h
index 5828af99..66d1fafa 100644
--- a/CPP/7zip/UI/Console/OpenCallbackConsole.h
+++ b/CPP/7zip/UI/Console/OpenCallbackConsole.h
@@ -7,18 +7,58 @@
#include "../Common/ArchiveOpenCallback.h"
+#include "PercentPrinter.h"
+
class COpenCallbackConsole: public IOpenCallbackUI
{
+protected:
+ CPercentPrinter _percent;
+
+ CStdOutStream *_so;
+ CStdOutStream *_se;
+
+ bool _totalFilesDefined;
+ bool _totalBytesDefined;
+ // UInt64 _totalFiles;
+ // UInt64 _totalBytes;
+
+ bool NeedPercents() const { return _percent._so != NULL; }
+
public:
- INTERFACE_IOpenCallbackUI(;)
+
+ bool MutiArcMode;
+
+ void ClosePercents()
+ {
+ if (NeedPercents())
+ _percent.ClosePrint(true);
+ }
+
+ COpenCallbackConsole():
+ _totalFilesDefined(false),
+ _totalBytesDefined(false),
+ MutiArcMode(false)
+
+ #ifndef _NO_CRYPTO
+ , PasswordIsDefined(false)
+ // , PasswordWasAsked(false)
+ #endif
+
+ {}
- CStdOutStream *OutStream;
+ void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
+ {
+ _so = outStream;
+ _se = errorStream;
+ _percent._so = percentStream;
+ }
+ INTERFACE_IOpenCallbackUI(;)
+
#ifndef _NO_CRYPTO
bool PasswordIsDefined;
- bool PasswordWasAsked;
+ // bool PasswordWasAsked;
UString Password;
- COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {}
#endif
};
diff --git a/CPP/7zip/UI/Console/PercentPrinter.cpp b/CPP/7zip/UI/Console/PercentPrinter.cpp
index f2889957..e3e8d599 100644
--- a/CPP/7zip/UI/Console/PercentPrinter.cpp
+++ b/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -2,101 +2,180 @@
#include "StdAfx.h"
-#include "../../../Common/Defs.h"
#include "../../../Common/IntToString.h"
#include "PercentPrinter.h"
-static const unsigned kPaddingSize = 2;
static const unsigned kPercentsSize = 4;
-static const unsigned kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;
-static void ClearPrev(char *p, unsigned num)
+CPercentPrinter::~CPercentPrinter()
{
- unsigned i;
- for (i = 0; i < num; i++) *p++ = '\b';
- for (i = 0; i < num; i++) *p++ = ' ';
- for (i = 0; i < num; i++) *p++ = '\b';
- *p = '\0';
-}
-
-void CPercentPrinter::ClosePrint()
-{
- if (m_NumExtraChars == 0)
- return;
- char s[kMaxExtraSize * 3 + 1];
- ClearPrev(s, m_NumExtraChars);
- (*OutStream) << s;
- m_NumExtraChars = 0;
+ ClosePrint(false);
}
-void CPercentPrinter::PrintString(const char *s)
+void CPercentPrinterState::ClearCurState()
{
- ClosePrint();
- (*OutStream) << s;
+ Completed = 0;
+ Total = ((UInt64)(Int64)-1);
+ Files = 0;
+ Command.Empty();
+ FileName.Empty();
}
-void CPercentPrinter::PrintString(const wchar_t *s)
+void CPercentPrinter::ClosePrint(bool needFlush)
{
- ClosePrint();
- (*OutStream) << s;
-}
+ unsigned num = _printedString.Len();
+ if (num != 0)
+ {
-void CPercentPrinter::PrintNewLine()
-{
- ClosePrint();
- (*OutStream) << "\n";
+ unsigned i;
+
+ /* '\r' in old MAC OS means "new line".
+ So we can't use '\r' in some systems */
+
+ #ifdef _WIN32
+ char *start = _temp.GetBuf(num + 2);
+ char *p = start;
+ *p++ = '\r';
+ for (i = 0; i < num; i++) *p++ = ' ';
+ *p++ = '\r';
+ #else
+ char *start = _temp.GetBuf(num * 3);
+ char *p = start;
+ for (i = 0; i < num; i++) *p++ = '\b';
+ for (i = 0; i < num; i++) *p++ = ' ';
+ for (i = 0; i < num; i++) *p++ = '\b';
+ #endif
+
+ *p = 0;
+ _temp.ReleaseBuf_SetLen((unsigned)(p - start));
+ *_so << _temp;
+ }
+ if (needFlush)
+ _so->Flush();
+ _printedString.Empty();
}
-void CPercentPrinter::RePrintRatio()
+void CPercentPrinter::GetPercents()
{
char s[32];
unsigned size;
{
char c = '%';
- UInt64 value = 0;
- if (m_Total == (UInt64)(Int64)-1)
+ UInt64 val = 0;
+ if (Total == (UInt64)(Int64)-1)
{
- value = m_CurValue >> 20;
+ val = Completed >> 20;
c = 'M';
}
- else if (m_Total != 0)
- value = m_CurValue * 100 / m_Total;
- ConvertUInt64ToString(value, s);
+ else if (Total != 0)
+ val = Completed * 100 / Total;
+ ConvertUInt64ToString(val, s);
size = (unsigned)strlen(s);
s[size++] = c;
- s[size] = '\0';
+ s[size] = 0;
}
- unsigned extraSize = kPaddingSize + MyMax(size, kPercentsSize);
- if (extraSize < m_NumExtraChars)
- extraSize = m_NumExtraChars;
-
- char fullString[kMaxExtraSize * 3];
- char *p = fullString;
- unsigned i;
- if (m_NumExtraChars == 0)
+ while (size < kPercentsSize)
{
- for (i = 0; i < extraSize; i++)
- *p++ = ' ';
- m_NumExtraChars = extraSize;
+ _s += ' ';
+ size++;
}
- for (i = 0; i < m_NumExtraChars; i++)
- *p++ = '\b';
- m_NumExtraChars = extraSize;
- for (; size < extraSize; size++)
- *p++ = ' ';
- MyStringCopy(p, s);
- (*OutStream) << fullString;
- OutStream->Flush();
- m_PrevValue = m_CurValue;
+ _s += s;
}
-void CPercentPrinter::PrintRatio()
+void CPercentPrinter::Print()
{
- if (m_CurValue < m_PrevValue + m_MinStepSize &&
- m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0)
+ DWORD tick = 0;
+ if (_tickStep != 0)
+ tick = GetTickCount();
+
+ bool onlyPercentsChanged = false;
+
+ if (!_printedString.IsEmpty())
+ {
+ if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep)
+ return;
+
+ CPercentPrinterState &st = *this;
+ if (_printedState.Command == st.Command
+ && _printedState.FileName == st.FileName
+ && _printedState.Files == st.Files)
+ {
+ if (_printedState.Total == st.Total
+ && _printedState.Completed == st.Completed)
+ return;
+ onlyPercentsChanged = true;
+ }
+ }
+
+ _s.Empty();
+
+ GetPercents();
+
+ if (onlyPercentsChanged && _s == _printedPercents)
return;
- RePrintRatio();
+
+ _printedPercents = _s;
+
+ if (Files != 0)
+ {
+ char s[32];
+ ConvertUInt64ToString(Files, s);
+ // unsigned size = (unsigned)strlen(s);
+ // for (; size < 3; size++) _s += ' ';
+ _s += ' ';
+ _s += s;
+ // _s += "f";
+ }
+
+
+ if (!Command.IsEmpty())
+ {
+ _s += ' ';
+ _s += Command;
+ }
+
+ if (!FileName.IsEmpty() && _s.Len() < MaxLen)
+ {
+ _s += ' ';
+
+ StdOut_Convert_UString_to_AString(FileName, _temp);
+ _temp.Replace('\n', ' ');
+ if (_s.Len() + _temp.Len() > MaxLen)
+ {
+ unsigned len = FileName.Len();
+ for (; len != 0;)
+ {
+ unsigned delta = len / 8;
+ if (delta == 0)
+ delta = 1;
+ len -= delta;
+ _tempU = FileName;
+ _tempU.Delete(len / 2, FileName.Len() - len);
+ _tempU.Insert(len / 2, L" . ");
+ StdOut_Convert_UString_to_AString(_tempU, _temp);
+ if (_s.Len() + _temp.Len() <= MaxLen)
+ break;
+ }
+ if (len == 0)
+ _temp.Empty();
+ }
+ _s += _temp;
+ }
+
+ if (_printedString != _s)
+ {
+ ClosePrint(false);
+ *_so << _s;
+ if (NeedFlush)
+ _so->Flush();
+ _printedString = _s;
+ }
+
+ _printedState = *this;
+
+ if (_tickStep != 0)
+ _prevTick = tick;
}
diff --git a/CPP/7zip/UI/Console/PercentPrinter.h b/CPP/7zip/UI/Console/PercentPrinter.h
index 509bab5f..95290b37 100644
--- a/CPP/7zip/UI/Console/PercentPrinter.h
+++ b/CPP/7zip/UI/Console/PercentPrinter.h
@@ -5,26 +5,58 @@
#include "../../../Common/StdOutStream.h"
-class CPercentPrinter
+struct CPercentPrinterState
{
- UInt64 m_MinStepSize;
- UInt64 m_PrevValue;
- UInt64 m_CurValue;
- UInt64 m_Total;
- unsigned m_NumExtraChars;
+ UInt64 Completed;
+ UInt64 Total;
+
+ UInt64 Files;
+
+ AString Command;
+ UString FileName;
+
+ void ClearCurState();
+
+ CPercentPrinterState():
+ Completed(0),
+ Total((UInt64)(Int64)-1),
+ Files(0)
+ {}
+};
+
+class CPercentPrinter: public CPercentPrinterState
+{
+ UInt32 _tickStep;
+ DWORD _prevTick;
+
+ AString _s;
+
+ AString _printedString;
+ AString _temp;
+ UString _tempU;
+
+ CPercentPrinterState _printedState;
+ AString _printedPercents;
+
+ void GetPercents();
+
public:
- CStdOutStream *OutStream;
-
- CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize),
- m_PrevValue(0), m_CurValue(0), m_Total((UInt64)(Int64)-1), m_NumExtraChars(0) {}
- void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; }
- void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; }
- void PrintString(const char *s);
- void PrintString(const wchar_t *s);
- void PrintNewLine();
- void ClosePrint();
- void RePrintRatio();
- void PrintRatio();
+ CStdOutStream *_so;
+
+ bool NeedFlush;
+ unsigned MaxLen;
+
+ CPercentPrinter(UInt32 tickStep = 200):
+ _tickStep(tickStep),
+ _prevTick(0),
+ NeedFlush(true),
+ MaxLen(80 - 1)
+ {}
+
+ ~CPercentPrinter();
+
+ void ClosePrint(bool needFlush);
+ void Print();
};
#endif
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
index 749021c4..f4f2d102 100644
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -2,7 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/IntToString.h"
+
#include "../../../Windows/ErrorMsg.h"
+
#ifndef _7ZIP_ST
#include "../../../Windows/Synchronization.h"
#endif
@@ -22,195 +25,590 @@ static NSynchronization::CCriticalSection g_CriticalSection;
static const wchar_t *kEmptyFileAlias = L"[Content]";
-static const char *kCreatingArchiveMessage = "Creating archive ";
-static const char *kUpdatingArchiveMessage = "Updating archive ";
-static const char *kScanningMessage = "Scanning";
+static const char *kOpenArchiveMessage = "Open archive: ";
+static const char *kCreatingArchiveMessage = "Creating archive: ";
+static const char *kUpdatingArchiveMessage = "Updating archive: ";
+static const char *kScanningMessage = "Scanning the drive:";
+static const char *kError = "ERROR: ";
+static const char *kWarning = "WARNING: ";
-HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType)
+static HRESULT CheckBreak2()
{
- (*OutStream) << endl;
- if (result != S_OK)
+ return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
+}
+
+HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
+HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
+
+void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
+
+void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);
+
+HRESULT CUpdateCallbackConsole::OpenResult(
+ const CCodecs *codecs, const CArchiveLink &arcLink,
+ const wchar_t *name, HRESULT result)
+{
+ ClosePercents2();
+
+ FOR_VECTOR (level, arcLink.Arcs)
{
- (*OutStream) << "Error: " << name;
- if (errorArcType)
- (*OutStream) << " : can not open the file as [" << errorArcType << "] archive";
- else
- (*OutStream) << " is not supported archive";
- (*OutStream) << endl;
+ const CArc &arc = arcLink.Arcs[level];
+ const CArcErrorInfo &er = arc.ErrorInfo;
+
+ UInt32 errorFlags = er.GetErrorFlags();
+
+ if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
+ {
+ if (_se)
+ {
+ *_se << endl;
+ if (level != 0)
+ *_se << arc.Path << endl;
+ }
+
+ if (errorFlags != 0)
+ {
+ if (_se)
+ PrintErrorFlags(*_se, "ERRORS:", errorFlags);
+ }
+
+ if (!er.ErrorMessage.IsEmpty())
+ {
+ if (_se)
+ *_se << "ERRORS:" << endl << er.ErrorMessage << endl;
+ }
+
+ if (_se)
+ {
+ *_se << endl;
+ _se->Flush();
+ }
+ }
+
+ UInt32 warningFlags = er.GetWarningFlags();
+
+ if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
+ {
+ if (_so)
+ {
+ *_so << endl;
+ if (level != 0)
+ *_so << arc.Path << endl;
+ }
+
+ if (warningFlags != 0)
+ {
+ if (_so)
+ PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
+ }
+
+ if (!er.WarningMessage.IsEmpty())
+ {
+ if (_so)
+ *_so << "WARNINGS:" << endl << er.WarningMessage << endl;
+ }
+
+ if (_so)
+ {
+ *_so << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
+ }
+
+
+ if (er.ErrorFormatIndex >= 0)
+ {
+ if (_so)
+ {
+ Print_ErrorFormatIndex_Warning(_so, codecs, arc);
+ if (NeedFlush)
+ _so->Flush();
+ }
+ }
}
+
+ if (result == S_OK)
+ {
+ if (_so)
+ {
+ RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
+ *_so << endl;
+ }
+ }
+ else
+ {
+ if (_so)
+ _so->Flush();
+ if (_se)
+ {
+ *_se << kError << name << endl;
+ HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
+ RINOK(res);
+ _se->Flush();
+ }
+ }
+
return S_OK;
}
HRESULT CUpdateCallbackConsole::StartScanning()
{
- (*OutStream) << kScanningMessage;
+ if (_so)
+ *_so << kScanningMessage << endl;
+ _percent.Command = "Scan ";
return S_OK;
}
-HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, UInt64 /* totalSize */, const wchar_t * /* path */, bool /* isDir */)
+HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
{
+ if (NeedPercents())
+ {
+ _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
+ _percent.Completed = st.GetTotalBytes();
+ _percent.FileName = fs2us(path);
+ _percent.Print();
+ }
+
return CheckBreak();
}
-HRESULT CCallbackConsoleBase::CanNotFindError_Base(const wchar_t *name, DWORD systemError)
+void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning)
{
- CantFindFiles.Add(name);
- CantFindCodes.Add(systemError);
- // m_PercentPrinter.ClosePrint();
- if (!m_WarningsMode)
+ ClosePercents2();
+
+ if (_se)
{
- (*OutStream) << endl << endl;
- m_PercentPrinter.PrintNewLine();
- m_WarningsMode = true;
+ if (_so)
+ _so->Flush();
+
+ *_se << endl << (isWarning ? kWarning : kError)
+ << NError::MyFormatMessage(systemError)
+ << endl << fs2us(path) << endl << endl;
+ _se->Flush();
}
- m_PercentPrinter.PrintString(name);
- m_PercentPrinter.PrintString(": WARNING: ");
- m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError));
- m_PercentPrinter.PrintNewLine();
+}
+
+
+HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError)
+{
+ MT_LOCK
+
+ ScanErrors.AddError(path, systemError);
+ CommonError(path, systemError, true);
+
return S_OK;
}
-HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)
+HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError)
+{
+ MT_LOCK
+ FailedFiles.AddError(path, systemError);
+ /*
+ if (systemError == ERROR_SHARING_VIOLATION)
+ {
+ */
+ CommonError(path, systemError, true);
+ return S_FALSE;
+ /*
+ }
+ return systemError;
+ */
+}
+
+HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError)
+{
+ MT_LOCK
+ CommonError(path, systemError, false);
+ return HRESULT_FROM_WIN32(systemError);
+}
+
+HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)
+{
+ return ScanError_Base(path, systemError);
+}
+
+
+static void PrintPropPair(AString &s, const char *name, UInt64 val)
{
- return CanNotFindError_Base(name, systemError);
+ char temp[32];
+ ConvertUInt64ToString(val, temp);
+ s += name;
+ s += ": ";
+ s += temp;
}
-HRESULT CUpdateCallbackConsole::FinishScanning()
+void PrintSize_bytes_Smart(AString &s, UInt64 val);
+void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
+
+HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
{
- (*OutStream) << endl << endl;
+ if (NeedPercents())
+ {
+ _percent.ClosePrint(true);
+ _percent.ClearCurState();
+ }
+
+ if (_so)
+ {
+ AString s;
+ Print_DirItemsStat(s, st);
+ *_so << s << endl << endl;
+ }
+ return S_OK;
+}
+
+static const char *k_StdOut_ArcName = "StdOut";
+
+HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)
+{
+ if (_so)
+ {
+ *_so << kOpenArchiveMessage;
+ if (name)
+ *_so << name;
+ else
+ *_so << k_StdOut_ArcName;
+ *_so << endl;
+ }
return S_OK;
}
HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
{
- if(updating)
- (*OutStream) << kUpdatingArchiveMessage;
- else
- (*OutStream) << kCreatingArchiveMessage;
- if (name != 0)
- (*OutStream) << name;
- else
- (*OutStream) << "StdOut";
- (*OutStream) << endl << endl;
+ if (_so)
+ {
+ *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
+ if (name != 0)
+ *_so << name;
+ else
+ *_so << k_StdOut_ArcName;
+ *_so << endl << endl;
+ }
return S_OK;
}
-HRESULT CUpdateCallbackConsole::FinishArchive()
+HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)
{
- (*OutStream) << endl;
+ ClosePercents2();
+
+ if (_so)
+ {
+ AString s;
+ // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files);
+ PrintPropPair(s, "Files read from disk", _percent.Files);
+ s.Add_LF();
+ s += "Archive size: ";
+ PrintSize_bytes_Smart(s, st.OutArcFileSize);
+ s.Add_LF();
+ *_so << endl;
+ *_so << s;
+ // *_so << endl;
+ }
+
return S_OK;
}
-HRESULT CUpdateCallbackConsole::CheckBreak()
+HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
+ if (_so)
+ {
+ *_so << "Write SFX: ";
+ *_so << name;
+ AString s = " : ";
+ PrintSize_bytes_Smart(s, size);
+ *_so << s << endl;
+ }
return S_OK;
}
-HRESULT CUpdateCallbackConsole::Finilize()
+
+HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
{
- MT_LOCK
- if (m_NeedBeClosed)
+ if (LogLevel > 0 && _so)
{
- if (EnablePercents)
+ ClosePercents_for_so();
+
+ if (!DeleteMessageWasShown)
+ {
+ if (_so)
+ *_so << endl << ": Removing files after including to archive" << endl;
+ }
+
{
- m_PercentPrinter.ClosePrint();
+ {
+ _tempA = "Removing";
+ _tempA.Add_Space();
+ *_so << _tempA;
+ _tempU = fs2us(path);
+ _so->PrintUString(_tempU, _tempA);
+ *_so << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
}
- if (!StdOutMode && m_NeedNewLine)
+ }
+
+ if (!DeleteMessageWasShown)
+ {
+ if (NeedPercents())
{
- m_PercentPrinter.PrintNewLine();
- m_NeedNewLine = false;
+ _percent.ClearCurState();
}
- m_NeedBeClosed = false;
+ DeleteMessageWasShown = true;
+ }
+ else
+ {
+ _percent.Files++;
}
+
+ if (NeedPercents())
+ {
+ // if (!FullLog)
+ {
+ _percent.Command = "Removing";
+ _percent.FileName = fs2us(path);
+ }
+ _percent.Print();
+ }
+
+ return S_OK;
+}
+
+
+HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
+{
+ ClosePercents2();
+ if (_so && DeleteMessageWasShown)
+ *_so << endl;
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::CheckBreak()
+{
+ return CheckBreak2();
+}
+
+/*
+HRESULT CUpdateCallbackConsole::Finalize()
+{
+ // MT_LOCK
return S_OK;
}
+*/
-HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */)
+HRESULT CUpdateCallbackConsole::SetNumItems(UInt64 numItems)
{
+ if (_so)
+ {
+ ClosePercents_for_so();
+ AString s;
+ PrintPropPair(s, "Items to compress", numItems);
+ *_so << s << endl << endl;
+ }
return S_OK;
}
HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
{
MT_LOCK
- if (EnablePercents)
- m_PercentPrinter.SetTotal(size);
+ if (NeedPercents())
+ {
+ _percent.Total = size;
+ _percent.Print();
+ }
return S_OK;
}
HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
MT_LOCK
- if (completeValue != NULL)
+ if (completeValue)
{
- if (EnablePercents)
+ if (NeedPercents())
{
- m_PercentPrinter.SetRatio(*completeValue);
- m_PercentPrinter.PrintRatio();
- m_NeedBeClosed = true;
+ _percent.Completed = *completeValue;
+ _percent.Print();
}
}
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
+ return CheckBreak2();
}
HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
+ return CheckBreak2();
}
-HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti)
+HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)
{
MT_LOCK
+
+ bool show2 = (showInLog && _so);
+
+ if (show2)
+ {
+ ClosePercents_for_so();
+
+ _tempA = command;
+ if (name)
+ _tempA.Add_Space();
+ *_so << _tempA;
+
+ _tempU.Empty();
+ if (name)
+ _tempU = name;
+ _so->PrintUString(_tempU, _tempA);
+ *_so << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
+
+ if (NeedPercents())
+ {
+ if (PercentsNameLevel >= 1)
+ {
+ _percent.FileName.Empty();
+ _percent.Command.Empty();
+ if (PercentsNameLevel > 1 || !show2)
+ {
+ _percent.Command = command;
+ if (name)
+ _percent.FileName = name;
+ }
+ }
+ _percent.Print();
+ }
+
+ return CheckBreak2();
+}
+
+HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)
+{
if (StdOutMode)
return S_OK;
- if(isAnti)
- m_PercentPrinter.PrintString("Anti item ");
- else
- m_PercentPrinter.PrintString("Compressing ");
- if (name[0] == 0)
+
+ if (!name || name[0] == 0)
name = kEmptyFileAlias;
- m_PercentPrinter.PrintString(name);
- if (EnablePercents)
- m_PercentPrinter.RePrintRatio();
- return S_OK;
+
+ unsigned requiredLevel = 1;
+
+ const char *s;
+ if (mode == NUpdateNotifyOp::kAdd ||
+ mode == NUpdateNotifyOp::kUpdate)
+ {
+ if (isAnti)
+ s = "Anti";
+ else if (mode == NUpdateNotifyOp::kAdd)
+ s = "+";
+ else
+ s = "U";
+ }
+ else
+ {
+ requiredLevel = 3;
+ if (mode == NUpdateNotifyOp::kAnalyze)
+ s = "A";
+ else
+ s = "Reading";
+ }
+
+ return PrintProgress(name, s, LogLevel >= requiredLevel);
+}
+
+HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
+{
+ return OpenFileError_Base(path, systemError);
+}
+
+HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
+{
+ return ReadingFileError_Base(path, systemError);
}
-HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)
+HRESULT CUpdateCallbackConsole::SetOperationResult(Int32)
{
MT_LOCK
- FailedCodes.Add(systemError);
- FailedFiles.Add(name);
- /*
- if (systemError == ERROR_SHARING_VIOLATION)
+ _percent.Files++;
+ return S_OK;
+}
+
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
+
+HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
+{
+ // if (StdOutMode) return S_OK;
+
+ if (opRes != NArchive::NExtract::NOperationResult::kOK)
{
- */
- m_PercentPrinter.ClosePrint();
- m_PercentPrinter.PrintNewLine();
- m_PercentPrinter.PrintString("WARNING: ");
- m_PercentPrinter.PrintString(NError::MyFormatMessage(systemError));
- return S_FALSE;
- /*
+ ClosePercents2();
+
+ if (_se)
+ {
+ if (_so)
+ _so->Flush();
+
+ AString s;
+ SetExtractErrorMessage(opRes, isEncrypted, s);
+ *_se << s << " : " << endl << name << endl << endl;
+ _se->Flush();
+ }
+ return S_OK;
}
- return systemError;
- */
+ return S_OK;
}
-HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 )
+
+HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)
+{
+ // if (StdOutMode) return S_OK;
+
+ char temp[16];
+ const char *s;
+
+ unsigned requiredLevel = 1;
+
+ switch (op)
+ {
+ case NUpdateNotifyOp::kAdd: s = "+"; break;
+ case NUpdateNotifyOp::kUpdate: s = "U"; break;
+ case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break;
+ case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;
+ case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break;
+ case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break;
+ case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break;
+ case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break;
+ default:
+ {
+ temp[0] = 'o';
+ temp[1] = 'p';
+ ConvertUInt64ToString(op, temp + 2);
+ s = temp;
+ }
+ }
+
+ return PrintProgress(name, s, LogLevel >= requiredLevel);
+}
+
+/*
+HRESULT CUpdateCallbackConsole::SetPassword(const UString &
+ #ifndef _NO_CRYPTO
+ password
+ #endif
+ )
{
- m_NeedBeClosed = true;
- m_NeedNewLine = true;
+ #ifndef _NO_CRYPTO
+ PasswordIsDefined = true;
+ Password = password;
+ #endif
return S_OK;
}
+*/
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
+ COM_TRY_BEGIN
+
*password = NULL;
#ifdef _NO_CRYPTO
@@ -224,7 +622,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined,
{
if (AskPassword)
{
- Password = GetPassword(OutStream);
+ Password = GetPassword(_so);
PasswordIsDefined = true;
}
}
@@ -232,10 +630,14 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined,
return StringToBstr(Password, password);
#endif
+
+ COM_TRY_END
}
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
{
+ COM_TRY_BEGIN
+
*password = NULL;
#ifdef _NO_CRYPTO
@@ -247,30 +649,26 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
if (!PasswordIsDefined)
{
{
- Password = GetPassword(OutStream);
+ Password = GetPassword(_so);
PasswordIsDefined = true;
}
}
return StringToBstr(Password, password);
#endif
+ COM_TRY_END
}
-/*
-HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name)
+HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
{
- // MT_LOCK
if (StdOutMode)
return S_OK;
- RINOK(Finilize());
- m_PercentPrinter.PrintString("Deleting ");
- if (name[0] == 0)
- name = kEmptyFileAlias;
- m_PercentPrinter.PrintString(name);
- if (EnablePercents)
- m_PercentPrinter.RePrintRatio();
- m_NeedBeClosed = true;
- m_NeedNewLine = true;
+
+ if (LogLevel > 7)
+ {
+ if (!name || name[0] == 0)
+ name = kEmptyFileAlias;
+ return PrintProgress(name, "D", true);
+ }
return S_OK;
}
-*/
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
index 77e0e178..ba8614eb 100644
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
@@ -9,44 +9,91 @@
#include "PercentPrinter.h"
+struct CErrorPathCodes
+{
+ FStringVector Paths;
+ CRecordVector<DWORD> Codes;
+
+ void AddError(const FString &path, DWORD systemError)
+ {
+ Paths.Add(path);
+ Codes.Add(systemError);
+ }
+ void Clear()
+ {
+ Paths.Clear();
+ Codes.Clear();
+ }
+};
+
class CCallbackConsoleBase
{
- bool m_WarningsMode;
protected:
- CPercentPrinter m_PercentPrinter;
+ CPercentPrinter _percent;
+
+ CStdOutStream *_so;
+ CStdOutStream *_se;
+
+ void CommonError(const FString &path, DWORD systemError, bool isWarning);
+
+ HRESULT ScanError_Base(const FString &path, DWORD systemError);
+ HRESULT OpenFileError_Base(const FString &name, DWORD systemError);
+ HRESULT ReadingFileError_Base(const FString &name, DWORD systemError);
- CStdOutStream *OutStream;
- HRESULT CanNotFindError_Base(const wchar_t *name, DWORD systemError);
public:
- bool EnablePercents;
+ bool NeedPercents() const { return _percent._so != NULL; };
+
bool StdOutMode;
+ bool NeedFlush;
+ unsigned PercentsNameLevel;
+ unsigned LogLevel;
+
+ AString _tempA;
+ UString _tempU;
+
CCallbackConsoleBase():
- m_PercentPrinter(1 << 16),
StdOutMode(false),
- EnablePercents(true),
- m_WarningsMode(false)
+ NeedFlush(false),
+ PercentsNameLevel(1),
+ LogLevel(0)
{}
- void Init(CStdOutStream *outStream)
+ void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
+
+ void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
{
FailedFiles.Clear();
- FailedCodes.Clear();
- OutStream = outStream;
- m_PercentPrinter.OutStream = outStream;
+
+ _so = outStream;
+ _se = errorStream;
+ _percent._so = percentStream;
}
- UStringVector FailedFiles;
- CRecordVector<HRESULT> FailedCodes;
+ void ClosePercents2()
+ {
+ if (NeedPercents())
+ _percent.ClosePrint(true);
+ }
+
+ void ClosePercents_for_so()
+ {
+ if (NeedPercents() && _so == _percent._so)
+ _percent.ClosePrint(false);
+ }
+
+
+ CErrorPathCodes FailedFiles;
+ CErrorPathCodes ScanErrors;
+
+ HRESULT PrintProgress(const wchar_t *name, const char *command, bool showInLog);
- UStringVector CantFindFiles;
- CRecordVector<HRESULT> CantFindCodes;
};
class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase
{
- bool m_NeedBeClosed;
- bool m_NeedNewLine;
+ // void PrintPropPair(const char *name, const wchar_t *val);
+
public:
#ifndef _NO_CRYPTO
bool PasswordIsDefined;
@@ -54,21 +101,23 @@ public:
bool AskPassword;
#endif
+ bool DeleteMessageWasShown;
+
CUpdateCallbackConsole()
+ : DeleteMessageWasShown(false)
#ifndef _NO_CRYPTO
- :
- PasswordIsDefined(false),
- AskPassword(false)
+ , PasswordIsDefined(false)
+ , AskPassword(false)
#endif
{}
+ /*
void Init(CStdOutStream *outStream)
{
- m_NeedBeClosed = false;
- m_NeedNewLine = false;
CCallbackConsoleBase::Init(outStream);
}
- ~CUpdateCallbackConsole() { Finilize(); }
+ */
+ // ~CUpdateCallbackConsole() { if (NeedPercents()) _percent.ClosePrint(); }
INTERFACE_IUpdateCallbackUI2(;)
};
diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
index a0d4af38..2974a5b9 100644
--- a/CPP/7zip/UI/Console/UserInputUtils.cpp
+++ b/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -14,7 +14,7 @@ static const char kNoAll = 's';
static const char kAutoRenameAll = 'u';
static const char kQuit = 'q';
-static const char *kFirstQuestionMessage = "?\n";
+static const char *kFirstQuestionMessage = "? ";
static const char *kHelpQuestionMessage =
"(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ";
@@ -22,11 +22,15 @@ static const char *kHelpQuestionMessage =
NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
{
- (*outStream) << kFirstQuestionMessage;
+ if (outStream)
+ *outStream << kFirstQuestionMessage;
for (;;)
{
- (*outStream) << kHelpQuestionMessage;
- outStream->Flush();
+ if (outStream)
+ {
+ *outStream << kHelpQuestionMessage;
+ outStream->Flush();
+ }
AString scannedString = g_StdIn.ScanStringUntilNewLine();
scannedString.Trim();
if (!scannedString.IsEmpty())
@@ -50,14 +54,18 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
UString GetPassword(CStdOutStream *outStream)
{
- (*outStream) << "\nEnter password"
+ if (outStream)
+ {
+ *outStream << "\nEnter password"
#ifdef MY_DISABLE_ECHO
" (will not be echoed)"
#endif
":";
- outStream->Flush();
+ outStream->Flush();
+ }
#ifdef MY_DISABLE_ECHO
+
HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
bool wasChanged = false;
DWORD mode = 0;
@@ -67,10 +75,16 @@ UString GetPassword(CStdOutStream *outStream)
UString res = g_StdIn.ScanUStringUntilNewLine();
if (wasChanged)
SetConsoleMode(console, mode);
- (*outStream) << "\n";
- outStream->Flush();
+ if (outStream)
+ {
+ *outStream << endl;
+ outStream->Flush();
+ }
return res;
+
#else
+
return g_StdIn.ScanUStringUntilNewLine();
+
#endif
}
diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile
index efabf91c..98ad91c2 100644
--- a/CPP/7zip/UI/Console/makefile
+++ b/CPP/7zip/UI/Console/makefile
@@ -7,8 +7,6 @@ CFLAGS = $(CFLAGS) \
CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE
!ENDIF
-CURRENT_OBJS = \
-
COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp
index d0fc1725..64a916b2 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.cpp
+++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp
@@ -115,7 +115,7 @@ STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT
return GetFileNames(dataObject, _fileNames);
}
-HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t **names, unsigned numFiles)
+HRESULT CZipContextMenu::InitContextMenu(const wchar_t * /* folder */, const wchar_t * const *names, unsigned numFiles)
{
_isMenuForFM = true;
_fileNames.Clear();
@@ -278,7 +278,7 @@ static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s, HBITMA
// ::SetMenuItemBitmaps(menu, pos, MF_BYPOSITION, bitmap, NULL);
}
-static const char *kArcExts[] =
+static const char * const kArcExts[] =
{
"7z"
, "bz2"
@@ -297,29 +297,28 @@ static bool IsItArcExt(const UString &ext2)
return false;
}
-static UString GetSubFolderNameForExtract(const UString &archiveName)
+static UString GetSubFolderNameForExtract(const UString &arcName)
{
- int dotPos = archiveName.ReverseFind(L'.');
+ int dotPos = arcName.ReverseFind_Dot();
if (dotPos < 0)
- {
- return GetCorrectFsPath(archiveName) + L"~";
- }
- const UString ext = archiveName.Ptr(dotPos + 1);
- UString res = archiveName.Left(dotPos);
+ return Get_Correct_FsFile_Name(arcName) + L'~';
+
+ const UString ext = arcName.Ptr(dotPos + 1);
+ UString res = arcName.Left(dotPos);
res.TrimRight();
- dotPos = res.ReverseFind(L'.');
+ dotPos = res.ReverseFind_Dot();
if (dotPos > 0)
{
const UString ext2 = res.Ptr(dotPos + 1);
- if (ext.IsEqualToNoCase(L"rar") &&
- (ext2.IsEqualToNoCase(L"part001") ||
- ext2.IsEqualToNoCase(L"part01") ||
- ext2.IsEqualToNoCase(L"part1")) ||
- IsItArcExt(ext2) && ext.IsEqualToNoCase(L"001"))
+ if (ext.IsEqualTo_Ascii_NoCase("001") && IsItArcExt(ext2)
+ || ext.IsEqualTo_Ascii_NoCase("rar") &&
+ ( ext2.IsEqualTo_Ascii_NoCase("part001")
+ || ext2.IsEqualTo_Ascii_NoCase("part01")
+ || ext2.IsEqualTo_Ascii_NoCase("part1")))
res.DeleteFrom(dotPos);
res.TrimRight();
}
- return GetCorrectFullFsPath(res);
+ return Get_Correct_FsFile_Name(res);
}
static void ReduceString(UString &s)
@@ -339,6 +338,11 @@ static UString GetQuotedReducedString(const UString &s)
return GetQuotedString(s2);
}
+static void MyFormatNew_ReducedName(UString &s, const UString &name)
+{
+ s = MyFormatNew(s, GetQuotedReducedString(name));
+}
+
static const char *kExtractExludeExtensions =
" 3gp"
" aac ans ape asc asm asp aspx avi awk"
@@ -368,7 +372,7 @@ static const char *kNoOpenAsExtensions =
" 7z arj bz2 cab chm cpio flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip ";
*/
-static const char *kOpenTypes[] =
+static const char * const kOpenTypes[] =
{
""
, "*"
@@ -383,11 +387,12 @@ static const char *kOpenTypes[] =
static bool FindExt(const char *p, const FString &name)
{
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
if (dotPos < 0 || dotPos == (int)name.Len() - 1)
return false;
AString s;
+
for (unsigned pos = dotPos + 1;; pos++)
{
wchar_t c = name[pos];
@@ -397,6 +402,7 @@ static bool FindExt(const char *p, const FString &name)
return false;
s += (char)MyCharLower_Ascii((char)c);
}
+
for (unsigned i = 0; p[i] != 0;)
{
unsigned j;
@@ -405,6 +411,7 @@ static bool FindExt(const char *p, const FString &name)
return true;
i = j + 1;
}
+
return false;
}
@@ -475,7 +482,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
if (_fileNames.Size() > 0)
{
const UString &fileName = _fileNames.Front();
- #ifdef _WIN32
+ #if defined(_WIN32) && !defined(UNDER_CE)
if (NName::IsDevicePath(us2fs(fileName)))
{
// CFileInfo::Find can be slow for device files. So we don't call it.
@@ -584,7 +591,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
commandMapItem.Folder = _dropPath;
else
commandMapItem.Folder = fs2us(folderPrefix);
- commandMapItem.Folder += GetSubFolderNameForExtract(fs2us(fi0.Name)) + UString(WCHAR_PATH_SEPARATOR);
+ commandMapItem.Folder += GetSubFolderNameForExtract(fs2us(fi0.Name));
+ commandMapItem.Folder.Add_PathSepar();
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap);
_commandMap.Add(commandMapItem);
}
@@ -608,17 +616,16 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CCommandMapItem commandMapItem;
UString s;
FillCommand(kExtractTo, s, commandMapItem);
- UString folder;
+ UString folder = L'*';
if (_fileNames.Size() == 1)
folder = GetSubFolderNameForExtract(fs2us(fi0.Name));
- else
- folder = L'*';
if (_dropMode)
commandMapItem.Folder = _dropPath;
else
commandMapItem.Folder = fs2us(folderPrefix);
commandMapItem.Folder += folder;
- s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR)));
+ folder.Add_PathSepar();
+ MyFormatNew_ReducedName(s, folder);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
_commandMap.Add(commandMapItem);
}
@@ -632,13 +639,13 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
}
}
- UString archiveName;
+ UString arcName;
if (_fileNames.Size() == 1)
- archiveName = CreateArchiveName(fi0, false);
+ arcName = CreateArchiveName(fi0, false);
else
- archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false);
- UString archiveName7z = archiveName + L".7z";
- UString archiveNameZip = archiveName + L".zip";
+ arcName = CreateArchiveName(fileName, _fileNames.Size() > 1, false);
+ UString arcName7z = arcName + L".7z";
+ UString arcNameZip = arcName + L".zip";
// Compress
if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0)
@@ -648,7 +655,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
commandMapItem.Folder = _dropPath;
else
commandMapItem.Folder = fs2us(folderPrefix);
- commandMapItem.ArcName = archiveName;
+ commandMapItem.ArcName = arcName;
FillCommand(kCompress, mainString, commandMapItem);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap);
_commandMap.Add(commandMapItem);
@@ -659,7 +666,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode)
{
CCommandMapItem commandMapItem;
- commandMapItem.ArcName = archiveName;
+ commandMapItem.ArcName = arcName;
FillCommand(kCompressEmail, mainString, commandMapItem);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap);
_commandMap.Add(commandMapItem);
@@ -668,7 +675,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
// CompressTo7z
if (contextMenuFlags & NContextMenuFlags::kCompressTo7z &&
- !archiveName7z.IsEqualToNoCase(fs2us(fi0.Name)))
+ !arcName7z.IsEqualTo_NoCase(fs2us(fi0.Name)))
{
CCommandMapItem commandMapItem;
UString s;
@@ -677,9 +684,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
commandMapItem.Folder = _dropPath;
else
commandMapItem.Folder = fs2us(folderPrefix);
- commandMapItem.ArcName = archiveName7z;
- commandMapItem.ArcType = L"7z";
- s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));
+ commandMapItem.ArcName = arcName7z;
+ commandMapItem.ArcType.SetFromAscii("7z");
+ MyFormatNew_ReducedName(s, arcName7z);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
_commandMap.Add(commandMapItem);
}
@@ -691,9 +698,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CCommandMapItem commandMapItem;
UString s;
FillCommand(kCompressTo7zEmail, s, commandMapItem);
- commandMapItem.ArcName = archiveName7z;
- commandMapItem.ArcType = L"7z";
- s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));
+ commandMapItem.ArcName = arcName7z;
+ commandMapItem.ArcType.SetFromAscii("7z");
+ MyFormatNew_ReducedName(s, arcName7z);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
_commandMap.Add(commandMapItem);
}
@@ -701,7 +708,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
// CompressToZip
if (contextMenuFlags & NContextMenuFlags::kCompressToZip &&
- !archiveNameZip.IsEqualToNoCase(fs2us(fi0.Name)))
+ !arcNameZip.IsEqualTo_NoCase(fs2us(fi0.Name)))
{
CCommandMapItem commandMapItem;
UString s;
@@ -710,9 +717,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
commandMapItem.Folder = _dropPath;
else
commandMapItem.Folder = fs2us(folderPrefix);
- commandMapItem.ArcName = archiveNameZip;
- commandMapItem.ArcType = L"zip";
- s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));
+ commandMapItem.ArcName = arcNameZip;
+ commandMapItem.ArcType.SetFromAscii("zip");
+ MyFormatNew_ReducedName(s, arcNameZip);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
_commandMap.Add(commandMapItem);
}
@@ -724,9 +731,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CCommandMapItem commandMapItem;
UString s;
FillCommand(kCompressToZipEmail, s, commandMapItem);
- commandMapItem.ArcName = archiveNameZip;
- commandMapItem.ArcType = L"zip";
- s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));
+ commandMapItem.ArcName = arcNameZip;
+ commandMapItem.ArcType.SetFromAscii("zip");
+ MyFormatNew_ReducedName(s, arcNameZip);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
_commandMap.Add(commandMapItem);
}
@@ -747,7 +754,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
mi.fMask |= MIIM_CHECKMARKS;
mi.wID = currentCommandID++;
mi.hSubMenu = popupMenu.Detach();
- mi.StringValue = L"7-Zip"; // LangString(IDS_CONTEXT_POPUP_CAPTION);
+ mi.StringValue.SetFromAscii("7-Zip"); // LangString(IDS_CONTEXT_POPUP_CAPTION);
mi.hbmpUnchecked = bitmap;
CMenu menu;
menu.Attach(hMenu);
@@ -774,7 +781,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
mi.fMask |= MIIM_CHECKMARKS;
mi.wID = currentCommandID++;
mi.hSubMenu = subMenu;
- mi.StringValue = L"CRC SHA";
+ mi.StringValue.SetFromAscii("CRC SHA");
mi.hbmpUnchecked = bitmap;
CMenu menu;
menu.Attach(hMenu);
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h
index b314bb38..a3b1174b 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.h
+++ b/CPP/7zip/UI/Explorer/ContextMenu.h
@@ -45,7 +45,7 @@ public:
STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax);
- HRESULT InitContextMenu(const wchar_t *folder, const wchar_t **names, unsigned numFiles);
+ HRESULT InitContextMenu(const wchar_t *folder, const wchar_t * const *names, unsigned numFiles);
CZipContextMenu();
~CZipContextMenu();
diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
index 478f6e97..d620cb70 100644
--- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
+++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
@@ -28,7 +28,10 @@
// {23170F69-40C1-278A-1000-000100020000}
DEFINE_GUID(CLSID_CZipContextMenu,
-0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);
+ k_7zip_GUID_Data1,
+ k_7zip_GUID_Data2,
+ k_7zip_GUID_Data3_Common,
+ 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);
using namespace NWindows;
diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp
index 4384c6ec..e1db1c9f 100644
--- a/CPP/7zip/UI/Far/ExtractEngine.cpp
+++ b/CPP/7zip/UI/Far/ExtractEngine.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#ifndef _7ZIP_ST
+#include "../../../Windows/Synchronization.h"
+#endif
+
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
@@ -13,13 +17,26 @@
using namespace NWindows;
using namespace NFar;
+#ifndef _7ZIP_ST
+static NSynchronization::CCriticalSection g_CriticalSection;
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+#define MT_LOCK
+#endif
+
+
+static HRESULT CheckBreak2()
+{
+ return WasEscPressed() ? E_ABORT : S_OK;
+}
+
extern void PrintMessage(const char *message);
-CExtractCallBackImp::~CExtractCallBackImp()
+CExtractCallbackImp::~CExtractCallbackImp()
{
}
-void CExtractCallBackImp::Init(
+void CExtractCallbackImp::Init(
UINT codePage,
CProgressBox *progressBox,
bool passwordIsDefined,
@@ -28,35 +45,41 @@ void CExtractCallBackImp::Init(
m_PasswordIsDefined = passwordIsDefined;
m_Password = password;
m_CodePage = codePage;
- m_ProgressBox = progressBox;
+ _percent = progressBox;
}
-STDMETHODIMP CExtractCallBackImp::SetTotal(UInt64 size)
+STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)
{
- _total = size;
- _totalIsDefined = true;
- return S_OK;
+ MT_LOCK
+
+ if (_percent)
+ {
+ _percent->Total = size;
+ _percent->Print();
+ }
+ return CheckBreak2();
}
-STDMETHODIMP CExtractCallBackImp::SetCompleted(const UInt64 *completeValue)
+STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)
{
- if (WasEscPressed())
- return E_ABORT;
- _processedIsDefined = (completeValue != NULL);
- if (_processedIsDefined)
- _processed = *completeValue;
- if (m_ProgressBox != 0)
- m_ProgressBox->Progress(
- _totalIsDefined ? &_total: NULL,
- _processedIsDefined ? &_processed: NULL, AString());
- return S_OK;
+ MT_LOCK
+
+ if (_percent)
+ {
+ if (completeValue)
+ _percent->Completed = *completeValue;
+ _percent->Print();
+ }
+ return CheckBreak2();
}
-STDMETHODIMP CExtractCallBackImp::AskOverwrite(
+STDMETHODIMP CExtractCallbackImp::AskOverwrite(
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
Int32 *answer)
{
+ MT_LOCK
+
NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo;
oldFileInfo.TimeIsDefined = (existTime != 0);
if (oldFileInfo.TimeIsDefined)
@@ -101,44 +124,62 @@ STDMETHODIMP CExtractCallBackImp::AskOverwrite(
default:
return E_FAIL;
}
- return S_OK;
+
+ return CheckBreak2();
}
-STDMETHODIMP CExtractCallBackImp::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 /* askExtractMode */, const UInt64 * /* position */)
+static const char *kTestString = "Testing";
+static const char *kExtractString = "Extracting";
+static const char *kSkipString = "Skipping";
+
+STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 * /* position */)
{
- if (WasEscPressed())
- return E_ABORT;
+ MT_LOCK
+
m_CurrentFilePath = name;
- return S_OK;
+ const char *s;
+
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;
+ case NArchive::NExtract::NAskMode::kTest: s = kTestString; break;
+ case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; break;
+ default: s = "???"; // return E_FAIL;
+ };
+
+ if (_percent)
+ {
+ _percent->Command = s;
+ _percent->FileName = name;
+ _percent->Print();
+ }
+
+ return CheckBreak2();
}
-STDMETHODIMP CExtractCallBackImp::MessageError(const wchar_t *message)
+STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *message)
{
+ MT_LOCK
+
AString s = UnicodeStringToMultiByte(message, CP_OEMCP);
- if (g_StartupInfo.ShowMessage((const char *)s) == -1)
+ if (g_StartupInfo.ShowErrorMessage((const char *)s) == -1)
return E_ABORT;
- return S_OK;
-}
-static void ReduceString(UString &s, unsigned size)
-{
- if (s.Len() > size)
- {
- s.Delete(size / 2, s.Len() - size);
- s.Insert(size / 2, L" ... ");
- }
+ return CheckBreak2();
}
-STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool encrypted)
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &s)
{
- switch (operationResult)
+ s.Empty();
+
+ switch (opRes)
{
case NArchive::NExtract::NOperationResult::kOK:
- break;
+ return;
default:
{
UINT messageID = 0;
- switch (operationResult)
+ switch (opRes)
{
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
messageID = NMessageID::kExtractUnsupportedMethod;
@@ -154,44 +195,78 @@ STDMETHODIMP CExtractCallBackImp::SetOperationResult(Int32 operationResult, bool
NMessageID::kExtractDataError;
break;
}
- UString name = m_CurrentFilePath;
- ReduceString(name, 70);
- AString s;
if (messageID != 0)
{
s = g_StartupInfo.GetMsgString(messageID);
s.Replace(" '%s'", "");
}
- else if (operationResult == NArchive::NExtract::NOperationResult::kUnavailable)
+ else if (opRes == NArchive::NExtract::NOperationResult::kUnavailable)
s = "Unavailable data";
- else if (operationResult == NArchive::NExtract::NOperationResult::kUnexpectedEnd)
+ else if (opRes == NArchive::NExtract::NOperationResult::kUnexpectedEnd)
s = "Unexpected end of data";
- else if (operationResult == NArchive::NExtract::NOperationResult::kDataAfterEnd)
+ else if (opRes == NArchive::NExtract::NOperationResult::kDataAfterEnd)
s = "There are some data after the end of the payload data";
- else if (operationResult == NArchive::NExtract::NOperationResult::kIsNotArc)
+ else if (opRes == NArchive::NExtract::NOperationResult::kIsNotArc)
s = "Is not archive";
- else if (operationResult == NArchive::NExtract::NOperationResult::kHeadersError)
+ else if (opRes == NArchive::NExtract::NOperationResult::kHeadersError)
s = "kHeaders Error";
else
{
char temp[16];
- ConvertUInt32ToString(operationResult, temp);
+ ConvertUInt32ToString(opRes, temp);
s = "Error #";
s += temp;
}
- s += "\n";
- s += UnicodeStringToMultiByte(name, m_CodePage);
- if (g_StartupInfo.ShowMessageLines(s) == -1)
- return E_ABORT;
}
}
- return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted)
+{
+ MT_LOCK
+
+ if (opRes == NArchive::NExtract::NOperationResult::kOK)
+ {
+ if (_percent)
+ {
+ _percent->Command.Empty();
+ _percent->FileName.Empty();
+ _percent->Files++;
+ }
+ }
+ else
+ {
+ AString s;
+ SetExtractErrorMessage(opRes, encrypted, s);
+ if (PrintErrorMessage(s, m_CurrentFilePath) == -1)
+ return E_ABORT;
+ }
+
+ return CheckBreak2();
+}
+
+
+STDMETHODIMP CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)
+{
+ MT_LOCK
+
+ if (opRes != NArchive::NExtract::NOperationResult::kOK)
+ {
+ AString s;
+ SetExtractErrorMessage(opRes, encrypted, s);
+ if (PrintErrorMessage(s, name) == -1)
+ return E_ABORT;
+ }
+
+ return CheckBreak2();
}
extern HRESULT GetPassword(UString &password);
-STDMETHODIMP CExtractCallBackImp::CryptoGetTextPassword(BSTR *password)
+STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)
{
+ MT_LOCK
+
if (!m_PasswordIsDefined)
{
RINOK(GetPassword(m_Password));
diff --git a/CPP/7zip/UI/Far/ExtractEngine.h b/CPP/7zip/UI/Far/ExtractEngine.h
index f57602a9..5861d92c 100644
--- a/CPP/7zip/UI/Far/ExtractEngine.h
+++ b/CPP/7zip/UI/Far/ExtractEngine.h
@@ -11,40 +11,29 @@
#include "ProgressBox.h"
-class CExtractCallBackImp:
+class CExtractCallbackImp:
public IFolderArchiveExtractCallback,
+ public IFolderArchiveExtractCallback2,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
public:
- MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+ MY_UNKNOWN_IMP2(ICryptoGetTextPassword, IFolderArchiveExtractCallback2)
// IProgress
STDMETHOD(SetTotal)(UInt64 size);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
- // IExtractCallBack
- STDMETHOD(AskOverwrite)(
- const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
- const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
- Int32 *result);
- STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);
+ INTERFACE_IFolderArchiveExtractCallback(;)
+ INTERFACE_IFolderArchiveExtractCallback2(;)
- STDMETHOD(MessageError)(const wchar_t *message);
- STDMETHOD(SetOperationResult)(Int32 resultEOperationResult, bool encrypted);
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
private:
- UInt64 _total;
- UInt64 _processed;
-
- bool _totalIsDefined;
- bool _processedIsDefined;
-
UString m_CurrentFilePath;
- CProgressBox *m_ProgressBox;
+ CProgressBox *_percent;
UINT m_CodePage;
bool m_PasswordIsDefined;
@@ -58,8 +47,8 @@ private:
*/
void AddErrorMessage(LPCTSTR message);
public:
- CExtractCallBackImp(): _totalIsDefined(false), _processedIsDefined(false) {}
- ~CExtractCallBackImp();
+ // CExtractCallbackImp() {}
+ ~CExtractCallbackImp();
void Init(UINT codePage,
CProgressBox *progressBox,
bool passwordIsDefined, const UString &password);
diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp
index 38fed101..3ae5bba2 100644
--- a/CPP/7zip/UI/Far/Far.cpp
+++ b/CPP/7zip/UI/Far/Far.cpp
@@ -1,3 +1,4 @@
+// Far.cpp
// Test Align for updating !!!!!!!!!!!!!!!!!!
#include "StdAfx.h"
@@ -11,8 +12,6 @@
#include "../../Common/FileStreams.h"
-#include "../Agent/Agent.h"
-
#include "Messages.h"
#include "Plugin.h"
#include "ProgressBox.h"
@@ -22,6 +21,8 @@ using namespace NFile;
using namespace NDir;
using namespace NFar;
+static const DWORD kShowProgressTime_ms = 100;
+
static const char *kCommandPrefix = "7-zip";
static const TCHAR *kRegisrtryMainKeyName = TEXT("");
static const TCHAR *kRegisrtryValueNameEnabled = TEXT("UsedByDefault3");
@@ -30,6 +31,12 @@ static bool kPluginEnabledDefault = true;
HINSTANCE g_hInstance;
+namespace NFar {
+
+const char *g_PluginName_for_Error = "7-Zip";
+
+}
+
#define NT_CHECK_FAIL_ACTION return FALSE;
BOOL WINAPI DllMain(
@@ -42,9 +49,14 @@ BOOL WINAPI DllMain(
{
if (dwReason == DLL_PROCESS_ATTACH)
{
+ // OutputDebugStringA("7-Zip FAR DLL_PROCESS_ATTACH");
g_hInstance = (HINSTANCE)hInstance;
NT_CHECK
}
+ if (dwReason == DLL_PROCESS_DETACH)
+ {
+ // OutputDebugStringA("7-Zip FAR DLL_PROCESS_DETACH");
+ }
return TRUE;
}
@@ -55,6 +67,18 @@ static struct COptions
static const TCHAR *kPliginNameForRegestry = TEXT("7-ZIP");
+EXTERN_C void WINAPI ExitFAR()
+{
+ /* WIN32:
+ it's not allowed to call FreeLibrary() from FreeLibrary().
+ So we try to free all DLLs before destructors */
+ // OutputDebugStringA("-- ExitFAR --- START");
+
+ FreeGlobalCodecs();
+
+ // OutputDebugStringA("-- ExitFAR --- END");
+}
+
EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info)
{
MY_TRY_BEGIN;
@@ -62,6 +86,10 @@ EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info)
g_Options.Enabled = g_StartupInfo.QueryRegKeyValue(
HKEY_CURRENT_USER, kRegisrtryMainKeyName,
kRegisrtryValueNameEnabled, kPluginEnabledDefault);
+
+ // OutputDebugStringA("SetStartupInfo");
+ // LoadGlobalCodecs();
+
MY_TRY_END1("SetStartupInfo");
}
@@ -77,17 +105,8 @@ class COpenArchiveCallback:
CProgressBox _progressBox;
- UInt64 _numFilesTotal;
- UInt64 _numFilesCur;
- UInt64 _numBytesTotal;
- UInt64 _numBytesCur;
-
bool _numFilesTotalDefined;
- bool _numFilesCurDefined;
bool _numBytesTotalDefined;
- bool _numBytesCurDefined;
-
- DWORD m_PrevTickCount;
NFind::CFileInfo _fileInfo;
public:
@@ -123,12 +142,13 @@ public:
PasswordIsDefined = false;
_numFilesTotalDefined = false;
- _numFilesCurDefined = false;
_numBytesTotalDefined = false;
- _numBytesCurDefined = false;
m_MessageBoxIsShown = false;
- m_PrevTickCount = GetTickCount();
+
+ _progressBox.Init(
+ // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kReading));
}
void ShowMessage();
@@ -140,113 +160,60 @@ public:
}
};
+static HRESULT CheckBreak2()
+{
+ return WasEscPressed() ? E_ABORT : S_OK;
+}
+
void COpenArchiveCallback::ShowMessage()
{
- DWORD currentTime = GetTickCount();
if (!m_MessageBoxIsShown)
{
- if (currentTime - m_PrevTickCount < 100)
+ DWORD currentTime = GetTickCount();
+ if (currentTime - _progressBox.StartTick < kShowProgressTime_ms)
return;
- _progressBox.Init(
- // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
- g_StartupInfo.GetMsgString(NMessageID::kReading), 48);
-
m_MessageBoxIsShown = true;
}
- else
- {
- if (currentTime - m_PrevTickCount < 200)
- return;
- }
- m_PrevTickCount = currentTime;
- UInt64 total = 0, cur = 0;
- bool curIsDefined = false, totalIsDefined = false;
-
- char message[256];
- message[0] = 0;
- if (_numFilesCurDefined)
- ConvertUInt64ToStringAligned(_numFilesCur, message, 5);
-
- if (_numFilesTotalDefined)
- {
- strcat(message, " / ");
- ConvertUInt64ToStringAligned(_numFilesTotal, message + strlen(message), 5);
- total = _numFilesTotal;
- totalIsDefined = true;
- if (_numFilesCurDefined)
- {
- cur = _numFilesCur;
- curIsDefined = true;
- }
- }
- else if (_numBytesTotalDefined)
- {
- total = _numBytesTotal;
- totalIsDefined = true;
- if (_numBytesCurDefined)
- {
- cur = _numBytesCur;
- curIsDefined = true;
- }
- }
- _progressBox.Progress(
- totalIsDefined ? &total: NULL,
- curIsDefined ? &cur: NULL,
- message);
+ _progressBox.UseBytesForPercents = !_numFilesTotalDefined;
+ _progressBox.Print();
}
STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes)
{
- if (WasEscPressed())
- return E_ABORT;
-
_numFilesTotalDefined = (numFiles != NULL);
if (_numFilesTotalDefined)
- _numFilesTotal = *numFiles;
+ _progressBox.FilesTotal = *numFiles;
_numBytesTotalDefined = (numBytes != NULL);
if (_numBytesTotalDefined)
- _numBytesTotal = *numBytes;
+ _progressBox.Total = *numBytes;
- return S_OK;
+ return CheckBreak2();
}
STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes)
{
- if (WasEscPressed())
- return E_ABORT;
+ if (numFiles)
+ _progressBox.Files = *numFiles;
- _numFilesCurDefined = (numFiles != NULL);
- if (_numFilesCurDefined)
- _numFilesCur = *numFiles;
+ if (numBytes)
+ _progressBox.Completed = *numBytes;
- _numBytesCurDefined = (numBytes != NULL);
- if (_numBytesCurDefined)
- _numBytesCur = *numBytes;
-
- // if (*numFiles % 100 != 0)
- // return S_OK;
ShowMessage();
- return S_OK;
+ return CheckBreak2();
}
STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 /* total */)
{
- if (WasEscPressed())
- return E_ABORT;
- return S_OK;
+ return CheckBreak2();
}
-STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed)
+STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 * /* completed */)
{
- if (WasEscPressed())
- return E_ABORT;
- if (completed == NULL)
- return S_OK;
ShowMessage();
- return S_OK;
+ return CheckBreak2();
}
STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **inStream)
@@ -303,7 +270,7 @@ HRESULT GetPassword(UString &password)
// sprintf(DialogItems[1].Data,GetMsg(MGetPasswordForFile),FileName);
if (g_StartupInfo.ShowDialog(76, 6, NULL, dialogItems, kNumItems) < 0)
- return (E_ABORT);
+ return E_ABORT;
AString oemPassword = dialogItems[2].Data;
password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);
@@ -383,26 +350,28 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name)
{
if (result == E_ABORT)
return (HANDLE)-2;
+ ShowSysErrorMessage(result);
return INVALID_HANDLE_VALUE;
}
UString errorMessage = agent->GetErrorMessage();
if (!errorMessage.IsEmpty())
- PrintErrorMessage("7-Zip", UnicodeStringToMultiByte(errorMessage, CP_OEMCP));
+ g_StartupInfo.ShowErrorMessage(UnicodeStringToMultiByte(errorMessage, CP_OEMCP));
// ::OutputDebugStringA("after OpenArchive\n");
CPlugin *plugin = new CPlugin(
fullName,
// defaultName,
- archiveHandler,
+ agent,
(const wchar_t *)archiveType
);
- if (plugin == NULL)
- return(INVALID_HANDLE_VALUE);
+ if (!plugin)
+ return INVALID_HANDLE_VALUE;
plugin->PasswordIsDefined = openArchiveCallbackSpec->PasswordIsDefined;
plugin->Password = openArchiveCallbackSpec->Password;
+ // OutputDebugStringA("--- OpenFilePlugin ---- END");
return (HANDLE)(plugin);
}
@@ -420,6 +389,7 @@ static HANDLE MyOpenFilePlugin(const char *name)
EXTERN_C HANDLE WINAPI OpenFilePlugin(char *name, const unsigned char * /* data */, int /* dataSize */)
{
MY_TRY_BEGIN;
+ // OutputDebugStringA("--- OpenFilePlugin");
if (name == NULL || (!g_Options.Enabled))
{
// if (!Opt.ProcessShiftF1)
@@ -474,9 +444,14 @@ EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item)
case 1:
{
CObjectVector<PluginPanelItem> pluginPanelItem;
- if(!g_StartupInfo.ControlGetActivePanelSelectedOrCurrentItems(pluginPanelItem))
+ if (!g_StartupInfo.ControlGetActivePanelSelectedOrCurrentItems(pluginPanelItem))
throw 142134;
- if (CompressFiles(pluginPanelItem) == S_OK)
+ HRESULT res = CompressFiles(pluginPanelItem);
+ if (res != S_OK && res != E_ABORT)
+ {
+ ShowSysErrorMessage(res);
+ }
+ // if (res == S_OK)
{
/* int t = */ g_StartupInfo.ControlClearPanelSelection();
g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEPANEL, NULL);
@@ -496,8 +471,10 @@ EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item)
EXTERN_C void WINAPI ClosePlugin(HANDLE plugin)
{
+ // OutputDebugStringA("-- ClosePlugin --- START");
MY_TRY_BEGIN;
delete (CPlugin *)plugin;
+ // OutputDebugStringA("-- ClosePlugin --- END");
MY_TRY_END1("ClosePlugin");
}
@@ -599,14 +576,14 @@ EXTERN_C void WINAPI GetOpenPluginInfo(HANDLE plugin,struct OpenPluginInfo *info
EXTERN_C int WINAPI PutFiles(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber, int move, int opMode)
{
MY_TRY_BEGIN;
- return(((CPlugin *)plugin)->PutFiles(panelItems, itemsNumber, move, opMode));
+ return (((CPlugin *)plugin)->PutFiles(panelItems, itemsNumber, move, opMode));
MY_TRY_END2("PutFiles", NFileOperationReturnCode::kError);
}
EXTERN_C int WINAPI DeleteFiles(HANDLE plugin, PluginPanelItem *panelItems, int itemsNumber, int opMode)
{
MY_TRY_BEGIN;
- return(((CPlugin *)plugin)->DeleteFiles(panelItems, itemsNumber, opMode));
+ return (((CPlugin *)plugin)->DeleteFiles(panelItems, itemsNumber, opMode));
MY_TRY_END2("DeleteFiles", FALSE);
}
diff --git a/CPP/7zip/UI/Far/Far.def b/CPP/7zip/UI/Far/Far.def
index 39f3a5e2..1de9acdf 100644
--- a/CPP/7zip/UI/Far/Far.def
+++ b/CPP/7zip/UI/Far/Far.def
@@ -3,6 +3,7 @@
LIBRARY "7-ZipFar"
EXPORTS
+ ExitFAR
SetStartupInfo
OpenPlugin
OpenFilePlugin
diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp
index bd50fd93..26365152 100644
--- a/CPP/7zip/UI/Far/Far.dsp
+++ b/CPP/7zip/UI/Far/Far.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 "FAR_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /D "NEW_FOLDER_INTERFACE" /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 "FAR_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FAR_EXPORTS" /D "EXTERNAL_CODECS" /D "NEW_FOLDER_INTERFACE" /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"
@@ -342,6 +342,14 @@ SOURCE=..\..\..\Windows\Registry.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Windows\ResourceString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ResourceString.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Windows\Synchronization.cpp
# End Source File
# Begin Source File
@@ -526,6 +534,18 @@ SOURCE=..\Agent\AgentProxy.h
# End Source File
# Begin Source File
+SOURCE=..\Agent\ArchiveFolder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\ArchiveFolderOpen.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Agent\ArchiveFolderOut.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\Agent\IFolderArchive.h
# End Source File
# Begin Source File
@@ -554,6 +574,14 @@ SOURCE=..\..\Compress\CopyCoder.h
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\Common\CreateCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\CreateCoder.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Common\FilePathAutoRename.cpp
# End Source File
# Begin Source File
@@ -570,6 +598,14 @@ SOURCE=..\..\Common\FileStreams.h
# End Source File
# Begin Source File
+SOURCE=..\..\Common\FilterCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilterCoder.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Common\LimitedStreams.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/UI/Far/FarPlugin.h b/CPP/7zip/UI/Far/FarPlugin.h
index a6185a1d..859d319f 100644
--- a/CPP/7zip/UI/Far/FarPlugin.h
+++ b/CPP/7zip/UI/Far/FarPlugin.h
@@ -104,18 +104,27 @@ typedef int (WINAPI *FARAPIDIALOG)(
);
enum {
- FMSG_WARNING=1,
- FMSG_ERRORTYPE=2,
- FMSG_KEEPBACKGROUND=4,
- FMSG_DOWN=8,
- FMSG_LEFTALIGN=16
+ FMSG_WARNING = 0x00000001,
+ FMSG_ERRORTYPE = 0x00000002,
+ FMSG_KEEPBACKGROUND = 0x00000004,
+ FMSG_DOWN = 0x00000008,
+ FMSG_LEFTALIGN = 0x00000010,
+
+ FMSG_ALLINONE = 0x00000020,
+
+ FMSG_MB_OK = 0x00010000,
+ FMSG_MB_OKCANCEL = 0x00020000,
+ FMSG_MB_ABORTRETRYIGNORE = 0x00030000,
+ FMSG_MB_YESNO = 0x00040000,
+ FMSG_MB_YESNOCANCEL = 0x00050000,
+ FMSG_MB_RETRYCANCEL = 0x00060000
};
typedef int (WINAPI *FARAPIMESSAGE)(
INT_PTR PluginNumber,
unsigned int Flags,
- char *HelpTopic,
- char **Items,
+ const char *HelpTopic,
+ const char * const *Items,
int ItemsNumber,
int ButtonsNumber
);
@@ -424,21 +433,22 @@ struct OpenPluginInfo
{
int StructSize;
DWORD Flags;
- char *HostFile;
- char *CurDir;
- char *Format;
- char *PanelTitle;
- struct InfoPanelLine *InfoLines;
+ const char *HostFile;
+ const char *CurDir;
+ const char *Format;
+ const char *PanelTitle;
+ const struct InfoPanelLine *InfoLines;
int InfoLinesNumber;
- char **DescrFiles;
+ const char * const *DescrFiles;
int DescrFilesNumber;
- struct PanelMode *PanelModesArray;
+ const struct PanelMode *PanelModesArray;
int PanelModesNumber;
int StartPanelMode;
int StartSortMode;
int StartSortOrder;
- struct KeyBarTitles *KeyBar;
- char *ShortcutData;
+ const struct KeyBarTitles *KeyBar;
+ const char *ShortcutData;
+ // long Reserverd;
};
enum {
diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp
index 14343522..28a4ada9 100644
--- a/CPP/7zip/UI/Far/FarUtils.cpp
+++ b/CPP/7zip/UI/Far/FarUtils.cpp
@@ -2,6 +2,7 @@
#include "StdAfx.h"
+#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#ifndef UNDER_CE
@@ -35,8 +36,8 @@ const char *CStartupInfo::GetMsgString(int messageId)
int CStartupInfo::ShowMessage(unsigned int flags,
const char *helpTopic, const char **items, int numItems, int numButtons)
{
- return m_Data.Message(m_Data.ModuleNumber, flags, (char *)helpTopic,
- (char **)items, numItems, numButtons);
+ return m_Data.Message(m_Data.ModuleNumber, flags, helpTopic,
+ items, numItems, numButtons);
}
namespace NMessageID
@@ -50,12 +51,40 @@ namespace NMessageID
};
}
-int CStartupInfo::ShowMessage(const char *message)
+int CStartupInfo::ShowWarningWithOk(const char **items, int numItems)
{
- const char *items[]= { GetMsgString(NMessageID::kError), message, GetMsgString(NMessageID::kOk) };
- return ShowMessage(FMSG_WARNING, NULL, items, ARRAY_SIZE(items), 1);
+ return ShowMessage(FMSG_WARNING | FMSG_MB_OK, NULL, items, numItems, 0);
}
+extern const char *g_PluginName_for_Error;
+
+void CStartupInfo::SetErrorTitle(AString &s)
+{
+ if (g_PluginName_for_Error)
+ {
+ s += g_PluginName_for_Error;
+ s += ": ";
+ }
+ s += GetMsgString(NMessageID::kError);
+}
+
+int CStartupInfo::ShowErrorMessage(const char *message)
+{
+ AString s;
+ SetErrorTitle(s);
+ const char *items[]= { s, message };
+ return ShowWarningWithOk(items, ARRAY_SIZE(items));
+}
+
+int CStartupInfo::ShowErrorMessage2(const char *m1, const char *m2)
+{
+ AString s;
+ SetErrorTitle(s);
+ const char *items[]= { s, m1, m2 };
+ return ShowWarningWithOk(items, ARRAY_SIZE(items));
+}
+
+/*
static void SplitString(const AString &srcString, AStringVector &destStrings)
{
destStrings.Clear();
@@ -80,7 +109,9 @@ static void SplitString(const AString &srcString, AStringVector &destStrings)
if (!string.IsEmpty())
destStrings.Add(string);
}
+*/
+/*
int CStartupInfo::ShowMessageLines(const char *message)
{
AStringVector strings;
@@ -94,10 +125,22 @@ int CStartupInfo::ShowMessageLines(const char *message)
return ShowMessage(FMSG_WARNING, NULL, items, pos, 1);
}
+*/
+
+/*
+int CStartupInfo::ShowMessageLines(const char *message)
+{
+ AString s = GetMsgString(NMessageID::kError);
+ s.Add_LF();
+ s += message;
+ return ShowMessage(FMSG_WARNING | FMSG_MB_OK | FMSG_ALLINONE, NULL,
+ (const char **)(const char *)s, 1, 0);
+}
+*/
int CStartupInfo::ShowMessage(int messageId)
{
- return ShowMessage(GetMsgString(messageId));
+ return ShowErrorMessage(GetMsgString(messageId));
}
int CStartupInfo::ShowDialog(int X1, int Y1, int X2, int Y2,
@@ -129,14 +172,14 @@ void CStartupInfo::InitDialogItems(const CInitDialogItem *srcItems,
destItem.X2 = srcItem.X2;
destItem.Y2 = srcItem.Y2;
destItem.Focus = GetBOOLValue(srcItem.Focus);
- if(srcItem.HistoryName != NULL)
+ if (srcItem.HistoryName != NULL)
destItem.History = srcItem.HistoryName;
else
destItem.Selected = GetBOOLValue(srcItem.Selected);
destItem.Flags = srcItem.Flags;
destItem.DefaultButton = GetBOOLValue(srcItem.DefaultButton);
- if(srcItem.DataMessageId < 0)
+ if (srcItem.DataMessageId < 0)
MyStringCopy(destItem.Data, srcItem.DataString);
else
MyStringCopy(destItem.Data, GetMsgString(srcItem.DataMessageId));
@@ -220,7 +263,7 @@ CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyN
return valueDefault;
CSysString value;
- if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
+ if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
return valueDefault;
return value;
@@ -234,7 +277,7 @@ UInt32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,
return valueDefault;
UInt32 value;
- if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
+ if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
return valueDefault;
return value;
@@ -248,7 +291,7 @@ bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const CSysString &keyName,
return valueDefault;
bool value;
- if(regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
+ if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
return valueDefault;
return value;
@@ -278,9 +321,9 @@ bool CStartupInfo::ControlGetActivePanelCurrentItemInfo(
PluginPanelItem &pluginPanelItem)
{
PanelInfo panelInfo;
- if(!ControlGetActivePanelInfo(panelInfo))
+ if (!ControlGetActivePanelInfo(panelInfo))
return false;
- if(panelInfo.ItemsNumber <= 0)
+ if (panelInfo.ItemsNumber <= 0)
throw "There are no items";
pluginPanelItem = panelInfo.PanelItems[panelInfo.CurrentItem];
return true;
@@ -291,9 +334,9 @@ bool CStartupInfo::ControlGetActivePanelSelectedOrCurrentItems(
{
pluginPanelItems.Clear();
PanelInfo panelInfo;
- if(!ControlGetActivePanelInfo(panelInfo))
+ if (!ControlGetActivePanelInfo(panelInfo))
return false;
- if(panelInfo.ItemsNumber <= 0)
+ if (panelInfo.ItemsNumber <= 0)
throw "There are no items";
if (panelInfo.SelectedItemsNumber == 0)
pluginPanelItems.Add(panelInfo.PanelItems[panelInfo.CurrentItem]);
@@ -306,7 +349,7 @@ bool CStartupInfo::ControlGetActivePanelSelectedOrCurrentItems(
bool CStartupInfo::ControlClearPanelSelection()
{
PanelInfo panelInfo;
- if(!ControlGetActivePanelInfo(panelInfo))
+ if (!ControlGetActivePanelInfo(panelInfo))
return false;
for (int i = 0; i < panelInfo.ItemsNumber; i++)
panelInfo.PanelItems[i].Flags &= ~PPIF_SELECTED;
@@ -375,7 +418,7 @@ CScreenRestorer::~CScreenRestorer()
}
void CScreenRestorer::Save()
{
- if(m_Saved)
+ if (m_Saved)
return;
m_HANDLE = g_StartupInfo.SaveScreen();
m_Saved = true;
@@ -383,41 +426,67 @@ void CScreenRestorer::Save()
void CScreenRestorer::Restore()
{
- if(m_Saved)
+ if (m_Saved)
{
g_StartupInfo.RestoreScreen(m_HANDLE);
m_Saved = false;
}
};
-static AString DWORDToString(DWORD number)
+int PrintErrorMessage(const char *message, unsigned code)
{
- char buffer[32];
- _ultoa(number, buffer, 10);
- return buffer;
+ AString s = message;
+ s += " #";
+ char temp[16];
+ ConvertUInt32ToString((UInt32)code, temp);
+ s += temp;
+ return g_StartupInfo.ShowErrorMessage(s);
}
-void PrintErrorMessage(const char *message, int code)
+int PrintErrorMessage(const char *message, const char *text)
{
- AString tmp = message;
- tmp += " #";
- tmp += DWORDToString(code);
- g_StartupInfo.ShowMessage(tmp);
+ return g_StartupInfo.ShowErrorMessage2(message, text);
}
-void PrintErrorMessage(const char *message, const char *text)
+
+static void ReduceString(UString &s, unsigned size)
{
- AString tmp = message;
- tmp += ":\n";
- tmp += text;
- g_StartupInfo.ShowMessageLines(tmp);
+ if (s.Len() > size)
+ {
+ if (size > 5)
+ size -= 5;
+ s.Delete(size / 2, s.Len() - size);
+ s.Insert(size / 2, L" ... ");
+ }
}
-void PrintErrorMessage(const char *message, const wchar_t *text)
+int PrintErrorMessage(const char *message, const wchar_t *name, unsigned maxLen)
{
- PrintErrorMessage(message, UnicodeStringToMultiByte(text, CP_OEMCP));
+ UString s = name;
+ ReduceString(s, maxLen);
+ return PrintErrorMessage(message, UnicodeStringToMultiByte(s, CP_OEMCP));
}
+int ShowSysErrorMessage(DWORD errorCode)
+{
+ UString message = NError::MyFormatMessage(errorCode);
+ return g_StartupInfo.ShowErrorMessage(UnicodeStringToMultiByte(message, CP_OEMCP));
+}
+
+int ShowLastErrorMessage()
+{
+ return ShowSysErrorMessage(::GetLastError());
+}
+
+int ShowSysErrorMessage(DWORD errorCode, const wchar_t *name)
+{
+ UString s = NError::MyFormatMessage(errorCode);
+ AString s1 = UnicodeStringToMultiByte(s, CP_OEMCP);
+ AString s2 = UnicodeStringToMultiByte(name, CP_OEMCP);
+ return g_StartupInfo.ShowErrorMessage2(s1, s2);
+}
+
+
bool WasEscPressed()
{
#ifdef UNDER_CE
@@ -425,19 +494,19 @@ bool WasEscPressed()
#else
NConsole::CIn inConsole;
HANDLE handle = ::GetStdHandle(STD_INPUT_HANDLE);
- if(handle == INVALID_HANDLE_VALUE)
+ if (handle == INVALID_HANDLE_VALUE)
return true;
inConsole.Attach(handle);
for (;;)
{
DWORD numEvents;
- if(!inConsole.GetNumberOfEvents(numEvents))
+ if (!inConsole.GetNumberOfEvents(numEvents))
return true;
- if(numEvents == 0)
+ if (numEvents == 0)
return false;
INPUT_RECORD event;
- if(!inConsole.ReadEvent(event, numEvents))
+ if (!inConsole.ReadEvent(event, numEvents))
return true;
if (event.EventType == KEY_EVENT &&
event.Event.KeyEvent.bKeyDown &&
@@ -447,17 +516,4 @@ bool WasEscPressed()
#endif
}
-void ShowErrorMessage(DWORD errorCode)
-{
- UString message = NError::MyFormatMessage(errorCode);
- message.RemoveChar(L'\x0D');
- message.Replace(L'\x0A', L' ');
- g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP));
-}
-
-void ShowLastErrorMessage()
-{
- ShowErrorMessage(::GetLastError());
-}
-
}
diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h
index 1a5a49c7..edec4cf9 100644
--- a/CPP/7zip/UI/Far/FarUtils.h
+++ b/CPP/7zip/UI/Far/FarUtils.h
@@ -59,10 +59,15 @@ public:
void Init(const PluginStartupInfo &pluginStartupInfo,
const CSysString &pluginNameForRegestry);
const char *GetMsgString(int messageId);
+
int ShowMessage(unsigned int flags, const char *helpTopic,
const char **items, int numItems, int numButtons);
- int ShowMessage(const char *message);
- int ShowMessageLines(const char *message);
+ int ShowWarningWithOk(const char **items, int numItems);
+
+ void SetErrorTitle(AString &s);
+ int ShowErrorMessage(const char *message);
+ int ShowErrorMessage2(const char *m1, const char *m2);
+ // int ShowMessageLines(const char *messageLines);
int ShowMessage(int messageId);
int ShowDialog(int X1, int Y1, int X2, int Y2,
@@ -158,30 +163,32 @@ public:
extern CStartupInfo g_StartupInfo;
-void PrintErrorMessage(const char *message, int code);
-void PrintErrorMessage(const char *message, const char *text);
-void PrintErrorMessage(const char *message, const wchar_t *text);
-#define MY_TRY_BEGIN try\
- {
+int PrintErrorMessage(const char *message, unsigned code);
+int PrintErrorMessage(const char *message, const char *text);
+int PrintErrorMessage(const char *message, const wchar_t *name, unsigned maxLen = 70);
-#define MY_TRY_END1(x) }\
- catch(int n) { PrintErrorMessage(x, n); return; }\
+#define MY_TRY_BEGIN try {
+
+#define MY_TRY_END1(x) }\
+ catch(unsigned n) { PrintErrorMessage(x, n); return; }\
catch(const CSysString &s) { PrintErrorMessage(x, s); return; }\
catch(const char *s) { PrintErrorMessage(x, s); return; }\
- catch(...) { g_StartupInfo.ShowMessage(x); return; }
+ catch(...) { g_StartupInfo.ShowErrorMessage(x); return; }
-#define MY_TRY_END2(x, y) }\
- catch(int n) { PrintErrorMessage(x, n); return y; }\
+#define MY_TRY_END2(x, y) }\
+ catch(unsigned n) { PrintErrorMessage(x, n); return y; }\
catch(const AString &s) { PrintErrorMessage(x, s); return y; }\
catch(const char *s) { PrintErrorMessage(x, s); return y; }\
catch(const UString &s) { PrintErrorMessage(x, s); return y; }\
catch(const wchar_t *s) { PrintErrorMessage(x, s); return y; }\
- catch(...) { g_StartupInfo.ShowMessage(x); return y; }
+ catch(...) { g_StartupInfo.ShowErrorMessage(x); return y; }
+
+int ShowSysErrorMessage(DWORD errorCode);
+int ShowSysErrorMessage(DWORD errorCode, const wchar_t *name);
+int ShowLastErrorMessage();
bool WasEscPressed();
-void ShowErrorMessage(DWORD errorCode);
-void ShowLastErrorMessage();
}
diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp
index bebd47de..8df7b512 100644
--- a/CPP/7zip/UI/Far/Plugin.cpp
+++ b/CPP/7zip/UI/Far/Plugin.cpp
@@ -27,14 +27,15 @@ int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2)
}
-CPlugin::CPlugin(const FString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName):
- m_ArchiveHandler(archiveHandler),
+CPlugin::CPlugin(const FString &fileName, CAgent *agent, UString archiveTypeName):
+ _agent(agent),
m_FileName(fileName),
_archiveTypeName(archiveTypeName)
{
+ m_ArchiveHandler = agent;
if (!m_FileInfo.Find(m_FileName))
throw "error";
- archiveHandler->BindToRootFolder(&_folder);
+ m_ArchiveHandler->BindToRootFolder(&_folder);
}
CPlugin::~CPlugin() {}
@@ -194,7 +195,7 @@ void CPlugin::EnterToDirectory(const UString &dirName)
if (dirName == kDotsReplaceStringU)
s = L"..";
_folder->BindToFolder(s, &newFolder);
- if (newFolder == NULL)
+ if (!newFolder)
if (dirName.IsEmpty())
return;
else
@@ -214,7 +215,7 @@ int CPlugin::SetDirectory(const char *aszDir, int /* opMode */)
{
CMyComPtr<IFolderFolder> newFolder;
_folder->BindToParentFolder(&newFolder);
- if (newFolder == NULL)
+ if (!newFolder)
throw 40312;
_folder = newFolder;
}
@@ -245,7 +246,7 @@ void CPlugin::GetPathParts(UStringVector &pathParts)
{
CMyComPtr<IFolderFolder> newFolder;
folderItem->BindToParentFolder(&newFolder);
- if (newFolder == NULL)
+ if (!newFolder)
break;
NCOM::CPropVariant prop;
if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK)
@@ -258,16 +259,29 @@ void CPlugin::GetPathParts(UStringVector &pathParts)
void CPlugin::SetCurrentDirVar()
{
m_CurrentDir.Empty();
+
+ /*
+ // kpidPath path has tail slash, but we don't need it for compatibility with default FAR style
+ NCOM::CPropVariant prop;
+ if (_folder->GetFolderProperty(kpidPath, &prop) == S_OK)
+ if (prop.vt == VT_BSTR)
+ {
+ m_CurrentDir = (wchar_t *)prop.bstrVal;
+ // if (!m_CurrentDir.IsEmpty())
+ }
+ m_CurrentDir.InsertAtFront(WCHAR_PATH_SEPARATOR);
+ */
+
UStringVector pathParts;
GetPathParts(pathParts);
FOR_VECTOR (i, pathParts)
{
- m_CurrentDir += WCHAR_PATH_SEPARATOR;
+ m_CurrentDir.Add_PathSepar();
m_CurrentDir += pathParts[i];
}
}
-static char *kPluginFormatName = "7-ZIP";
+static const char *kPluginFormatName = "7-ZIP";
static int FindPropNameID(PROPID propID)
@@ -290,19 +304,19 @@ static CPropertyIDInfo kPropertyIDInfos[] =
{
{ kpidName, "N", 0},
{ kpidSize, "S", 8},
- { kpidPackedSize, "P", 8},
+ { kpidPackSize, "P", 8},
{ kpidAttrib, "A", 0},
{ kpidCTime, "DC", 14},
{ kpidATime, "DA", 14},
{ kpidMTime, "DM", 14},
{ kpidSolid, NULL, 0, 'S'},
- { kpidEncrypted, NULL, 0, 'P'}
+ { kpidEncrypted, NULL, 0, 'P'},
{ kpidDictionarySize, IDS_PROPERTY_DICTIONARY_SIZE },
{ kpidSplitBefore, NULL, 'B'},
{ kpidSplitAfter, NULL, 'A'},
- { kpidComment, , NULL, 'C'},
+ { kpidComment, NULL, 'C'},
{ kpidCRC, IDS_PROPERTY_CRC }
// { kpidType, L"Type" }
};
@@ -394,17 +408,20 @@ static AString ConvertSizeToString(UInt64 value)
static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID)
{
- AString s;
-
if (prop.vt == VT_BSTR)
- s = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP);
- else if (prop.vt == VT_BOOL)
+ {
+ AString s = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP);
+ s.Replace((char)0xA, ' ');
+ s.Replace((char)0xD, ' ');
+ return s;
+ }
+ if (prop.vt == VT_BOOL)
{
int messageID = VARIANT_BOOLToBool(prop.boolVal) ?
NMessageID::kYes : NMessageID::kNo;
return g_StartupInfo.GetMsgString(messageID);
}
- else if (prop.vt != VT_EMPTY)
+ if (prop.vt != VT_EMPTY)
{
if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && (
propID == kpidSize ||
@@ -420,18 +437,15 @@ static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID)
{
UInt64 v = 0;
ConvertPropVariantToUInt64(prop, v);
- s = ConvertSizeToString(v);
+ return ConvertSizeToString(v);
}
- else
{
- UString temp;
- ConvertPropertyToString(temp, prop, propID);
- s = UnicodeStringToMultiByte(temp, CP_OEMCP);
+ char sz[64];
+ ConvertPropertyToShortString(sz, prop, propID);
+ return sz;
}
}
- s.Replace((char)0xA, ' ');
- s.Replace((char)0xD, ' ');
- return s;
+ return AString();
}
static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID)
@@ -489,12 +503,11 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)
name = fs2us(fileName);
}
- m_PannelTitle =
- UString(L' ') +
- _archiveTypeName +
- UString(L':') +
- name +
- UString(L' ');
+ m_PannelTitle = L' ';
+ m_PannelTitle += _archiveTypeName;
+ m_PannelTitle += L':';
+ m_PannelTitle += name;
+ m_PannelTitle.Add_Space();
if (!m_CurrentDir.IsEmpty())
{
// m_PannelTitle += '\\';
@@ -629,25 +642,25 @@ void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)
/*
AddColumn(kpidName);
AddColumn(kpidSize);
- AddColumn(kpidPackedSize);
+ AddColumn(kpidPackSize);
AddColumn(kpidMTime);
AddColumn(kpidCTime);
AddColumn(kpidATime);
AddColumn(kpidAttrib);
- PanelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes;
- PanelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths;
- PanelMode.ColumnTitles = NULL;
- PanelMode.FullScreen = TRUE;
- PanelMode.DetailedStatus = FALSE;
- PanelMode.AlignExtensions = FALSE;
- PanelMode.CaseConversion = FALSE;
- PanelMode.StatusColumnTypes = "N";
- PanelMode.StatusColumnWidths = "0";
- PanelMode.Reserved[0] = 0;
- PanelMode.Reserved[1] = 0;
-
- info->PanelModesArray = &PanelMode;
+ _PanelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes;
+ _PanelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths;
+ _PanelMode.ColumnTitles = NULL;
+ _PanelMode.FullScreen = TRUE;
+ _PanelMode.DetailedStatus = FALSE;
+ _PanelMode.AlignExtensions = FALSE;
+ _PanelMode.CaseConversion = FALSE;
+ _PanelMode.StatusColumnTypes = "N";
+ _PanelMode.StatusColumnWidths = "0";
+ _PanelMode.Reserved[0] = 0;
+ _PanelMode.Reserved[1] = 0;
+
+ info->PanelModesArray = &_PanelMode;
info->PanelModesNumber = 1;
*/
@@ -667,6 +680,11 @@ struct CArchiveItemProperty
VARTYPE Type;
};
+static inline char GetHex(Byte value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
HRESULT CPlugin::ShowAttributesWindow()
{
PluginPanelItem pluginPanelItem;
@@ -691,7 +709,7 @@ HRESULT CPlugin::ShowAttributesWindow()
prop.Type = vt;
prop.ID = propID;
if (prop.ID == kpidPath)
- prop.ID = kpidName;
+ prop.ID = kpidName;
prop.Name = GetNameOfProp(propID, name);
properties.Add(prop);
}
@@ -705,12 +723,16 @@ HRESULT CPlugin::ShowAttributesWindow()
initDialogItems.Add(idi);
AStringVector values;
+ const int kStartY = 3;
+
for (i = 0; i < properties.Size(); i++)
{
const CArchiveItemProperty &property = properties[i];
+ int startY = kStartY + values.Size();
+
CInitDialogItem idi =
- { DI_TEXT, 5, 3 + i, 0, 0, false, false, 0, false, 0, NULL, NULL };
+ { DI_TEXT, 5, startY, 0, 0, false, false, 0, false, 0, NULL, NULL };
idi.DataMessageId = FindPropNameID(property.ID);
if (idi.DataMessageId < 0)
idi.DataString = property.Name;
@@ -723,11 +745,91 @@ HRESULT CPlugin::ShowAttributesWindow()
{
CInitDialogItem idi =
- { DI_TEXT, 30, 3 + i, 0, 0, false, false, 0, false, -1, NULL, NULL };
+ { DI_TEXT, 30, startY, 0, 0, false, false, 0, false, -1, NULL, NULL };
initDialogItems.Add(idi);
}
}
+ CMyComPtr<IArchiveGetRawProps> _folderRawProps;
+ _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps);
+
+ CObjectVector<CArchiveItemProperty> properties2;
+
+ if (_folderRawProps)
+ {
+ _folderRawProps->GetNumRawProps(&numProps);
+
+ for (i = 0; i < numProps; i++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ if (_folderRawProps->GetRawPropInfo(i, &name, &propID) != S_OK)
+ continue;
+ CArchiveItemProperty prop;
+ prop.Type = VT_EMPTY;
+ prop.ID = propID;
+ if (prop.ID == kpidPath)
+ prop.ID = kpidName;
+ prop.Name = GetNameOfProp(propID, name);
+ properties2.Add(prop);
+ }
+
+ for (unsigned i = 0; i < properties2.Size(); i++)
+ {
+ const CArchiveItemProperty &property = properties2[i];
+ CMyComBSTR name;
+
+ const void *data;
+ UInt32 dataSize;
+ UInt32 propType;
+ if (_folderRawProps->GetRawProp(itemIndex, property.ID, &data, &dataSize, &propType) != S_OK)
+ continue;
+
+ if (dataSize != 0)
+ {
+ AString s;
+ if (property.ID == kpidNtSecure)
+ ConvertNtSecureToString((const Byte *)data, dataSize, s);
+ else
+ {
+ const UInt32 kMaxDataSize = 64;
+ if (dataSize > kMaxDataSize)
+ {
+ char temp[64];
+ s += "data:";
+ ConvertUInt32ToString(dataSize, temp);
+ s += temp;
+ }
+ else
+ {
+ for (UInt32 i = 0; i < dataSize; i++)
+ {
+ Byte b = ((const Byte *)data)[i];
+ s += GetHex((Byte)((b >> 4) & 0xF));
+ s += GetHex((Byte)(b & 0xF));
+ }
+ }
+ }
+
+ int startY = kStartY + values.Size();
+ CInitDialogItem idi =
+ { DI_TEXT, 5, startY, 0, 0, false, false, 0, false, 0, NULL, NULL };
+ idi.DataMessageId = FindPropNameID(property.ID);
+ if (idi.DataMessageId < 0)
+ idi.DataString = property.Name;
+ initDialogItems.Add(idi);
+
+ values.Add(s);
+
+ {
+ CInitDialogItem idi =
+ { DI_TEXT, 30, startY, 0, 0, false, false, 0, false, -1, NULL, NULL };
+ initDialogItems.Add(idi);
+ }
+ }
+ }
+ }
+
unsigned numLines = values.Size();
for (i = 0; i < numLines; i++)
{
@@ -741,6 +843,7 @@ HRESULT CPlugin::ShowAttributesWindow()
g_StartupInfo.InitDialogItems(&initDialogItems.Front(), dialogItems, numDialogItems);
unsigned maxLen = 0;
+
for (i = 0; i < numLines; i++)
{
FarDialogItem &dialogItem = dialogItems[1 + i * 2];
@@ -748,8 +851,10 @@ HRESULT CPlugin::ShowAttributesWindow()
if (len > maxLen)
maxLen = len;
}
+
unsigned maxLen2 = 0;
const unsigned kSpace = 10;
+
for (i = 0; i < numLines; i++)
{
FarDialogItem &dialogItem = dialogItems[1 + i * 2 + 1];
@@ -758,6 +863,7 @@ HRESULT CPlugin::ShowAttributesWindow()
maxLen2 = len;
dialogItem.X1 = maxLen + kSpace;
}
+
size = numLines + 6;
xSize = maxLen + kSpace + maxLen2 + 5;
FarDialogItem &firstDialogItem = dialogItems[0];
@@ -770,6 +876,12 @@ HRESULT CPlugin::ShowAttributesWindow()
int CPlugin::ProcessKey(int key, unsigned int controlState)
{
+ if (key == VK_F7 && controlState == 0)
+ {
+ CreateFolder();
+ return TRUE;
+ }
+
if (controlState == PKF_CONTROL && key == 'A')
{
HRESULT result = ShowAttributesWindow();
@@ -779,6 +891,7 @@ int CPlugin::ProcessKey(int key, unsigned int controlState)
return FALSE;
throw "Error";
}
+
if ((controlState & PKF_ALT) != 0 && key == VK_F6)
{
FString folderPath;
diff --git a/CPP/7zip/UI/Far/Plugin.h b/CPP/7zip/UI/Far/Plugin.h
index f01dc435..1fe190e4 100644
--- a/CPP/7zip/UI/Far/Plugin.h
+++ b/CPP/7zip/UI/Far/Plugin.h
@@ -5,13 +5,13 @@
#include "../../../Common/MyCom.h"
-#include "../../../Windows/COM.h"
+// #include "../../../Windows/COM.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/PropVariant.h"
#include "../Common/WorkDir.h"
-#include "../Agent/IFolderArchive.h"
+#include "../Agent/Agent.h"
#include "FarUtils.h"
@@ -19,10 +19,18 @@ const UInt32 kNumInfoLinesMax = 64;
class CPlugin
{
- NWindows::NCOM::CComInitializer m_ComInitializer;
+ CAgent *_agent;
+ CMyComPtr<IInFolderArchive> m_ArchiveHandler;
+ CMyComPtr<IFolderFolder> _folder;
+
+ // NWindows::NCOM::CComInitializer m_ComInitializer;
UString m_CurrentDir;
UString m_PannelTitle;
+ FString m_FileName;
+ NWindows::NFile::NFind::CFileInfo m_FileInfo;
+
+ UString _archiveTypeName;
InfoPanelLine m_InfoLines[kNumInfoLinesMax];
@@ -32,26 +40,20 @@ class CPlugin
AString PanelModeColumnTypes;
AString PanelModeColumnWidths;
- PanelMode PanelMode;
+ // PanelMode _PanelMode;
void AddColumn(PROPID aPropID);
void EnterToDirectory(const UString &dirName);
void GetPathParts(UStringVector &pathParts);
void SetCurrentDirVar();
- HRESULT AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector);
-public:
- FString m_FileName;
- NWindows::NFile::NFind::CFileInfo m_FileInfo;
+ // HRESULT AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector);
- CMyComPtr<IInFolderArchive> m_ArchiveHandler;
- CMyComPtr<IFolderFolder> _folder;
-
- UString _archiveTypeName;
+public:
bool PasswordIsDefined;
UString Password;
- CPlugin(const FString &fileName, IInFolderArchive *archiveHandler, UString archiveTypeName);
+ CPlugin(const FString &fileName, CAgent *agent, UString archiveTypeName);
~CPlugin();
void ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex);
@@ -80,6 +82,7 @@ public:
NFar::NFileOperationReturnCode::EEnum PutFiles(struct PluginPanelItem *panelItems, int itemsNumber,
int move, int opMode);
+ HRESULT CreateFolder();
HRESULT ShowAttributesWindow();
diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp
index 1adf91a7..e1a103ac 100644
--- a/CPP/7zip/UI/Far/PluginDelete.cpp
+++ b/CPP/7zip/UI/Far/PluginDelete.cpp
@@ -14,13 +14,11 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode)
{
if (numItems == 0)
return FALSE;
- /*
- if (!m_ArchiverInfo.UpdateEnabled)
+ if (_agent->IsThereReadOnlyArc())
{
g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
return FALSE;
}
- */
if ((opMode & OPM_SILENT) == 0)
{
const char *msgItems[]=
@@ -55,21 +53,21 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode)
progressBoxPointer = &progressBox;
progressBox.Init(
// g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
- g_StartupInfo.GetMsgString(NMessageID::kDeleting), 48);
+ g_StartupInfo.GetMsgString(NMessageID::kDeleting));
}
+ /*
CWorkDirTempFile tempFile;
if (tempFile.CreateTempFile(m_FileName) != S_OK)
return FALSE;
+ */
CObjArray<UInt32> indices(numItems);
int i;
for (i = 0; i < numItems; i++)
indices[i] = (UInt32)panelItems[i].UserData;
- ////////////////////////////
- // Save _folder;
-
+ /*
UStringVector pathVector;
GetPathParts(pathVector);
@@ -80,13 +78,15 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode)
g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
return FALSE;
}
- outArchive->SetFolder(_folder);
+ */
CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec);
updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer);
+ /*
+ outArchive->SetFolder(_folder);
result = outArchive->DeleteItems(tempFile.OutStream, indices, numItems, updateCallback);
updateCallback.Release();
outArchive.Release();
@@ -95,11 +95,24 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode)
{
result = AfterUpdate(tempFile, pathVector);
}
+ */
+
+ HRESULT result;
+ {
+ CMyComPtr<IFolderOperations> folderOperations;
+ result = _folder.QueryInterface(IID_IFolderOperations, &folderOperations);
+ if (folderOperations)
+ result = folderOperations->Delete(indices, numItems, updateCallback);
+ else if (result != S_OK)
+ result = E_FAIL;
+ }
+
if (result != S_OK)
{
- ShowErrorMessage(result);
+ ShowSysErrorMessage(result);
return FALSE;
}
+
SetCurrentDirVar();
return TRUE;
}
diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp
index 6e77a9d5..433e8140 100644
--- a/CPP/7zip/UI/Far/PluginRead.cpp
+++ b/CPP/7zip/UI/Far/PluginRead.cpp
@@ -47,11 +47,11 @@ HRESULT CPlugin::ExtractFiles(
progressBoxPointer = &progressBox;
progressBox.Init(
// g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
- g_StartupInfo.GetMsgString(NMessageID::kExtracting), 48);
+ g_StartupInfo.GetMsgString(NMessageID::kExtracting));
}
- CExtractCallBackImp *extractCallbackSpec = new CExtractCallBackImp;
+ CExtractCallbackImp *extractCallbackSpec = new CExtractCallbackImp;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback(extractCallbackSpec);
extractCallbackSpec->Init(
@@ -100,7 +100,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa
NName::NormalizeDirPathPrefix(destPathU);
destPath = UnicodeStringToMultiByte(destPathU, CP_OEMCP);
- bool extractSelectedFiles = true;
+ // bool extractSelectedFiles = true;
NExtract::CInfo extractionInfo;
extractionInfo.PathMode = NExtract::NPathMode::kCurPaths;
@@ -211,7 +211,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa
if (destPathU.Back() == kDirDelimiter)
break;
}
- g_StartupInfo.ShowMessage("You must specify directory path");
+ g_StartupInfo.ShowErrorMessage("You must specify directory path");
}
if (dialogItems[kPathModeRadioIndex].Selected)
@@ -246,9 +246,13 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa
extractionInfo.Save();
if (dialogItems[kFilesModeIndex].Selected)
- extractSelectedFiles = true;
+ {
+ // extractSelectedFiles = true;
+ }
else if (dialogItems[kFilesModeIndex + 1].Selected)
- extractSelectedFiles = false;
+ {
+ // extractSelectedFiles = false;
+ }
else
throw 31806;
@@ -278,7 +282,7 @@ NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *pa
{
if (result == E_ABORT)
return NFileOperationReturnCode::kInterruptedByUser;
- ShowErrorMessage(result);
+ ShowSysErrorMessage(result);
return NFileOperationReturnCode::kError;
}
diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp
index e36f3911..8afba039 100644
--- a/CPP/7zip/UI/Far/PluginWrite.cpp
+++ b/CPP/7zip/UI/Far/PluginWrite.cpp
@@ -49,6 +49,7 @@ static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UInt32 method)
return S_OK;
}
+/*
HRESULT CPlugin::AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector)
{
_folder.Release();
@@ -69,26 +70,28 @@ HRESULT CPlugin::AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pa
}
return S_OK;
}
+*/
NFileOperationReturnCode::EEnum CPlugin::PutFiles(
struct PluginPanelItem *panelItems, int numItems,
int moveMode, int opMode)
{
+ /*
if (moveMode != 0)
{
g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);
return NFileOperationReturnCode::kError;
}
+ */
+
if (numItems == 0)
return NFileOperationReturnCode::kError;
- /*
- if (!m_ArchiverInfo.UpdateEnabled)
+ if (_agent->IsThereReadOnlyArc())
{
g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
return NFileOperationReturnCode::kError;
}
- */
const int kYSize = 14;
const int kXMid = 38;
@@ -184,7 +187,7 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
progressBoxPointer = &progressBox;
progressBox.Init(
// g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
- g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48);
+ g_StartupInfo.GetMsgString(NMessageID::kUpdating));
}
UStringVector pathVector;
@@ -205,12 +208,12 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
return NFileOperationReturnCode::kError;
}
- outArchive->SetFolder(_folder);
- outArchive->SetFiles(L"", fileNamePointers, numItems);
+ /*
BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];
for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSetByte[i] = (BYTE)actionSet->StateActions[i];
+ */
CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
@@ -220,6 +223,9 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK)
return NFileOperationReturnCode::kError;
+ /*
+ outArchive->SetFolder(_folder);
+ outArchive->SetFiles(L"", fileNamePointers, numItems);
// FStringVector requestedPaths;
// FStringVector processedPaths;
result = outArchive->DoOperation2(
@@ -233,28 +239,33 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
{
result = AfterUpdate(tempFile, pathVector);
}
- if (result != S_OK)
- {
- ShowErrorMessage(result);
- return NFileOperationReturnCode::kError;
- }
+ */
- /*
- if (moveMode != 0)
{
- for (int i = 0; i < numItems; i++)
+ result = _agent->SetFiles(L"", fileNamePointers, numItems);
+ if (result == S_OK)
{
- const PluginPanelItem &pluginPanelItem = panelItems[i];
- bool result;
- if (NFile::NFind::NAttributes::IsDir(pluginPanelItem.FindData.dwFileAttributes))
- result = NFile::NDirectory::RemoveDirectoryWithSubItems(pluginPanelItem.FindData.cFileName);
+ CAgentFolder *agentFolder = NULL;
+ {
+ CMyComPtr<IArchiveFolderInternal> afi;
+ _folder.QueryInterface(IID_IArchiveFolderInternal, &afi);
+ if (afi)
+ afi->GetAgentFolder(&agentFolder);
+ }
+ if (agentFolder)
+ result = agentFolder->CommonUpdateOperation(AGENT_OP_Uni,
+ (moveMode != 0), NULL, actionSet, NULL, 0, updateCallback);
else
- result = NFile::NDirectory::DeleteFileAlways(pluginPanelItem.FindData.cFileName);
- if (!result)
- return NFileOperationReturnCode::kError;
+ result = E_FAIL;
}
}
- */
+
+ if (result != S_OK)
+ {
+ ShowSysErrorMessage(result);
+ return NFileOperationReturnCode::kError;
+ }
+
return NFileOperationReturnCode::kSuccess;
}
@@ -335,11 +346,18 @@ UString CParsedPath::MergePath() const
}
-/*
-// {23170F69-40C1-278A-1000-000100030000}
-DEFINE_GUID(CLSID_CAgentArchiveHandler,
- 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00);
-*/
+static void SetArcName(UString &arcName, const CArcInfoEx &arcInfo)
+{
+ if (!arcInfo.Flags_KeepName())
+ {
+ int dotPos = arcName.ReverseFind_Dot();
+ int slashPos = arcName.ReverseFind_PathSepar();
+ if (dotPos > slashPos + 1)
+ arcName.DeleteFrom(dotPos);
+ }
+ arcName += L'.';
+ arcName += arcInfo.GetMainExt();
+}
HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
{
@@ -368,12 +386,20 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
NCompression::CInfo compressionInfo;
compressionInfo.Load();
- int archiverIndex = 0;
+ int archiverIndex = -1;
+ /*
CCodecs *codecs = new CCodecs;
CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs;
if (codecs->Load() != S_OK)
throw "Can't load 7-Zip codecs";
+ */
+
+ if (LoadGlobalCodecs() != S_OK)
+ throw "Can't load 7-Zip codecs";
+
+ CCodecs *codecs = g_CodecsObj;
+
{
FOR_VECTOR (i, codecs->Formats)
{
@@ -388,6 +414,8 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
}
}
+ if (archiverIndex < 0)
+ throw "there is no output handler";
UString resultPath;
{
@@ -407,26 +435,18 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
}
}
UString archiveNameSrc = resultPath;
- UString archiveName = archiveNameSrc;
+ UString arcName = archiveNameSrc;
const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];
int prevFormat = archiverIndex;
- if (!arcInfo.Flags_KeepName())
- {
- int dotPos = archiveName.ReverseFind('.');
- int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/'));
- if (dotPos > slashPos)
- archiveName = archiveName.Left(dotPos);
- }
- archiveName += L'.';
- archiveName += arcInfo.GetMainExt();
+ SetArcName(arcName, arcInfo);
const CActionSet *actionSet = &k_ActionSet_Add;
for (;;)
{
- AString archiveNameA = UnicodeStringToMultiByte(archiveName, CP_OEMCP);
+ AString archiveNameA = UnicodeStringToMultiByte(arcName, CP_OEMCP);
const int kYSize = 16;
const int kXMid = 38;
@@ -458,7 +478,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
{ DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL },
{ DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName},
- // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, archiveName, NULL},
+ // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, arcName, NULL},
{ DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL },
@@ -495,7 +515,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
archiveNameA = dialogItems[kArchiveNameIndex].Data;
archiveNameA.Trim();
- archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP);
+ MultiByteToUnicodeString2(arcName, archiveNameA, CP_OEMCP);
compressionInfo.Level = g_MethodMap[0];
for (i = 0; i < ARRAY_SIZE(g_MethodMap); i++)
@@ -532,15 +552,14 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
{
const UString &prevExtension = prevArchiverInfo.GetMainExt();
const unsigned prevExtensionLen = prevExtension.Len();
- if (archiveName.Len() >= prevExtensionLen &&
- MyStringCompareNoCase(archiveName.RightPtr(prevExtensionLen), prevExtension) == 0)
+ if (arcName.Len() >= prevExtensionLen &&
+ MyStringCompareNoCase(arcName.RightPtr(prevExtensionLen), prevExtension) == 0)
{
- int pos = archiveName.Len() - prevExtensionLen;
- if (pos > 1)
+ int pos = arcName.Len() - prevExtensionLen;
+ if (pos > 2)
{
- int dotPos = archiveName.ReverseFind('.');
- if (dotPos == pos - 1)
- archiveName = archiveName.Left(dotPos);
+ if (arcName[pos - 1] == '.')
+ arcName.DeleteFrom(pos - 1);
}
}
}
@@ -550,16 +569,8 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
prevFormat = archiverIndex;
if (arcInfo.Flags_KeepName())
- archiveName = archiveNameSrc;
- else
- {
- int dotPos = archiveName.ReverseFind('.');
- int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/'));
- if (dotPos > slashPos)
- archiveName = archiveName.Left(dotPos);
- }
- archiveName += L'.';
- archiveName += arcInfo.GetMainExt();
+ arcName = archiveNameSrc;
+ SetArcName(arcName, arcInfo);
}
continue;
}
@@ -577,12 +588,12 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
NWorkDir::CInfo workDirInfo;
workDirInfo.Load();
- FString fullArchiveName;
- if (!MyGetFullPathName(us2fs(archiveName), fullArchiveName))
+ FString fullArcName;
+ if (!MyGetFullPathName(us2fs(arcName), fullArcName))
return E_FAIL;
CWorkDirTempFile tempFile;
- RINOK(tempFile.CreateTempFile(fullArchiveName));
+ RINOK(tempFile.CreateTempFile(fullArcName));
CScreenRestorer screenRestorer;
CProgressBox progressBox;
@@ -593,7 +604,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
progressBoxPointer = &progressBox;
progressBox.Init(
// g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
- g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48);
+ g_StartupInfo.GetMsgString(NMessageID::kUpdating));
NFind::CFileInfo fileInfo;
@@ -601,7 +612,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
CMyComPtr<IOutFolderArchive> outArchive;
CMyComPtr<IInFolderArchive> archiveHandler;
- if (fileInfo.Find(fullArchiveName))
+ if (fileInfo.Find(fullArcName))
{
if (fileInfo.IsDir())
throw "There is Directory with such name";
@@ -611,7 +622,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
// CLSID realClassID;
CMyComBSTR archiveType;
RINOK(agentSpec->Open(NULL,
- GetUnicodeString(fullArchiveName, CP_OEMCP), UString(),
+ GetUnicodeString(fullArcName, CP_OEMCP), UString(),
// &realClassID,
&archiveType,
NULL));
@@ -675,7 +686,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
if (result != S_OK)
{
- ShowErrorMessage(result);
+ ShowSysErrorMessage(result);
return result;
}
@@ -687,8 +698,122 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
result = tempFile.MoveToOriginal(archiveHandler != NULL);
if (result != S_OK)
{
- ShowErrorMessage(result);
+ ShowSysErrorMessage(result);
+ return result;
+ }
+ return S_OK;
+}
+
+
+static const char *k_CreateFolder_History = "NewFolder"; // we use default FAR folder name
+
+HRESULT CPlugin::CreateFolder()
+{
+ if (_agent->IsThereReadOnlyArc())
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
+ return TRUE;
+ }
+
+ UString destPathU;
+ {
+ const int kXSize = 60;
+ const int kYSize = 8;
+ const int kPathIndex = 2;
+
+ AString destPath = "New Folder";
+
+ const struct CInitDialogItem initItems[]={
+ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false,
+ -1, "Create Folder", NULL },
+
+ { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, "Folder name:", NULL },
+
+ { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, DIF_HISTORY, false, -1, destPath, k_CreateFolder_History },
+
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kOk, NULL, NULL },
+ { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL }
+ };
+
+ const int kNumDialogItems = ARRAY_SIZE(initItems);
+ const int kOkButtonIndex = kNumDialogItems - 2;
+
+ FarDialogItem dialogItems[kNumDialogItems];
+ g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
+ for (;;)
+ {
+ int askCode = g_StartupInfo.ShowDialog(kXSize, kYSize,
+ NULL, // kHelpTopic
+ dialogItems, kNumDialogItems);
+ if (askCode != kOkButtonIndex)
+ return E_ABORT;
+ destPath = dialogItems[kPathIndex].Data;
+ destPathU = GetUnicodeString(destPath, CP_OEMCP);
+ destPathU.Trim();
+ if (!destPathU.IsEmpty())
+ break;
+ g_StartupInfo.ShowErrorMessage("You must specify folder name");
+ }
+
+ }
+
+ CScreenRestorer screenRestorer;
+ CProgressBox progressBox;
+ CProgressBox *progressBoxPointer = NULL;
+ // if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
+ {
+ screenRestorer.Save();
+
+ progressBoxPointer = &progressBox;
+ progressBox.Init(
+ // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
+ g_StartupInfo.GetMsgString(NMessageID::kDeleting));
+ }
+
+ CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
+ CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+
+ updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer);
+
+ HRESULT result;
+ {
+ CMyComPtr<IFolderOperations> folderOperations;
+ result = _folder.QueryInterface(IID_IFolderOperations, &folderOperations);
+ if (folderOperations)
+ result = folderOperations->CreateFolder(destPathU, updateCallback);
+ else if (result != S_OK)
+ result = E_FAIL;
+ }
+
+ if (result != S_OK)
+ {
+ ShowSysErrorMessage(result);
return result;
}
+
+ g_StartupInfo.Control(this, FCTL_UPDATEPANEL, (void *)1);
+ g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL);
+
+ PanelInfo panelInfo;
+
+ if (g_StartupInfo.ControlGetActivePanelInfo(panelInfo))
+ {
+ AString destPath = GetOemString(destPathU);
+
+ for (int i = 0; i < panelInfo.ItemsNumber; i++)
+ {
+ const PluginPanelItem &pi = panelInfo.PanelItems[i];
+ if (strcmp(destPath, pi.FindData.cFileName) == 0)
+ {
+ PanelRedrawInfo panelRedrawInfo;
+ panelRedrawInfo.CurrentItem = i;
+ panelRedrawInfo.TopPanelItem = 0;
+ g_StartupInfo.Control(this, FCTL_REDRAWPANEL, &panelRedrawInfo);
+ break;
+ }
+ }
+ }
+
+ SetCurrentDirVar();
return S_OK;
}
diff --git a/CPP/7zip/UI/Far/ProgressBox.cpp b/CPP/7zip/UI/Far/ProgressBox.cpp
index 3ad0560a..75467864 100644
--- a/CPP/7zip/UI/Far/ProgressBox.cpp
+++ b/CPP/7zip/UI/Far/ProgressBox.cpp
@@ -2,112 +2,305 @@
#include "StdAfx.h"
-#include <stdio.h>
-
#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
#include "FarUtils.h"
#include "ProgressBox.h"
-static void CopySpaces(char *dest, int numSpaces)
+void CPercentPrinterState::ClearCurState()
{
- int i;
- for (i = 0; i < numSpaces; i++)
- dest[i] = ' ';
- dest[i] = '\0';
+ Completed = 0;
+ Total = ((UInt64)(Int64)-1);
+ Files = 0;
+ FilesTotal = 0;
+ Command.Empty();
+ FileName.Empty();
}
-void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize)
+void CProgressBox::Init(const AString &title)
{
- char temp[32];
- ConvertUInt64ToString(value, temp);
- int len = (int)strlen(temp);
- int numSpaces = 0;
- if (len < alignSize)
+ _title = title;
+ _wasPrinted = false;
+ StartTick = GetTickCount();
+ _prevTick = StartTick;
+ _prevElapsedSec = 0;
+}
+
+static unsigned GetPower32(UInt32 val)
+{
+ const unsigned kStart = 32;
+ UInt32 mask = ((UInt32)1 << (kStart - 1));
+ for (unsigned i = kStart;; i--)
{
- numSpaces = alignSize - len;
- CopySpaces(s, numSpaces);
+ if (i == 0 || (val & mask) != 0)
+ return i;
+ mask >>= 1;
}
- strcpy(s + numSpaces, temp);
}
+static unsigned GetPower64(UInt64 val)
+{
+ UInt32 high = (UInt32)(val >> 32);
+ if (high == 0)
+ return GetPower32((UInt32)val);
+ return GetPower32(high) + 32;
+}
-// ---------- CMessageBox ----------
+static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider)
+{
+ unsigned pow1 = GetPower64(mult1);
+ unsigned pow2 = GetPower64(mult2);
+ while (pow1 + pow2 > 64)
+ {
+ if (pow1 > pow2) { pow1--; mult1 >>= 1; }
+ else { pow2--; mult2 >>= 1; }
+ divider >>= 1;
+ }
+ UInt64 res = mult1 * mult2;
+ if (divider != 0)
+ res /= divider;
+ return res;
+}
-static const int kMaxLen = 255;
+#define UINT_TO_STR_2(val) { s[0] = (char)('0' + (val) / 10); s[1] = (char)('0' + (val) % 10); s += 2; }
-void CMessageBox::Init(const AString &title, int width)
+static void GetTimeString(UInt64 timeValue, char *s)
{
- _title = title;
- _width = MyMin(width, kMaxLen);
+ UInt64 hours = timeValue / 3600;
+ UInt32 seconds = (UInt32)(timeValue - hours * 3600);
+ UInt32 minutes = seconds / 60;
+ seconds %= 60;
+ if (hours > 99)
+ {
+ ConvertUInt64ToString(hours, s);
+ for (; *s != 0; s++);
+ }
+ else
+ {
+ UInt32 hours32 = (UInt32)hours;
+ UINT_TO_STR_2(hours32);
+ }
+ *s++ = ':'; UINT_TO_STR_2(minutes);
+ *s++ = ':'; UINT_TO_STR_2(seconds);
+ *s = 0;
+}
+
+void CProgressBox::ReduceString(const UString &src, AString &dest)
+{
+ UnicodeStringToMultiByte2(dest, src, CP_OEMCP);
+
+ if (dest.Len() <= MaxLen)
+ return;
+ unsigned len = FileName.Len();
+ for (; len != 0;)
+ {
+ unsigned delta = len / 8;
+ if (delta == 0)
+ delta = 1;
+ len -= delta;
+ _tempU = FileName;
+ _tempU.Delete(len / 2, FileName.Len() - len);
+ _tempU.Insert(len / 2, L" . ");
+ UnicodeStringToMultiByte2(dest, _tempU, CP_OEMCP);
+ if (dest.Len() <= MaxLen)
+ return;
+ }
+ dest.Empty();
+}
+
+static void Print_UInt64_and_String(AString &s, UInt64 val, const char *name)
+{
+ char temp[32];
+ ConvertUInt64ToString(val, temp);
+ s += temp;
+ s.Add_Space();
+ s += name;
}
-void CMessageBox::ShowMessages(const char *strings[], int numStrings)
+
+static void PrintSize_bytes_Smart(AString &s, UInt64 val)
{
- const int kNumStaticStrings = 1;
- const int kNumStringsMax = 10;
+ // Print_UInt64_and_String(s, val, "bytes");
+ {
+ char temp[32];
+ ConvertUInt64ToString(val, temp);
+ s += temp;
+ }
- if (numStrings > kNumStringsMax)
- numStrings = kNumStringsMax;
+ if (val == 0)
+ return;
+
+ unsigned numBits = 10;
+ char c = 'K';
+ char temp[4] = { 'K', 'i', 'B', 0 };
+ if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; }
+ else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; }
+ temp[0] = c;
+ s += " (";
+ Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);
+ s += ')';
+}
- const char *msgItems[kNumStaticStrings + kNumStringsMax];
- msgItems[0] = _title;
- char formattedMessages[kNumStringsMax][kMaxLen + 1];
+static const unsigned kPercentsSize = 4;
- for (int i = 0; i < numStrings; i++)
+void CProgressBox::Print()
+{
+ DWORD tick = GetTickCount();
+ DWORD elapsedTicks = tick - StartTick;
+ DWORD elapsedSec = elapsedTicks / 1000;
+
+ if (_wasPrinted)
{
- char *formattedMessage = formattedMessages[i];
- const char *s = strings[i];
- int len = (int)strlen(s);
- if (len < kMaxLen)
+ if (elapsedSec == _prevElapsedSec)
{
- int size = MyMax(_width, len);
- int startPos = (size - len) / 2;
- CopySpaces(formattedMessage, startPos);
- strcpy(formattedMessage + startPos, s);
- CopySpaces(formattedMessage + startPos + len, size - startPos - len);
+ if ((UInt32)(tick - _prevTick) < _tickStep)
+ return;
+ if (_printedState.IsEqualTo((const CPercentPrinterState &)*this))
+ return;
}
- else
+ }
+
+ UInt64 cur = Completed;
+ UInt64 total = Total;
+
+ if (!UseBytesForPercents)
+ {
+ cur = Files;
+ total = FilesTotal;
+ }
+
+ {
+ _timeStr.Empty();
+ _timeStr = "Elapsed time: ";
+ char s[40];
+ GetTimeString(elapsedSec, s);
+ _timeStr += s;
+
+ if (cur != 0)
{
- strncpy(formattedMessage, s, kMaxLen);
- formattedMessage[kMaxLen] = 0;
+ UInt64 remainingTime = 0;
+ if (cur < total)
+ remainingTime = MyMultAndDiv(elapsedTicks, total - cur, cur);
+ UInt64 remainingSec = remainingTime / 1000;
+ _timeStr += " Remaining time: ";
+
+ GetTimeString(remainingSec, s);
+ _timeStr += s;
}
- msgItems[kNumStaticStrings + i] = formattedMessage;
}
- NFar::g_StartupInfo.ShowMessage(0, NULL, msgItems, kNumStaticStrings + numStrings, 0);
-}
-// ---------- CProgressBox ----------
+ {
+ _perc.Empty();
+ char s[32];
+ unsigned size;
+ {
+ UInt64 val = 0;
+ if (total != (UInt64)(Int64)-1 && total != 0)
+ val = cur * 100 / Total;
+
+ ConvertUInt64ToString(val, s);
+ size = (unsigned)strlen(s);
+ s[size++] = '%';
+ s[size] = 0;
+ }
+
+ unsigned len = size;
+ while (len < kPercentsSize)
+ len = kPercentsSize;
+ len++;
+
+ if (len < MaxLen)
+ {
+ unsigned numChars = MaxLen - len;
+ unsigned filled = 0;
+ if (total != (UInt64)(Int64)-1 && total != 0)
+ filled = (unsigned)(cur * numChars / total);
+ unsigned i = 0;
+ if (filled < numChars)
+ {
+ for (i = 0; i < filled; i++)
+ _perc += '=';
+ }
+ for (; i < numChars; i++)
+ _perc += '.';
+ }
+
+ _perc.Add_Space();
+ while (size < kPercentsSize)
+ {
+ _perc.Add_Space();
+ size++;
+ }
+ _perc += s;
+ }
-void CProgressBox::Init(const AString &title, int width)
-{
- CMessageBox::Init(title, width);
- _prevMessage.Empty();
- _prevPercentMessage.Empty();
- _wasShown = false;
-}
+ _files.Empty();
+ if (Files != 0 || FilesTotal != 0)
+ {
+ _files += "Files: ";
+ char s[32];
+ // if (Files != 0)
+ {
+ ConvertUInt64ToString(Files, s);
+ _files += s;
+ }
+ if (FilesTotal != 0)
+ {
+ _files += " / ";
+ ConvertUInt64ToString(FilesTotal, s);
+ _files += s;
+ }
+ }
-void CProgressBox::Progress(const UInt64 *total, const UInt64 *completed, const AString &message)
-{
- AString percentMessage;
- if (total != 0 && completed != 0)
+ _sizesStr.Empty();
+ if (Total != 0)
+ {
+ _sizesStr += "Size: ";
+ PrintSize_bytes_Smart(_sizesStr, Completed);
+ if (Total != 0 && Total != (UInt64)(Int64)-1)
+ {
+ _sizesStr += " / ";
+ PrintSize_bytes_Smart(_sizesStr, Total);
+ }
+ }
+
+ _name1.Empty();
+ _name2.Empty();
+
+ if (!FileName.IsEmpty())
{
- UInt64 totalVal = *total;
- if (totalVal == 0)
- totalVal = 1;
- char buf[32];
- ConvertUInt64ToStringAligned(*completed * 100 / totalVal, buf, 3);
- strcat(buf, "%");
- percentMessage = buf;
+ _name1U.Empty();
+ _name2U.Empty();
+
+ /*
+ if (_isDir)
+ s1 = _filePath;
+ else
+ */
+ {
+ int slashPos = FileName.ReverseFind_PathSepar();
+ if (slashPos >= 0)
+ {
+ _name1U.SetFrom(FileName, slashPos + 1);
+ _name2U = FileName.Ptr(slashPos + 1);
+ }
+ else
+ _name2U = FileName;
+ }
+ ReduceString(_name1U, _name1);
+ ReduceString(_name2U, _name2);
}
- if (message != _prevMessage || percentMessage != _prevPercentMessage || !_wasShown)
+
{
- _prevMessage = message;
- _prevPercentMessage = percentMessage;
- const char *strings[] = { message, percentMessage };
- ShowMessages(strings, ARRAY_SIZE(strings));
- _wasShown = true;
+ const char *strings[] = { _title, _timeStr, _files, _sizesStr, Command, _name1, _name2, _perc };
+ NFar::g_StartupInfo.ShowMessage(FMSG_LEFTALIGN, NULL, strings, ARRAY_SIZE(strings), 0);
}
+
+ _wasPrinted = true;
+ _printedState = *this;
+ _prevTick = tick;
+ _prevElapsedSec = elapsedSec;
}
diff --git a/CPP/7zip/UI/Far/ProgressBox.h b/CPP/7zip/UI/Far/ProgressBox.h
index 9c26763d..83731b38 100644
--- a/CPP/7zip/UI/Far/ProgressBox.h
+++ b/CPP/7zip/UI/Far/ProgressBox.h
@@ -6,25 +6,78 @@
#include "../../../Common/MyString.h"
#include "../../../Common/MyTypes.h"
-void ConvertUInt64ToStringAligned(UInt64 value, char *s, int alignSize);
-
-class CMessageBox
+struct CPercentPrinterState
{
- AString _title;
- int _width;
-public:
- void Init(const AString &title, int width);
- void ShowMessages(const char *strings[], int numStrings);
+ UInt64 Completed;
+ UInt64 Total;
+
+ UInt64 Files;
+ UInt64 FilesTotal;
+
+ AString Command;
+ UString FileName;
+
+ void ClearCurState();
+
+ bool IsEqualTo(const CPercentPrinterState &s) const
+ {
+ return
+ Completed == s.Completed
+ && Total == s.Total
+ && Files == s.Files
+ && FilesTotal == s.FilesTotal
+ && Command == s.Command
+ && FileName == s.FileName;
+ }
+
+ CPercentPrinterState():
+ Completed(0),
+ Total((UInt64)(Int64)-1),
+ Files(0),
+ FilesTotal(0)
+ {}
};
-class CProgressBox: public CMessageBox
+class CProgressBox: public CPercentPrinterState
{
- AString _prevMessage;
- AString _prevPercentMessage;
- bool _wasShown;
+ UInt32 _tickStep;
+ DWORD _prevTick;
+ DWORD _prevElapsedSec;
+
+ bool _wasPrinted;
+
+ UString _tempU;
+ UString _name1U;
+ UString _name2U;
+
+ CPercentPrinterState _printedState;
+
+ AString _title;
+
+ AString _timeStr;
+ AString _files;
+ AString _sizesStr;
+ AString _name1;
+ AString _name2;
+ AString _perc;
+
+ void ReduceString(const UString &src, AString &dest);
+
public:
- void Init(const AString &title, int width);
- void Progress(const UInt64 *total, const UInt64 *completed, const AString &message);
+ DWORD StartTick;
+ bool UseBytesForPercents;
+ unsigned MaxLen;
+
+ CProgressBox(UInt32 tickStep = 200):
+ _tickStep(tickStep),
+ _prevTick(0),
+ StartTick(0),
+ UseBytesForPercents(true),
+ MaxLen(60)
+ {}
+
+ void Init(const AString &title);
+ void Print();
};
#endif
diff --git a/CPP/7zip/UI/Far/UpdateCallbackFar.cpp b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp
index f2877888..18d1a2c9 100644
--- a/CPP/7zip/UI/Far/UpdateCallbackFar.cpp
+++ b/CPP/7zip/UI/Far/UpdateCallbackFar.cpp
@@ -2,59 +2,206 @@
#include "StdAfx.h"
+#ifndef _7ZIP_ST
+#include "../../../Windows/Synchronization.h"
+#endif
+
#include "../../../Common/StringConvert.h"
#include "FarUtils.h"
#include "UpdateCallbackFar.h"
+using namespace NWindows;
using namespace NFar;
-STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 /* numFiles */)
+#ifndef _7ZIP_ST
+static NSynchronization::CCriticalSection g_CriticalSection;
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+#define MT_LOCK
+#endif
+
+static HRESULT CheckBreak2()
+{
+ return WasEscPressed() ? E_ABORT : S_OK;
+}
+
+
+STDMETHODIMP CUpdateCallback100Imp::ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 /* isDir */)
+{
+ MT_LOCK
+
+ if (_percent)
+ {
+ _percent->FilesTotal = numFolders + numFiles;
+ _percent->Total = totalSize;
+ _percent->Command = "Scanning";
+ _percent->FileName = path;
+ _percent->Print();
+ _percent->Print();
+ }
+ return CheckBreak2();
+}
+
+STDMETHODIMP CUpdateCallback100Imp::ScanError(const wchar_t *path, HRESULT errorCode)
{
- return S_OK;
+ if (ShowSysErrorMessage(errorCode, path) == -1)
+ return E_ABORT;
+ return CheckBreak2();
+}
+
+STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles)
+{
+ MT_LOCK
+
+ if (_percent)
+ {
+ _percent->FilesTotal = numFiles;
+ _percent->Print();
+ }
+ return CheckBreak2();
}
STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size)
{
- _total = size;
- return S_OK;
+ MT_LOCK
+
+ if (_percent)
+ {
+ _percent->Total = size;
+ _percent->Print();
+ }
+ return CheckBreak2();
}
STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completeValue)
{
- if (WasEscPressed())
- return E_ABORT;
- if (_progressBox != 0)
- _progressBox->Progress(&_total, completeValue, AString());
- return S_OK;
+ MT_LOCK
+
+ if (_percent)
+ {
+ if (completeValue)
+ _percent->Completed = *completeValue;
+ _percent->Print();
+ }
+ return CheckBreak2();
}
-STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t* /* name */)
+STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name)
{
- return S_OK;
+ MT_LOCK
+
+ if (_percent)
+ {
+ _percent->Command = "Adding";
+ _percent->FileName = name;
+ _percent->Print();
+ }
+ return CheckBreak2();;
}
-STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t* /* name */)
+STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name)
{
- return S_OK;
+ MT_LOCK
+
+ if (_percent)
+ {
+ _percent->Command = "Deleting";
+ _percent->FileName = name;
+ _percent->Print();
+ }
+ return CheckBreak2();;
}
STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* opRes */)
{
- return S_OK;
+ MT_LOCK
+
+ if (_percent)
+ {
+ _percent->Files++;
+ }
+ return CheckBreak2();
}
STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message)
{
- if (g_StartupInfo.ShowMessage(UnicodeStringToMultiByte(message, CP_OEMCP)) == -1)
+ MT_LOCK
+
+ if (g_StartupInfo.ShowErrorMessage(UnicodeStringToMultiByte(message, CP_OEMCP)) == -1)
+ return E_ABORT;
+ return CheckBreak2();
+}
+
+HRESULT CUpdateCallback100Imp::OpenFileError(const wchar_t *path, HRESULT errorCode)
+{
+ if (ShowSysErrorMessage(errorCode, path) == -1)
+ return E_ABORT;
+ return CheckBreak2();
+}
+
+STDMETHODIMP CUpdateCallback100Imp::ReadingFileError(const wchar_t *path, HRESULT errorCode)
+{
+ if (ShowSysErrorMessage(errorCode, path) == -1)
return E_ABORT;
- return S_OK;
+ return CheckBreak2();
}
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &s);
+
+STDMETHODIMP CUpdateCallback100Imp::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
+{
+ MT_LOCK
+
+ if (opRes != NArchive::NExtract::NOperationResult::kOK)
+ {
+ AString s;
+ SetExtractErrorMessage(opRes, isEncrypted, s);
+ if (PrintErrorMessage(s, name) == -1)
+ return E_ABORT;
+ }
+
+ return CheckBreak2();
+}
+
+
+STDMETHODIMP CUpdateCallback100Imp::ReportUpdateOperation(UInt32 op, const wchar_t *name, Int32 /* isDir */)
+{
+ const char *s;
+ switch (op)
+ {
+ case NUpdateNotifyOp::kAdd: s = "Adding"; break;
+ case NUpdateNotifyOp::kUpdate: s = "Updating"; break;
+ case NUpdateNotifyOp::kAnalyze: s = "Analyzing"; break;
+ case NUpdateNotifyOp::kReplicate: s = "Replicating"; break;
+ case NUpdateNotifyOp::kRepack: s = "Repacking"; break;
+ case NUpdateNotifyOp::kSkip: s = "Skipping"; break;
+ case NUpdateNotifyOp::kHeader: s = "Header creating"; break;
+ case NUpdateNotifyOp::kDelete: s = "Deleting"; break;
+ default: s = "Unknown operation";
+ }
+
+ MT_LOCK
+
+ if (_percent)
+ {
+ _percent->Command = s;
+ _percent->FileName.Empty();
+ if (name)
+ _percent->FileName = name;
+ _percent->Print();
+ }
+
+ return CheckBreak2();;
+}
+
+
extern HRESULT GetPassword(UString &password);
STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)
{
+ MT_LOCK
+
*password = NULL;
if (!m_PasswordIsDefined)
{
diff --git a/CPP/7zip/UI/Far/UpdateCallbackFar.h b/CPP/7zip/UI/Far/UpdateCallbackFar.h
index b2980f21..a2328669 100644
--- a/CPP/7zip/UI/Far/UpdateCallbackFar.h
+++ b/CPP/7zip/UI/Far/UpdateCallbackFar.h
@@ -13,31 +13,38 @@
class CUpdateCallback100Imp:
public IFolderArchiveUpdateCallback,
+ public IFolderArchiveUpdateCallback2,
+ public IFolderScanProgress,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
// CMyComPtr<IInFolderArchive> _archiveHandler;
- CProgressBox *_progressBox;
+ CProgressBox *_percent;
UInt64 _total;
bool m_PasswordIsDefined;
UString m_Password;
public:
- MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+ MY_UNKNOWN_IMP4(
+ IFolderArchiveUpdateCallback,
+ IFolderArchiveUpdateCallback2,
+ IFolderScanProgress,
+ ICryptoGetTextPassword)
INTERFACE_IProgress(;)
INTERFACE_IFolderArchiveUpdateCallback(;)
+ INTERFACE_IFolderArchiveUpdateCallback2(;)
+ INTERFACE_IFolderScanProgress(;)
+
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
CUpdateCallback100Imp(): _total(0) {}
void Init(/* IInFolderArchive *archiveHandler, */ CProgressBox *progressBox)
{
// _archiveHandler = archiveHandler;
- _progressBox = progressBox;
+ _percent = progressBox;
m_PasswordIsDefined = false;
}
};
-
-
#endif
diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile
index 2c32d533..0fff95a2 100644
--- a/CPP/7zip/UI/Far/makefile
+++ b/CPP/7zip/UI/Far/makefile
@@ -1,7 +1,8 @@
PROG = 7-ZipFar.dll
DEF_FILE = Far.def
CFLAGS = $(CFLAGS) \
- -DEXTERNAL_CODECS
+ -DEXTERNAL_CODECS \
+ -DNEW_FOLDER_INTERFACE
!IFNDEF UNDER_CE
CFLAGS = $(CFLAGS) -DWIN_LONG_PATH
@@ -40,12 +41,15 @@ WIN_OBJS = \
$O\PropVariant.obj \
$O\PropVariantConv.obj \
$O\Registry.obj \
+ $O\ResourceString.obj \
$O\Synchronization.obj \
$O\TimeUtils.obj \
7ZIP_COMMON_OBJS = \
+ $O\CreateCoder.obj \
$O\FilePathAutoRename.obj \
$O\FileStreams.obj \
+ $O\FilterCoder.obj \
$O\LimitedStreams.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
@@ -78,6 +82,9 @@ AGENT_OBJS = \
$O\Agent.obj \
$O\AgentOut.obj \
$O\AgentProxy.obj \
+ $O\ArchiveFolder.obj \
+ $O\ArchiveFolderOpen.obj \
+ $O\ArchiveFolderOut.obj \
$O\UpdateCallbackAgent.obj \
COMPRESS_OBJS = \
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp
index 10d76671..35e67753 100644
--- a/CPP/7zip/UI/FileManager/AboutDialog.cpp
+++ b/CPP/7zip/UI/FileManager/AboutDialog.cpp
@@ -29,7 +29,7 @@ bool CAboutDialog::OnInit()
UString s = L"7-Zip " LLL(MY_VERSION);
#ifdef MY_CPU_64BIT
s += L" [";
- s += LangString(IDS_PROP_BIT64);
+ AddLangString(s, IDS_PROP_BIT64);
s += L']';
#endif
diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
new file mode 100644
index 00000000..c209bf35
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
@@ -0,0 +1,839 @@
+// AltStreamsFolder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileIO.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
+
+#include "../Common/ExtractingFilePath.h"
+
+#include "../Agent/IFolderArchive.h"
+
+#include "AltStreamsFolder.h"
+#include "FSDrives.h"
+#include "FSFolder.h"
+
+#include "SysIconUtils.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NFind;
+using namespace NDir;
+using namespace NName;
+
+#ifndef USE_UNICODE_FSTRING
+int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2);
+#endif
+
+#ifndef UNDER_CE
+
+namespace NFsFolder
+{
+bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size);
+}
+
+#endif
+
+namespace NAltStreamsFolder {
+
+static const Byte kProps[] =
+{
+ kpidName,
+ kpidSize,
+ kpidPackSize
+};
+
+static unsigned GetFsParentPrefixSize(const FString &path)
+{
+ if (IsNetworkShareRootPath(path))
+ return 0;
+ unsigned prefixSize = GetRootPrefixSize(path);
+ if (prefixSize == 0 || prefixSize >= path.Len())
+ return 0;
+ FString parentPath = path;
+ int pos = parentPath.ReverseFind_PathSepar();
+ if (pos < 0)
+ return 0;
+ if (pos == (int)parentPath.Len() - 1)
+ {
+ parentPath.DeleteBack();
+ pos = parentPath.ReverseFind_PathSepar();
+ if (pos < 0)
+ return 0;
+ }
+ if ((unsigned)pos + 1 < prefixSize)
+ return 0;
+ return pos + 1;
+}
+
+HRESULT CAltStreamsFolder::Init(const FString &path /* , IFolderFolder *parentFolder */)
+{
+ // _parentFolder = parentFolder;
+ if (path.Back() != ':')
+ return E_FAIL;
+
+ _pathPrefix = path;
+ _pathBaseFile = path;
+ _pathBaseFile.DeleteBack();
+
+ {
+ CFileInfo fi;
+ if (!fi.Find(_pathBaseFile))
+ return GetLastError();
+ }
+
+ unsigned prefixSize = GetFsParentPrefixSize(_pathBaseFile);
+ if (prefixSize == 0)
+ return S_OK;
+ FString parentPath = _pathBaseFile;
+ parentPath.DeleteFrom(prefixSize);
+
+ _findChangeNotification.FindFirst(parentPath, false,
+ FILE_NOTIFY_CHANGE_FILE_NAME
+ | FILE_NOTIFY_CHANGE_DIR_NAME
+ | FILE_NOTIFY_CHANGE_ATTRIBUTES
+ | FILE_NOTIFY_CHANGE_SIZE
+ | FILE_NOTIFY_CHANGE_LAST_WRITE
+ /*
+ | FILE_NOTIFY_CHANGE_LAST_ACCESS
+ | FILE_NOTIFY_CHANGE_CREATION
+ | FILE_NOTIFY_CHANGE_SECURITY
+ */
+ );
+ /*
+ if (_findChangeNotification.IsHandleAllocated())
+ return S_OK;
+ return GetLastError();
+ */
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::LoadItems()
+{
+ Int32 dummy;
+ WasChanged(&dummy);
+ Clear();
+
+ CStreamEnumerator enumerator(_pathBaseFile);
+
+ CStreamInfo si;
+ for (;;)
+ {
+ bool found;
+ if (!enumerator.Next(si, found))
+ {
+ // if (GetLastError() == ERROR_ACCESS_DENIED)
+ // break;
+ // return E_FAIL;
+ break;
+ }
+ if (!found)
+ break;
+ if (si.IsMainStream())
+ continue;
+ CAltStream ss;
+ ss.Name = si.GetReducedName();
+ if (!ss.Name.IsEmpty() && ss.Name[0] == ':')
+ ss.Name.Delete(0);
+
+ ss.Size = si.Size;
+ ss.PackSize_Defined = false;
+ ss.PackSize = si.Size;
+ Streams.Add(ss);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = Streams.Size();
+ return S_OK;
+}
+
+#ifdef USE_UNICODE_FSTRING
+
+STDMETHODIMP CAltStreamsFolder::GetItemPrefix(UInt32 /* index */, const wchar_t **name, unsigned *len)
+{
+ *name = 0;
+ *len = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len)
+{
+ *name = 0;
+ *len = 0;
+ {
+ const CAltStream &ss = Streams[index];
+ *name = ss.Name;
+ *len = ss.Name.Len();
+ }
+ return S_OK;
+}
+
+STDMETHODIMP_(UInt64) CAltStreamsFolder::GetItemSize(UInt32 index)
+{
+ return Streams[index].Size;
+}
+
+#endif
+
+
+STDMETHODIMP CAltStreamsFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant prop;
+ {
+ CAltStream &ss = Streams[index];
+ switch (propID)
+ {
+ case kpidIsDir: prop = false; break;
+ case kpidIsAltStream: prop = true; break;
+ case kpidName: prop = ss.Name; break;
+ case kpidSize: prop = ss.Size; break;
+ case kpidPackSize:
+ #ifdef UNDER_CE
+ prop = ss.Size;
+ #else
+ if (!ss.PackSize_Defined)
+ {
+ ss.PackSize_Defined = true;
+ if (!NFsFolder::MyGetCompressedFileSizeW(_pathPrefix + us2fs(ss.Name), ss.PackSize))
+ ss.PackSize = ss.Size;
+ }
+ prop = ss.PackSize;
+ #endif
+ break;
+ }
+ }
+
+ prop.Detach(value);
+ return S_OK;
+}
+
+
+// returns Position of extension including '.'
+
+static inline const wchar_t *GetExtensionPtr(const UString &name)
+{
+ int dotPos = name.ReverseFind_Dot();
+ return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
+}
+
+STDMETHODIMP_(Int32) CAltStreamsFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 /* propIsRaw */)
+{
+ const CAltStream &ss1 = Streams[index1];
+ const CAltStream &ss2 = Streams[index2];
+
+ switch (propID)
+ {
+ case kpidName:
+ {
+ return CompareFileNames_ForFolderList(ss1.Name, ss2.Name);
+ // return MyStringCompareNoCase(ss1.Name, ss2.Name);
+ }
+ case kpidSize:
+ return MyCompare(ss1.Size, ss2.Size);
+ case kpidPackSize:
+ {
+ #ifdef UNDER_CE
+ return MyCompare(ss1.Size, ss2.Size);
+ #else
+ // PackSize can be undefined here
+ return MyCompare(
+ ss1.PackSize,
+ ss2.PackSize);
+ #endif
+ }
+
+ case kpidExtension:
+ return CompareFileNames_ForFolderList(
+ GetExtensionPtr(ss1.Name),
+ GetExtensionPtr(ss2.Name));
+ }
+
+ return 0;
+}
+
+STDMETHODIMP CAltStreamsFolder::BindToFolder(UInt32 /* index */, IFolderFolder **resultFolder)
+{
+ *resultFolder = 0;
+ return E_INVALIDARG;
+}
+
+STDMETHODIMP CAltStreamsFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder **resultFolder)
+{
+ *resultFolder = 0;
+ return E_INVALIDARG;
+}
+
+static const CFSTR kSuperPrefix = FTEXT("\\\\?\\");
+
+STDMETHODIMP CAltStreamsFolder::BindToParentFolder(IFolderFolder **resultFolder)
+{
+ *resultFolder = 0;
+ /*
+ if (_parentFolder)
+ {
+ CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
+ *resultFolder = parentFolder.Detach();
+ return S_OK;
+ }
+ */
+
+ if (IsDriveRootPath_SuperAllowed(_pathBaseFile))
+ {
+ CFSDrives *drivesFolderSpec = new CFSDrives;
+ CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
+ drivesFolderSpec->Init();
+ *resultFolder = drivesFolder.Detach();
+ return S_OK;
+ }
+
+ /*
+ parentPath.DeleteFrom(pos + 1);
+
+ if (parentPath == kSuperPrefix)
+ {
+ #ifdef UNDER_CE
+ *resultFolder = 0;
+ #else
+ CFSDrives *drivesFolderSpec = new CFSDrives;
+ CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
+ drivesFolderSpec->Init(false, true);
+ *resultFolder = drivesFolder.Detach();
+ #endif
+ return S_OK;
+ }
+
+ FString parentPathReduced = parentPath.Left(pos);
+
+ #ifndef UNDER_CE
+ pos = parentPathReduced.ReverseFind_PathSepar();
+ if (pos == 1)
+ {
+ if (!IS_PATH_SEPAR_CHAR(parentPath[0]))
+ return E_FAIL;
+ CNetFolder *netFolderSpec = new CNetFolder;
+ CMyComPtr<IFolderFolder> netFolder = netFolderSpec;
+ netFolderSpec->Init(fs2us(parentPath));
+ *resultFolder = netFolder.Detach();
+ return S_OK;
+ }
+ #endif
+
+ CFSFolder *parentFolderSpec = new CFSFolder;
+ CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;
+ RINOK(parentFolderSpec->Init(parentPath, 0));
+ *resultFolder = parentFolder.Detach();
+ */
+
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::GetNumberOfProperties(UInt32 *numProperties)
+{
+ *numProperties = ARRAY_SIZE(kProps);
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
+
+STDMETHODIMP CAltStreamsFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidType: prop = "AltStreamsFolder"; break;
+ case kpidPath: prop = fs2us(_pathPrefix); break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAltStreamsFolder::WasChanged(Int32 *wasChanged)
+{
+ bool wasChangedMain = false;
+ for (;;)
+ {
+ if (!_findChangeNotification.IsHandleAllocated())
+ {
+ *wasChanged = BoolToInt(false);
+ return S_OK;
+ }
+
+ DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
+ bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
+ if (wasChangedLoc)
+ {
+ _findChangeNotification.FindNext();
+ wasChangedMain = true;
+ }
+ else
+ break;
+ }
+ *wasChanged = BoolToInt(wasChangedMain);
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::Clone(IFolderFolder **resultFolder)
+{
+ CAltStreamsFolder *folderSpec = new CAltStreamsFolder;
+ CMyComPtr<IFolderFolder> folderNew = folderSpec;
+ folderSpec->Init(_pathPrefix);
+ *resultFolder = folderNew.Detach();
+ return S_OK;
+}
+
+void CAltStreamsFolder::GetAbsPath(const wchar_t *name, FString &absPath)
+{
+ absPath.Empty();
+ if (!IsAbsolutePath(name))
+ absPath += _pathPrefix;
+ absPath += us2fs(name);
+}
+
+
+
+static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
+ const wchar_t *message, const FString &fileName)
+{
+ UString s = message;
+ s += L" : ";
+ s += fs2us(fileName);
+ return callback->ShowMessage(s);
+}
+
+static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback,
+ const wchar_t *message, const FString &fileName)
+{
+ UString s = message;
+ s += L" : ";
+ s += fs2us(fileName);
+ return callback->UpdateErrorMessage(s);
+}
+
+static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
+ const char *message, const FString &fileName)
+{
+ return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
+}
+
+/*
+static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback,
+ const char *message, const FString &fileName)
+{
+ return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
+}
+*/
+
+STDMETHODIMP CAltStreamsFolder::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CAltStreamsFolder::CreateFile(const wchar_t *name, IProgress * /* progress */)
+{
+ FString absPath;
+ GetAbsPath(name, absPath);
+ NIO::COutFile outFile;
+ if (!outFile.Create(absPath, false))
+ return ::GetLastError();
+ return S_OK;
+}
+
+static DWORD Return_LastError_or_FAIL()
+{
+ DWORD errorCode = GetLastError();
+ if (errorCode == 0)
+ errorCode = (DWORD)E_FAIL;
+ return errorCode;
+}
+
+static UString GetLastErrorMessage()
+{
+ return NError::MyFormatMessage(Return_LastError_or_FAIL());
+}
+
+static HRESULT UpdateFile(NFsFolder::CCopyStateIO &state, CFSTR inPath, CFSTR outPath, IFolderArchiveUpdateCallback *callback)
+{
+ if (NFind::DoesFileOrDirExist(outPath))
+ {
+ RINOK(SendMessageError(callback, NError::MyFormatMessage(ERROR_ALREADY_EXISTS), outPath));
+ CFileInfo fi;
+ if (fi.Find(inPath))
+ {
+ if (state.TotalSize >= fi.Size)
+ state.TotalSize -= fi.Size;
+ }
+ return S_OK;
+ }
+
+ {
+ if (callback)
+ RINOK(callback->CompressOperation(fs2us(inPath)));
+ RINOK(state.MyCopyFile(inPath, outPath));
+ if (state.ErrorFileIndex >= 0)
+ {
+ if (state.ErrorMessage.IsEmpty())
+ state.ErrorMessage = GetLastErrorMessage();
+ FString errorName;
+ if (state.ErrorFileIndex == 0)
+ errorName = inPath;
+ else
+ errorName = outPath;
+ if (callback)
+ RINOK(SendMessageError(callback, state.ErrorMessage, errorName));
+ }
+ if (callback)
+ RINOK(callback->OperationResult(0));
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress)
+{
+ CMyComPtr<IFolderArchiveUpdateCallback> callback;
+ if (progress)
+ {
+ RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback));
+ }
+
+ FString destPath = _pathPrefix + us2fs(newName);
+
+ const CAltStream &ss = Streams[index];
+
+ if (callback)
+ {
+ RINOK(callback->SetNumFiles(1));
+ RINOK(callback->SetTotal(ss.Size));
+ }
+
+ NFsFolder::CCopyStateIO state;
+ state.Progress = progress;
+ state.TotalSize = 0;
+ state.DeleteSrcFile = true;
+
+ return UpdateFile(state, _pathPrefix + us2fs(ss.Name), destPath, callback);
+}
+
+STDMETHODIMP CAltStreamsFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress)
+{
+ RINOK(progress->SetTotal(numItems));
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ const CAltStream &ss = Streams[indices[i]];
+ const FString fullPath = _pathPrefix + us2fs(ss.Name);
+ bool result = DeleteFileAlways(fullPath);
+ if (!result)
+ return Return_LastError_or_FAIL();
+ UInt64 completed = i;
+ RINOK(progress->SetCompleted(&completed));
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID */,
+ const PROPVARIANT * /* value */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
+{
+ const CAltStream &ss = Streams[index];
+ *iconIndex = 0;
+ int iconIndexTemp;
+ if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name),
+ 0 // fi.Attrib
+ , iconIndexTemp) != 0)
+ {
+ *iconIndex = iconIndexTemp;
+ return S_OK;
+ }
+ return Return_LastError_or_FAIL();
+}
+
+/*
+class CGetProp:
+ public IGetProp,
+ public CMyUnknownImp
+{
+public:
+ // const CArc *Arc;
+ // UInt32 IndexInArc;
+ UString Name; // relative path
+ UInt64 Size;
+
+ MY_UNKNOWN_IMP1(IGetProp)
+ INTERFACE_IGetProp(;)
+};
+
+STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)
+{
+ if (propID == kpidName)
+ {
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop = Name;
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+ }
+ if (propID == kpidSize)
+ {
+ NCOM::CPropVariant prop = Size;
+ prop.Detach(value);
+ return S_OK;
+ }
+ NCOM::CPropVariant prop;
+ prop.Detach(value);
+ return S_OK;
+}
+*/
+
+static HRESULT CopyStream(
+ NFsFolder::CCopyStateIO &state,
+ const FString &srcPath,
+ const CFileInfo &srcFileInfo,
+ const CAltStream &srcAltStream,
+ const FString &destPathSpec,
+ IFolderOperationsExtractCallback *callback)
+{
+ FString destPath = destPathSpec;
+ if (CompareFileNames(destPath, srcPath) == 0)
+ {
+ RINOK(SendMessageError(callback, "can not copy file onto itself", destPath));
+ return E_ABORT;
+ }
+
+ Int32 writeAskResult;
+ CMyComBSTR destPathResult;
+ RINOK(callback->AskWrite(
+ fs2us(srcPath),
+ BoolToInt(false),
+ &srcFileInfo.MTime, &srcAltStream.Size,
+ fs2us(destPath),
+ &destPathResult,
+ &writeAskResult));
+
+ if (IntToBool(writeAskResult))
+ {
+ RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
+ FString destPathNew = us2fs((LPCOLESTR)destPathResult);
+ RINOK(state.MyCopyFile(srcPath, destPathNew));
+ if (state.ErrorFileIndex >= 0)
+ {
+ if (state.ErrorMessage.IsEmpty())
+ state.ErrorMessage = GetLastErrorMessage();
+ FString errorName;
+ if (state.ErrorFileIndex == 0)
+ errorName = srcPath;
+ else
+ errorName = destPathNew;
+ RINOK(SendMessageError(callback, state.ErrorMessage, errorName));
+ return E_ABORT;
+ }
+ state.StartPos += state.CurrentSize;
+ }
+ else
+ {
+ if (state.TotalSize >= srcAltStream.Size)
+ {
+ state.TotalSize -= srcAltStream.Size;
+ RINOK(state.Progress->SetTotal(state.TotalSize));
+ }
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
+ Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
+ const wchar_t *path, IFolderOperationsExtractCallback *callback)
+{
+ if (numItems == 0)
+ return S_OK;
+
+ /*
+ CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
+ RINOK(callback->QueryInterface(IID_IFolderExtractToStreamCallback, (void **)&ExtractToStreamCallback));
+ if (ExtractToStreamCallback)
+ {
+ Int32 useStreams = 0;
+ if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)
+ useStreams = 0;
+ if (useStreams == 0)
+ ExtractToStreamCallback.Release();
+ }
+ */
+
+ UInt64 totalSize = 0;
+ {
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ {
+ totalSize += Streams[indices[i]].Size;
+ }
+ RINOK(callback->SetTotal(totalSize));
+ RINOK(callback->SetNumFiles(numItems));
+ }
+
+ /*
+ if (ExtractToStreamCallback)
+ {
+ CGetProp *GetProp_Spec = new CGetProp;
+ CMyComPtr<IGetProp> GetProp= GetProp_Spec;
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ UInt32 index = indices[i];
+ const CAltStream &ss = Streams[index];
+ GetProp_Spec->Name = ss.Name;
+ GetProp_Spec->Size = ss.Size;
+ CMyComPtr<ISequentialOutStream> outStream;
+ RINOK(ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, BoolToInt(false), &outStream,
+ NArchive::NExtract::NAskMode::kExtract, GetProp)); // isDir
+ FString srcPath;
+ GetFullPath(ss, srcPath);
+ RINOK(ExtractToStreamCallback->PrepareOperation7(NArchive::NExtract::NAskMode::kExtract));
+ RINOK(ExtractToStreamCallback->SetOperationResult7(NArchive::NExtract::NOperationResult::kOK, BoolToInt(false))); // _encrypted
+ // RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback, completedSize));
+ }
+ return S_OK;
+ }
+ */
+
+ FString destPath = us2fs(path);
+ if (destPath.IsEmpty() /* && !ExtractToStreamCallback */)
+ return E_INVALIDARG;
+
+ bool isAltDest = NName::IsAltPathPrefix(destPath);;
+ bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
+
+ if (isDirectPath)
+ {
+ if (numItems > 1)
+ return E_INVALIDARG;
+ }
+
+ CFileInfo fi;
+ if (!fi.Find(_pathBaseFile))
+ return GetLastError();
+
+ NFsFolder::CCopyStateIO state;
+ state.Progress = callback;
+ state.DeleteSrcFile = IntToBool(moveMode);
+ state.TotalSize = totalSize;
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ UInt32 index = indices[i];
+ const CAltStream &ss = Streams[index];
+ FString destPath2 = destPath;
+ if (!isDirectPath)
+ destPath2 += us2fs(Get_Correct_FsFile_Name(ss.Name));
+ FString srcPath;
+ GetFullPath(ss, srcPath);
+ RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback));
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CAltStreamsFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
+ const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
+{
+ /*
+ if (numItems == 0)
+ return S_OK;
+
+ CMyComPtr<IFolderArchiveUpdateCallback> callback;
+ if (progress)
+ {
+ RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback));
+ }
+
+ if (CompareFileNames(fromFolderPath, fs2us(_pathPrefix)) == 0)
+ {
+ RINOK(SendMessageError(callback, "can not copy file onto itself", _pathPrefix));
+ return E_ABORT;
+ }
+
+ if (callback)
+ RINOK(callback->SetNumFiles(numItems));
+
+ UInt64 totalSize = 0;
+
+ UInt32 i;
+
+ FString path;
+ for (i = 0; i < numItems; i++)
+ {
+ path = us2fs(fromFolderPath);
+ path += us2fs(itemsPaths[i]);
+
+ CFileInfo fi;
+ if (!fi.Find(path))
+ return ::GetLastError();
+ if (fi.IsDir())
+ return E_NOTIMPL;
+ totalSize += fi.Size;
+ }
+
+ RINOK(progress->SetTotal(totalSize));
+
+ // UInt64 completedSize = 0;
+
+ NFsFolder::CCopyStateIO state;
+ state.Progress = progress;
+ state.DeleteSrcFile = IntToBool(moveMode);
+ state.TotalSize = totalSize;
+
+ // we need to clear READ-ONLY of parent before creating alt stream
+ {
+ DWORD attrib = GetFileAttrib(_pathBaseFile);
+ if (attrib != INVALID_FILE_ATTRIBUTES
+ && (attrib & FILE_ATTRIBUTE_READONLY) != 0)
+ {
+ if (!SetFileAttrib(_pathBaseFile, attrib & ~FILE_ATTRIBUTE_READONLY))
+ {
+ if (callback)
+ {
+ RINOK(SendMessageError(callback, GetLastErrorMessage(), _pathBaseFile));
+ return S_OK;
+ }
+ return Return_LastError_or_FAIL();
+ }
+ }
+ }
+
+ for (i = 0; i < numItems; i++)
+ {
+ path = us2fs(fromFolderPath);
+ path += us2fs(itemsPaths[i]);
+
+ FString destPath = _pathPrefix + us2fs(itemsPaths[i]);
+
+ RINOK(UpdateFile(state, path, destPath, callback));
+ }
+
+ return S_OK;
+ */
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CAltStreamsFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */)
+{
+ return E_NOTIMPL;
+}
+
+}
diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.h b/CPP/7zip/UI/FileManager/AltStreamsFolder.h
new file mode 100644
index 00000000..ccd0a58f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.h
@@ -0,0 +1,100 @@
+// AltStreamsFolder.h
+
+#ifndef __ALT_STREAMS_FOLDER_H
+#define __ALT_STREAMS_FOLDER_H
+
+#include "../../../Common/MyCom.h"
+
+#include "../../../Windows/FileFind.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "IFolder.h"
+
+namespace NAltStreamsFolder {
+
+class CAltStreamsFolder;
+
+struct CAltStream
+{
+ UInt64 Size;
+ UInt64 PackSize;
+ bool PackSize_Defined;
+ UString Name;
+};
+
+
+class CAltStreamsFolder:
+ public IFolderFolder,
+ public IFolderCompare,
+ #ifdef USE_UNICODE_FSTRING
+ public IFolderGetItemName,
+ #endif
+ public IFolderWasChanged,
+ public IFolderOperations,
+ // public IFolderOperationsDeleteToRecycleBin,
+ public IFolderClone,
+ public IFolderGetSystemIconIndex,
+ public CMyUnknownImp
+{
+public:
+ MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
+ MY_QUERYINTERFACE_ENTRY(IFolderCompare)
+ #ifdef USE_UNICODE_FSTRING
+ MY_QUERYINTERFACE_ENTRY(IFolderGetItemName)
+ #endif
+ MY_QUERYINTERFACE_ENTRY(IFolderWasChanged)
+ // MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin)
+ MY_QUERYINTERFACE_ENTRY(IFolderOperations)
+ MY_QUERYINTERFACE_ENTRY(IFolderClone)
+ MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex)
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+
+ INTERFACE_FolderFolder(;)
+ INTERFACE_FolderOperations(;)
+
+ STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
+
+ #ifdef USE_UNICODE_FSTRING
+ INTERFACE_IFolderGetItemName(;)
+ #endif
+ STDMETHOD(WasChanged)(Int32 *wasChanged);
+ STDMETHOD(Clone)(IFolderFolder **resultFolder);
+
+ STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
+
+private:
+ FString _pathBaseFile; // folder
+ FString _pathPrefix; // folder:
+
+ CObjectVector<CAltStream> Streams;
+ // CMyComPtr<IFolderFolder> _parentFolder;
+
+ NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
+
+ HRESULT GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress);
+ void GetAbsPath(const wchar_t *name, FString &absPath);
+
+public:
+ // path must be with ':' at tail
+ HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */);
+
+ CAltStreamsFolder() {}
+
+ void GetFullPath(const CAltStream &item, FString &path) const
+ {
+ path = _pathPrefix;
+ path += us2fs(item.Name);
+ }
+
+ void Clear()
+ {
+ Streams.Clear();
+ }
+};
+
+}
+
+#endif
diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp
index 51c8d2db..b6a66975 100644
--- a/CPP/7zip/UI/FileManager/App.cpp
+++ b/CPP/7zip/UI/FileManager/App.cpp
@@ -140,8 +140,8 @@ HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UStr
}
static void CreateToolbar(HWND parent,
- NWindows::NControl::CImageList &imageList,
- NWindows::NControl::CToolBar &toolBar,
+ NControl::CImageList &imageList,
+ NControl::CToolBar &toolBar,
bool largeButtons)
{
toolBar.Attach(::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 0
@@ -364,7 +364,8 @@ void CApp::Save()
if (panel._parentFolders.IsEmpty())
path = panel._currentFolderPrefix;
else
- path = GetFolderPath(panel._parentFolders[0].ParentFolder);
+ path = panel._parentFolders[0].ParentFolderPath;
+ // GetFolderPath(panel._parentFolders[0].ParentFolder);
SavePanelPath(i, path);
listMode.Panels[i] = panel.GetListViewMode();
SaveFlatView(i, panel._flatModeForArc);
@@ -380,9 +381,12 @@ void CApp::Release()
Panels[i].Release();
}
-// reduces path to part that exists on disk
+// reduces path to part that exists on disk (or root prefix of path)
+// output path is normalized (with WCHAR_PATH_SEPARATOR)
static void ReducePathToRealFileSystemPath(UString &path)
{
+ unsigned prefixSize = GetRootPrefixSize(path);
+
while (!path.IsEmpty())
{
if (NFind::DoesDirExist(us2fs(path)))
@@ -390,63 +394,59 @@ static void ReducePathToRealFileSystemPath(UString &path)
NName::NormalizeDirPathPrefix(path);
break;
}
- int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR);
+ int pos = path.ReverseFind_PathSepar();
if (pos < 0)
{
path.Empty();
break;
}
path.DeleteFrom(pos + 1);
- if (path.Len() == 3 && path[1] == L':')
+ if ((unsigned)pos + 1 == prefixSize)
break;
- if (path.Len() > 2 && path[0] == '\\' && path[1] == '\\')
- {
- int nextPos = path.Find(WCHAR_PATH_SEPARATOR, 2); // pos after \\COMPNAME
- if (nextPos > 0 && path.Find(WCHAR_PATH_SEPARATOR, nextPos + 1) == pos)
- break;
- }
path.DeleteFrom(pos);
}
}
-// return true for dir\, if dir exist
+// returns: true, if such dir exists or is root
+/*
static bool CheckFolderPath(const UString &path)
{
UString pathReduced = path;
ReducePathToRealFileSystemPath(pathReduced);
return (pathReduced == path);
}
+*/
extern UString ConvertSizeToString(UInt64 value);
-static UString AddSizeValue(UInt64 size)
+static void AddSizeValue(UString &s, UInt64 size)
{
- return MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size));
+ s += MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size));
}
static void AddValuePair1(UString &s, UINT resourceID, UInt64 size)
{
- s += LangString(resourceID);
+ AddLangString(s, resourceID);
s += L": ";
- s += AddSizeValue(size);
- s += L'\n';
+ AddSizeValue(s, size);
+ s.Add_LF();
}
void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size)
{
if (num == 0)
return;
- s += LangString(resourceID);
+ AddLangString(s, resourceID);
s += L": ";
s += ConvertSizeToString(num);
if (size != (UInt64)(Int64)-1)
{
s += L" ( ";
- s += AddSizeValue(size);
+ AddSizeValue(s, size);
s += L" )";
}
- s += L'\n';
+ s.Add_LF();
}
static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, UInt64 &sum)
@@ -490,7 +490,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)
if (numDefined == 2)
AddValuePair1(info, IDS_PROP_SIZE, filesSize + foldersSize);
- info += L"\n";
+ info.Add_LF();
info += _currentFolderPrefix;
for (i = 0; i < indices.Size() && (int)i < (int)kCopyDialog_NumInfoLines - 6; i++)
@@ -499,7 +499,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)
int index = indices[i];
info += GetItemRelPath(index);
if (IsItem_Folder(index))
- info += WCHAR_PATH_SEPARATOR;
+ info.Add_PathSepar();
}
if (i != indices.Size())
info += L"\n ...";
@@ -508,6 +508,20 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)
bool IsCorrectFsName(const UString &name);
+
+
+/* Returns true, if path is path that can be used as path for File System functions
+*/
+
+/*
+static bool IsFsPath(const FString &path)
+{
+ if (!IsAbsolutePath(path))
+ return false;
+ unsigned prefixSize = GetRootPrefixSize(path);
+}
+*/
+
void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
{
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
@@ -517,7 +531,12 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel);
CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel);
- if (!srcPanel.DoesItSupportOperations())
+ if (move)
+ {
+ if (!srcPanel.CheckBeforeUpdate(IDS_MOVE))
+ return;
+ }
+ else if (!srcPanel.DoesItSupportOperations())
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
@@ -544,13 +563,15 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
srcPanel.GetOperatedIndicesSmart(indices);
if (indices.Size() == 0)
return;
- destPath = destPanel._currentFolderPrefix;
+ destPath = destPanel.GetFsPath();
if (NumPanels == 1)
ReducePathToRealFileSystemPath(destPath);
}
}
+
UStringVector copyFolders;
ReadCopyHistory(copyFolders);
+
{
CCopyDialog copyDialog;
@@ -583,10 +604,10 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
if (IsAbsolutePath(destPath))
destPath.Empty();
else
- destPath = srcPanel._currentFolderPrefix;
+ destPath = srcPanel.GetFsPath();
destPath += correctName;
- #ifndef UNDER_CE
+ #if defined(_WIN32) && !defined(UNDER_CE)
if (destPath.Len() > 0 && destPath[0] == '\\')
if (destPath.Len() == 1 || destPath[1] != '\\')
{
@@ -595,59 +616,112 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
}
#endif
- if (indices.Size() > 1 ||
- (!destPath.IsEmpty() && destPath.Back() == WCHAR_PATH_SEPARATOR) ||
- NFind::DoesDirExist(us2fs(destPath)) ||
- srcPanel.IsArcFolder())
+ bool possibleToUseDestPanel = false;
+
+ if (CompareFileNames(destPath, destPanel.GetFsPath()) == 0)
{
- CreateComplexDir(us2fs(destPath));
- NName::NormalizeDirPathPrefix(destPath);
- if (!CheckFolderPath(destPath))
+ if (NumPanels == 1 || CompareFileNames(destPath, srcPanel.GetFsPath()) == 0)
{
- if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations())
- {
- srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
- return;
- }
- useDestPanel = true;
+ srcPanel.MessageBoxMyError(L"Can not copy files onto itself");
+ return;
}
+
+ if (destPanel.DoesItSupportOperations())
+ possibleToUseDestPanel = true;
}
- else
+
+ bool destIsFsPath = false;
+
+ if (possibleToUseDestPanel)
{
- if (!IsCorrectFsName(destPath))
+ if (destPanel.IsFSFolder() || destPanel.IsAltStreamsFolder())
+ destIsFsPath = true;
+ else if (destPanel.IsFSDrivesFolder() || destPanel.IsRootFolder())
{
- srcPanel.MessageBoxError(E_INVALIDARG);
+ srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
}
- int pos = destPath.ReverseFind(WCHAR_PATH_SEPARATOR);
- if (pos >= 0)
+ }
+ else
+ {
+ if (IsAltPathPrefix(us2fs(destPath)))
{
- UString prefix = destPath.Left(pos + 1);
- CreateComplexDir(us2fs(prefix));
- if (!CheckFolderPath(prefix))
+ // we allow alt streams dest only to alt stream folder in second panel
+ srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
+ return;
+ /*
+ FString basePath = us2fs(destPath);
+ basePath.DeleteBack();
+ if (!DoesFileOrDirExist(basePath))
{
- srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
+ srcPanel.MessageBoxError2Lines(basePath, ERROR_FILE_NOT_FOUND); // GetLastError()
return;
}
+ destIsFsPath = true;
+ */
+ }
+ else
+ {
+ if (indices.Size() == 1 &&
+ !destPath.IsEmpty() && destPath.Back() != WCHAR_PATH_SEPARATOR)
+ {
+ int pos = destPath.ReverseFind_PathSepar();
+ if (pos < 0)
+ {
+ srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
+ return;
+ }
+ {
+ /*
+ #ifdef _WIN32
+ UString name = destPath.Ptr(pos + 1);
+ if (name.Find(L':') >= 0)
+ {
+ srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
+ return;
+ }
+ #endif
+ */
+ UString prefix = destPath.Left(pos + 1);
+ if (!CreateComplexDir(us2fs(prefix)))
+ {
+ srcPanel.MessageBoxError2Lines(prefix, GetLastError());
+ return;
+ }
+ }
+ // bool isFolder = srcPanael.IsItem_Folder(indices[0]);
+ }
+ else
+ {
+ NName::NormalizeDirPathPrefix(destPath);
+ if (!CreateComplexDir(us2fs(destPath)))
+ {
+ srcPanel.MessageBoxError2Lines(destPath, GetLastError());
+ return;
+ }
+ }
+ destIsFsPath = true;
}
}
+ if (!destIsFsPath)
+ useDestPanel = true;
+
AddUniqueStringToHeadOfList(copyFolders, destPath);
while (copyFolders.Size() > 20)
copyFolders.DeleteBack();
SaveCopyHistory(copyFolders);
}
- /*
- if (destPath == destPanel._currentFolderPrefix)
- {
- if (destPanel.GetFolderTypeID() == L"PhysDrive")
- useDestPanel = true;
- }
- */
+ bool useSrcPanel = !useDestPanel || !srcPanel.Is_IO_FS_Folder();
- bool useSrcPanel = (!useDestPanel || !srcPanel.IsFsOrDrivesFolder() || destPanel.IsFSFolder());
bool useTemp = useSrcPanel && useDestPanel;
+ if (useTemp && NumPanels == 1)
+ {
+ srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
+ return;
+ }
+
CTempDir tempDirectory;
FString tempDirPrefix;
if (useTemp)
@@ -666,6 +740,7 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
CPanel::CDisableNotify disableNotify2(srcPanel);
HRESULT result = S_OK;
+
if (useSrcPanel)
{
CCopyToOptions options;
@@ -685,12 +760,13 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
if (useTemp)
folderPrefix = fs2us(tempDirPrefix);
else
- folderPrefix = srcPanel._currentFolderPrefix;
+ folderPrefix = srcPanel.GetFsPath();
filePaths.ClearAndReserve(indices.Size());
FOR_VECTOR (i, indices)
- filePaths.AddInReserved(srcPanel.GetItemRelPath(indices[i]));
+ filePaths.AddInReserved(srcPanel.GetItemRelPath2(indices[i]));
result = destPanel.CopyFrom(move, folderPrefix, filePaths, true, 0);
}
+
if (result != S_OK)
{
// disableNotify1.Restore();
@@ -705,15 +781,18 @@ void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
}
RefreshTitleAlways();
+
if (copyToSame || move)
{
srcPanel.RefreshListCtrl(srcSelState);
}
+
if (!copyToSame)
{
destPanel.RefreshListCtrl(destSelState);
srcPanel.KillSelection();
}
+
disableNotify1.Restore();
disableNotify2.Restore();
srcPanel.SetFocusToList();
@@ -831,7 +910,7 @@ void CApp::RefreshTitle(int panelIndex, bool always)
void AddUniqueStringToHead(UStringVector &list, const UString &s)
{
for (unsigned i = 0; i < list.Size();)
- if (s.IsEqualToNoCase(list[i]))
+ if (s.IsEqualTo_NoCase(list[i]))
list.Delete(i);
else
i++;
@@ -848,7 +927,7 @@ void CFolderHistory::Normalize()
void CFolderHistory::AddString(const UString &s)
{
- NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
+ NSynchronization::CCriticalSectionLock lock(_criticalSection);
AddUniqueStringToHead(Strings, s);
Normalize();
}
diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h
index c775cc2e..5fe95e0b 100644
--- a/CPP/7zip/UI/FileManager/App.h
+++ b/CPP/7zip/UI/FileManager/App.h
@@ -195,6 +195,7 @@ public:
void CopyTo() { OnCopy(false, false, GetFocusedPanelIndex()); }
void MoveTo() { OnCopy(true, false, GetFocusedPanelIndex()); }
void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); }
+ HRESULT CalculateCrc2(const UString &methodName);
void CalculateCrc(const UString &methodName);
void DiffFiles();
void Split();
@@ -204,6 +205,7 @@ public:
#ifndef UNDER_CE
void Link();
+ void OpenAltStreams() { GetFocusedPanel().OpenAltStreams(); }
#endif
void CreateFolder() { GetFocusedPanel().CreateFolder(); }
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
index 32db8f8f..89a6b45a 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -77,7 +77,7 @@ static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *nam
UString s = HResultToMessage(errorCode);
if (name)
{
- s += L'\n';
+ s.Add_LF();
s += name;
}
MessageBox_Error_Global(wnd, s);
@@ -209,7 +209,7 @@ bool CBrowseDialog::OnInit()
FOR_VECTOR (i, Filters)
{
if (i != 0)
- s += L' ';
+ s.Add_Space();
s += Filters[i];
}
}
@@ -256,14 +256,16 @@ bool CBrowseDialog::OnInit()
_topDirPrefix.Empty();
{
int rootSize = GetRootPrefixSize(FilePath);
+ #if defined(_WIN32) && !defined(UNDER_CE)
// We can go up from root folder to drives list
- if (NName::IsDrivePath(FilePath))
+ if (IsDrivePath(FilePath))
rootSize = 0;
else if (IsSuperPath(FilePath))
{
- if (NName::IsDrivePath(&FilePath[kSuperPathPrefixSize]))
+ if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize)))
rootSize = kSuperPathPrefixSize;
}
+ #endif
_topDirPrefix.SetFrom(FilePath, rootSize);
}
@@ -466,7 +468,7 @@ bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, US
return false;
if (s.Back() == WCHAR_PATH_SEPARATOR)
return false;
- int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);
+ int pos = s.ReverseFind_PathSepar();
parentPrefix.SetFrom(s, pos + 1);
name = s.Ptr(pos + 1);
return true;
@@ -856,7 +858,7 @@ bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path,
return false;
{
UString s = errorMessage;
- s += L"\n";
+ s.Add_LF();
s += path;
MessageBox_Error_Global(owner, s);
}
@@ -904,27 +906,32 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result
result.Empty();
UString path = path2;
- path.Replace('/', WCHAR_PATH_SEPARATOR);
+ path.Replace(L'/', WCHAR_PATH_SEPARATOR);
unsigned start = 0;
UString base;
- if (NName::IsAbsolutePath(path))
+
+ if (IsAbsolutePath(path))
{
+ #if defined(_WIN32) && !defined(UNDER_CE)
if (IsSuperOrDevicePath(path))
{
result = path;
return true;
}
+ #endif
int pos = GetRootPrefixSize(path);
if (pos > 0)
start = pos;
}
else
{
+ #if defined(_WIN32) && !defined(UNDER_CE)
if (IsSuperOrDevicePath(relBase))
{
result = path;
return true;
}
+ #endif
base = relBase;
}
@@ -954,6 +961,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result
result += path.Left(start);
bool checkExist = true;
UString cur;
+
for (;;)
{
if (start == path.Len())
@@ -979,7 +987,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result
result += cur;
if (slashPos < 0)
break;
- result += WCHAR_PATH_SEPARATOR;
+ result.Add_PathSepar();
start = slashPos + 1;
}
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h
index 77c749b5..957af2e2 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog.h
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.h
@@ -9,7 +9,7 @@ bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultP
bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath);
/* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file)
- But it doesn't change "bad" name in any of the following caes:
+ But it doesn't change "bad" name in any of the following cases:
- path is Super Path (with \\?\ prefix)
- path is relative and relBase is Super Path
- there is file or dir in filesystem with specified "bad" name */
diff --git a/CPP/7zip/UI/FileManager/EditPage.rc b/CPP/7zip/UI/FileManager/EditPage.rc
index f5618d04..38f74ea1 100644
--- a/CPP/7zip/UI/FileManager/EditPage.rc
+++ b/CPP/7zip/UI/FileManager/EditPage.rc
@@ -1,7 +1,7 @@
#include "EditPageRes.h"
#include "../../GuiCommon.rc"
-#define xc 200
+#define xc 240
#define yc 80
IDD_EDIT MY_PAGE
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
index ed4bb884..50c43163 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -22,6 +22,7 @@
#endif
#include "../GUI/ExtractRes.h"
+#include "resourceGui.h"
#include "ExtractCallback.h"
#include "FormatUtils.h"
@@ -30,6 +31,7 @@
#ifndef _NO_CRYPTO
#include "PasswordDialog.h"
#endif
+#include "PropertyName.h"
using namespace NWindows;
using namespace NFile;
@@ -39,6 +41,10 @@ CExtractCallbackImp::~CExtractCallbackImp() {}
void CExtractCallbackImp::Init()
{
+ _lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING);
+ _lang_Testing = LangString(IDS_PROGRESS_TESTING);
+ _lang_Skipping = LangString(IDS_PROGRESS_SKIPPING);
+
NumArchiveErrors = 0;
ThereAreMessageErrors = false;
#ifndef _SFX
@@ -97,6 +103,11 @@ HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, co
return ProgressDialog->Sync.CheckStop();
}
+HRESULT CExtractCallbackImp::Open_Finished()
+{
+ return ProgressDialog->Sync.CheckStop();
+}
+
#ifndef _NO_CRYPTO
HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)
@@ -104,6 +115,7 @@ HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)
return CryptoGetTextPassword(password);
}
+/*
HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
{
passwordIsDefined = PasswordIsDefined;
@@ -116,10 +128,11 @@ bool CExtractCallbackImp::Open_WasPasswordAsked()
return PasswordWasAsked;
}
-void CExtractCallbackImp::Open_ClearPasswordWasAskedFlag()
+void CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag()
{
PasswordWasAsked = false;
}
+*/
#endif
@@ -179,10 +192,21 @@ STDMETHODIMP CExtractCallbackImp::AskOverwrite(
}
-STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, bool isFolder, Int32 /* askExtractMode */, const UInt64 * /* position */)
+STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */)
{
- _isFolder = isFolder;
- return SetCurrentFilePath2(name);
+ _isFolder = IntToBool(isFolder);
+ _currentFilePath = name;
+
+ const UString *msg = &_lang_Empty;
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break;
+ case NArchive::NExtract::NAskMode::kTest: msg = &_lang_Testing; break;
+ case NArchive::NExtract::NAskMode::kSkip: msg = &_lang_Skipping; break;
+ // default: s = "Unknown operation";
+ }
+
+ return ProgressDialog->Sync.Set_Status2(*msg, name, IntToBool(isFolder));
}
STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *s)
@@ -208,101 +232,108 @@ STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s)
#endif
-STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted)
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s)
{
+ s.Empty();
+
+ if (opRes == NArchive::NExtract::NOperationResult::kOK)
+ return;
+
+ UINT messageID = 0;
+ UINT id = 0;
+
switch (opRes)
{
- case NArchive::NExtract::NOperationResult::kOK:
+ case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
+ messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;
+ id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD;
+ break;
+ case NArchive::NExtract::NOperationResult::kDataError:
+ messageID = encrypted ?
+ IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:
+ IDS_EXTRACT_MESSAGE_DATA_ERROR;
+ id = IDS_EXTRACT_MSG_DATA_ERROR;
+ break;
+ case NArchive::NExtract::NOperationResult::kCRCError:
+ messageID = encrypted ?
+ IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED:
+ IDS_EXTRACT_MESSAGE_CRC_ERROR;
+ id = IDS_EXTRACT_MSG_CRC_ERROR;
+ break;
+ case NArchive::NExtract::NOperationResult::kUnavailable:
+ id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA;
+ break;
+ case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
+ id = IDS_EXTRACT_MSG_UEXPECTED_END;
break;
+ case NArchive::NExtract::NOperationResult::kDataAfterEnd:
+ id = IDS_EXTRACT_MSG_DATA_AFTER_END;
+ break;
+ case NArchive::NExtract::NOperationResult::kIsNotArc:
+ id = IDS_EXTRACT_MSG_IS_NOT_ARC;
+ break;
+ case NArchive::NExtract::NOperationResult::kHeadersError:
+ id = IDS_EXTRACT_MSG_HEADERS_ERROR;
+ break;
+ case NArchive::NExtract::NOperationResult::kWrongPassword:
+ id = IDS_EXTRACT_MSG_WRONG_PSW_CLAIM;
+ break;
+ /*
default:
- {
- UINT messageID = 0;
- UINT id = 0;
-
- switch (opRes)
- {
- case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
- messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;
- id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD;
- break;
- case NArchive::NExtract::NOperationResult::kDataError:
- messageID = encrypted ?
- IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:
- IDS_EXTRACT_MESSAGE_DATA_ERROR;
- id = IDS_EXTRACT_MSG_DATA_ERROR;
- break;
- case NArchive::NExtract::NOperationResult::kCRCError:
- messageID = encrypted ?
- IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED:
- IDS_EXTRACT_MESSAGE_CRC_ERROR;
- id = IDS_EXTRACT_MSG_CRC_ERROR;
- break;
- case NArchive::NExtract::NOperationResult::kUnavailable:
- id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA;
- break;
- case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
- id = IDS_EXTRACT_MSG_UEXPECTED_END;
- break;
- case NArchive::NExtract::NOperationResult::kDataAfterEnd:
- id = IDS_EXTRACT_MSG_DATA_AFTER_END;
- break;
- case NArchive::NExtract::NOperationResult::kIsNotArc:
- id = IDS_EXTRACT_MSG_IS_NOT_ARC;
- break;
- case NArchive::NExtract::NOperationResult::kHeadersError:
- id = IDS_EXTRACT_MSG_HEADERS_ERROR;
- break;
- /*
- default:
- messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;
- break;
- */
- }
- if (_needWriteArchivePath)
- {
- if (!_currentArchivePath.IsEmpty())
- AddError_Message(_currentArchivePath);
- _needWriteArchivePath = false;
- }
+ messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;
+ break;
+ */
+ }
- UString msg;
- UString msgOld;
+ UString msg;
+ UString msgOld;
- #ifndef _SFX
- if (id != 0)
- LangString_OnlyFromLangFile(id, msg);
- if (messageID != 0 && msg.IsEmpty())
- LangString_OnlyFromLangFile(messageID, msgOld);
- #endif
+ #ifndef _SFX
+ if (id != 0)
+ LangString_OnlyFromLangFile(id, msg);
+ if (messageID != 0 && msg.IsEmpty())
+ LangString_OnlyFromLangFile(messageID, msgOld);
+ #endif
- UString s;
- if (msg.IsEmpty() && !msgOld.IsEmpty())
- s = MyFormatNew(msgOld, _currentFilePath);
- else
- {
- if (msg.IsEmpty())
- LangString(id, msg);
- if (!msg.IsEmpty())
- s += msg;
- else
- {
- wchar_t temp[16];
- ConvertUInt32ToString(opRes, temp);
- s += L"Error #";
- s += temp;
- }
+ if (msg.IsEmpty() && !msgOld.IsEmpty())
+ s = MyFormatNew(msgOld, fileName);
+ else
+ {
+ if (msg.IsEmpty() && id != 0)
+ LangString(id, msg);
+ if (!msg.IsEmpty())
+ s += msg;
+ else
+ {
+ char temp[16];
+ ConvertUInt32ToString(opRes, temp);
+ s.AddAscii("Error #");
+ s.AddAscii(temp);
+ }
- if (encrypted)
- {
- // s += L" : ";
- // s += LangString(IDS_EXTRACT_MSG_ENCRYPTED);
- s += L" : ";
- s += LangString(IDS_EXTRACT_MSG_WRONG_PSW);
- }
- s += L" : ";
- s += _currentFilePath;
- }
+ if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword)
+ {
+ // s.AddAscii(" : ");
+ // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED);
+ s.AddAscii(" : ");
+ AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
+ }
+ s.AddAscii(" : ");
+ s += fileName;
+ }
+}
+STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted)
+{
+ switch (opRes)
+ {
+ case NArchive::NExtract::NOperationResult::kOK:
+ break;
+ default:
+ {
+ UString s;
+ SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s);
+ Add_ArchiveName_Error();
AddError_Message(s);
}
}
@@ -318,10 +349,22 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, bool encrypted
return S_OK;
}
+STDMETHODIMP CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)
+{
+ if (opRes != NArchive::NExtract::NOperationResult::kOK)
+ {
+ UString s;
+ SetExtractErrorMessage(opRes, encrypted, name, s);
+ Add_ArchiveName_Error();
+ AddError_Message(s);
+ }
+ return S_OK;
+}
+
////////////////////////////////////////
// IExtractCallbackUI
-HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name)
+HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */)
{
#ifndef _SFX
RINOK(ProgressDialog->Sync.CheckStop());
@@ -357,27 +400,6 @@ HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path)
UString HResultToMessage(HRESULT errorCode);
-HRESULT CExtractCallbackImp::OpenResult(const wchar_t *name, HRESULT result, bool encrypted)
-{
- if (result != S_OK)
- {
- UString s;
- if (result == S_FALSE)
- s = MyFormatNew(encrypted ? IDS_CANT_OPEN_ENCRYPTED_ARCHIVE : IDS_CANT_OPEN_ARCHIVE, name);
- else
- {
- s = name;
- s += L": ";
- s += HResultToMessage(result);
- }
- MessageError(s);
- NumArchiveErrors++;
- }
- _currentArchivePath = name;
- _needWriteArchivePath = true;
- return S_OK;
-}
-
static const UInt32 k_ErrorFlagsIds[] =
{
IDS_EXTRACT_MSG_IS_NOT_ARC,
@@ -393,9 +415,16 @@ static const UInt32 k_ErrorFlagsIds[] =
IDS_EXTRACT_MSG_CRC_ERROR
};
+static void AddNewLineString(UString &s, const UString &m)
+{
+ s += m;
+ s.Add_LF();
+}
+
UString GetOpenArcErrorMessage(UInt32 errorFlags)
{
UString s;
+
for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsIds); i++)
{
UInt32 f = ((UInt32)1 << i);
@@ -407,14 +436,15 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags)
continue;
if (f == kpv_ErrorFlags_EncryptedHeadersError)
{
- m += L" : ";
- m += LangString(IDS_EXTRACT_MSG_WRONG_PSW);
+ m.AddAscii(" : ");
+ AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
}
if (!s.IsEmpty())
- s += L'\n';
+ s.Add_LF();
s += m;
errorFlags &= ~f;
}
+
if (errorFlags != 0)
{
char sz[16];
@@ -422,76 +452,153 @@ UString GetOpenArcErrorMessage(UInt32 errorFlags)
sz[1] = 'x';
ConvertUInt32ToHex(errorFlags, sz + 2);
if (!s.IsEmpty())
- s += L'\n';
- s += GetUnicodeString(AString(sz));
+ s.Add_LF();
+ s.AddAscii(sz);
}
+
return s;
}
-HRESULT CExtractCallbackImp::SetError(int level, const wchar_t *name,
- UInt32 errorFlags, const wchar_t *errors,
- UInt32 warningFlags, const wchar_t *warnings)
+static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)
{
- NumArchiveErrors++;
+ UInt32 errorFlags = er.GetErrorFlags();
+ UInt32 warningFlags = er.GetWarningFlags();
- if (_needWriteArchivePath)
+ if (errorFlags != 0)
+ AddNewLineString(s, GetOpenArcErrorMessage(errorFlags));
+
+ if (!er.ErrorMessage.IsEmpty())
+ AddNewLineString(s, er.ErrorMessage);
+
+ if (warningFlags != 0)
{
- if (!_currentArchivePath.IsEmpty())
- AddError_Message(_currentArchivePath);
- _needWriteArchivePath = false;
+ s += GetNameOfProperty(kpidWarningFlags, L"Warnings");
+ s.AddAscii(":");
+ s.Add_LF();
+ AddNewLineString(s, GetOpenArcErrorMessage(warningFlags));
}
-
- if (level != 0)
+
+ if (!er.WarningMessage.IsEmpty())
{
- UString s;
- s += name;
- s += L": ";
- MessageError(s);
+ s += GetNameOfProperty(kpidWarning, L"Warning");
+ s.AddAscii(": ");
+ s += er.WarningMessage;
+ s.Add_LF();
}
+}
- if (errorFlags != 0)
- MessageError(GetOpenArcErrorMessage(errorFlags));
+static UString GetBracedType(const wchar_t *type)
+{
+ UString s = L'[';
+ s += type;
+ s += L']';
+ return s;
+}
- if (errors && wcslen(errors) != 0)
- MessageError(errors);
+void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)
+{
+ FOR_VECTOR (level, arcLink.Arcs)
+ {
+ const CArc &arc = arcLink.Arcs[level];
+ const CArcErrorInfo &er = arc.ErrorInfo;
- if (warningFlags != 0)
- MessageError((UString)L"Warnings: " + GetOpenArcErrorMessage(warningFlags));
+ if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0)
+ continue;
- if (warnings && wcslen(warnings) != 0)
- MessageError((UString)L"Warnings: " + warnings);
+ if (s.IsEmpty())
+ {
+ s += name;
+ s.Add_LF();
+ }
+
+ if (level != 0)
+ {
+ AddNewLineString(s, arc.Path);
+ }
+
+ ErrorInfo_Print(s, er);
- return S_OK;
-}
+ if (er.ErrorFormatIndex >= 0)
+ {
+ AddNewLineString(s, GetNameOfProperty(kpidWarning, L"Warning"));
+ if (arc.FormatIndex == er.ErrorFormatIndex)
+ {
+ AddNewLineString(s, LangString(IDS_IS_OPEN_WITH_OFFSET));
+ }
+ else
+ {
+ AddNewLineString(s, MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(er.ErrorFormatIndex))));
+ AddNewLineString(s, MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(arc.FormatIndex))));
+ }
+ }
+ }
-HRESULT CExtractCallbackImp::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType)
-{
- UString s = L"Warning:\n";
- s += name;
- s += L"\n";
- if (wcscmp(okType, errorType) == 0)
+ if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK)
{
- s += L"The archive is open with offset";
+ s += name;
+ s.Add_LF();
+ if (!arcLink.Arcs.IsEmpty())
+ AddNewLineString(s, arcLink.NonOpen_ArcPath);
+
+ if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result == S_FALSE)
+ {
+ UINT id = IDS_CANT_OPEN_ARCHIVE;
+ UString param;
+ if (arcLink.PasswordWasAsked)
+ id = IDS_CANT_OPEN_ENCRYPTED_ARCHIVE;
+ else if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
+ {
+ id = IDS_CANT_OPEN_AS_TYPE;
+ param = GetBracedType(codecs->GetFormatNamePtr(arcLink.NonOpen_ErrorInfo.ErrorFormatIndex));
+ }
+ UString s2 = MyFormatNew(id, param);
+ s2.Replace(L" ''", L"");
+ s2.Replace(L"''", L"");
+ s += s2;
+ }
+ else
+ s += HResultToMessage(result);
+
+ s.Add_LF();
+ ErrorInfo_Print(s, arcLink.NonOpen_ErrorInfo);
}
- else
+
+ if (!s.IsEmpty() && s.Back() == '\n')
+ s.DeleteBack();
+}
+
+HRESULT CExtractCallbackImp::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)
+{
+ _currentArchivePath = name;
+ _needWriteArchivePath = true;
+
+ UString s;
+ OpenResult_GUI(s, codecs, arcLink, name, result);
+ if (!s.IsEmpty())
{
- s += L"Can not open the file as [";
- s += errorType;
- s += L"] archive\n";
- s += L"The file is open as [";
- s += okType;
- s += L"] archive";
+ NumArchiveErrors++;
+ AddError_Message(s);
+ _needWriteArchivePath = false;
}
- MessageError(s);
- NumArchiveErrors++;
+
return S_OK;
}
-
+
HRESULT CExtractCallbackImp::ThereAreNoFiles()
{
return S_OK;
}
+void CExtractCallbackImp::Add_ArchiveName_Error()
+{
+ if (_needWriteArchivePath)
+ {
+ if (!_currentArchivePath.IsEmpty())
+ AddError_Message(_currentArchivePath);
+ _needWriteArchivePath = false;
+ }
+}
+
HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)
{
if (result == S_OK)
@@ -499,7 +606,10 @@ HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)
NumArchiveErrors++;
if (result == E_ABORT || result == ERROR_DISK_FULL)
return result;
- MessageError(_currentFilePath);
+
+ Add_ArchiveName_Error();
+ if (!_currentFilePath.IsEmpty())
+ MessageError(_currentFilePath);
MessageError(NError::MyFormatMessage(result));
return S_OK;
}
@@ -564,7 +674,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
{
if (!destFileInfo.IsDir())
{
- RINOK(MessageError("can not replace file with folder with same name: ", destPathSys));
+ RINOK(MessageError("can not replace file with folder with same name", destPathSys));
return E_ABORT;
}
*writeAnswer = BoolToInt(false);
@@ -573,8 +683,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
if (destFileInfo.IsDir())
{
- RINOK(MessageError("can not replace folder with file with same name: ", destPathSys));
- return E_FAIL;
+ RINOK(MessageError("can not replace folder with file with same name", destPathSys));
+ *writeAnswer = BoolToInt(false);
+ return S_OK;
}
switch (OverwriteMode)
@@ -583,13 +694,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
return S_OK;
case NExtract::NOverwriteMode::kAsk:
{
- Int32 overwiteResult;
+ Int32 overwriteResult;
UString destPathSpec = destPath;
- int slashPos = destPathSpec.ReverseFind(L'/');
- #ifdef _WIN32
- int slash1Pos = destPathSpec.ReverseFind(L'\\');
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
+ int slashPos = destPathSpec.ReverseFind_PathSepar();
destPathSpec.DeleteFrom(slashPos + 1);
destPathSpec += fs2us(destFileInfo.Name);
@@ -598,9 +705,9 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
&destFileInfo.MTime, &destFileInfo.Size,
srcPath,
srcTime, srcSize,
- &overwiteResult));
+ &overwriteResult));
- switch (overwiteResult)
+ switch (overwriteResult)
{
case NOverwriteAnswer::kCancel: return E_ABORT;
case NOverwriteAnswer::kNo: return S_OK;
@@ -618,7 +725,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
{
if (!AutoRenamePath(destPathSys))
{
- RINOK(MessageError("can not create name for file: ", destPathSys));
+ RINOK(MessageError("can not create name for file", destPathSys));
return E_ABORT;
}
destPathResultTemp = fs2us(destPathSys);
@@ -626,7 +733,7 @@ STDMETHODIMP CExtractCallbackImp::AskWrite(
else
if (!NDir::DeleteFileAlways(destPathSys))
{
- RINOK(MessageError("can not delete output file: ", destPathSys));
+ RINOK(MessageError("can not delete output file", destPathSys));
return E_ABORT;
}
}
@@ -783,7 +890,7 @@ STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)
COM_TRY_END
}
-STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, bool encrypted)
+STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypted)
{
COM_TRY_BEGIN
if (VirtFileSystem && _newVirtFileWasAdded)
@@ -865,7 +972,7 @@ HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
while (_numFlushed < Files.Size())
{
const CVirtFile &file = Files[_numFlushed];
- const FString path = DirPrefix + us2fs(GetCorrectFsPath(file.Name));
+ const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name));
if (!_fileIsOpen)
{
if (!_outFileStreamSpec->Create(path, false))
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h
index 71e48e5e..1654bcd6 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.h
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.h
@@ -36,8 +36,7 @@ class CGrowBuf
Byte *_items;
size_t _size;
- CGrowBuf(const CGrowBuf &buffer);
- void operator=(const CGrowBuf &buffer);
+ CLASS_NO_COPY(CGrowBuf);
public:
bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
@@ -45,7 +44,8 @@ public:
void *buf = MyAlloc(newSize);
if (!buf)
return false;
- memcpy(buf, _items, keepSize);
+ if (keepSize != 0)
+ memcpy(buf, _items, keepSize);
MyFree(_items);
_items = (Byte *)buf;
_size = newSize;
@@ -55,8 +55,8 @@ public:
CGrowBuf(): _items(0), _size(0) {}
~CGrowBuf() { MyFree(_items); }
- operator Byte *() { return _items; };
- operator const Byte *() const { return _items; };
+ operator Byte *() { return _items; }
+ operator const Byte *() const { return _items; }
size_t Size() const { return _size; }
};
@@ -135,10 +135,11 @@ public:
{
if (_fileMode)
return false;
- if (Files.Size() < 1 || Files[0].IsAltStream || Files[0].IsDir)
+ if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir)
return false;
return true;
}
+
size_t GetMemStreamWrittenSize() const { return _pos; }
CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
@@ -165,6 +166,7 @@ public:
class CExtractCallbackImp:
public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback
public IOpenCallbackUI,
+ public IFolderArchiveExtractCallback2,
#ifndef _SFX
public IFolderOperationsExtractCallback,
public IFolderExtractToStreamCallback,
@@ -176,8 +178,10 @@ class CExtractCallbackImp:
public CMyUnknownImp
{
HRESULT MessageError(const char *message, const FString &path);
+ void Add_ArchiveName_Error();
public:
MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
+ MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
#ifndef _SFX
MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)
MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)
@@ -191,33 +195,12 @@ public:
INTERFACE_IProgress(;)
INTERFACE_IOpenCallbackUI(;)
-
- // IFolderArchiveExtractCallback
+ INTERFACE_IFolderArchiveExtractCallback(;)
+ INTERFACE_IFolderArchiveExtractCallback2(;)
// STDMETHOD(SetTotalFiles)(UInt64 total);
// STDMETHOD(SetCompletedFiles)(const UInt64 *value);
- STDMETHOD(AskOverwrite)(
- const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
- const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
- Int32 *answer);
- STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);
- STDMETHOD(MessageError)(const wchar_t *message);
- STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);
-
- // IExtractCallbackUI
-
- HRESULT BeforeOpen(const wchar_t *name);
- HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);
- HRESULT SetError(int level, const wchar_t *name,
- UInt32 errorFlags, const wchar_t *errors,
- UInt32 warningFlags, const wchar_t *warnings);
- HRESULT ThereAreNoFiles();
- HRESULT ExtractResult(HRESULT result);
- HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType);
-
- #ifndef _NO_CRYPTO
- HRESULT SetPassword(const UString &password);
- #endif
+ INTERFACE_IExtractCallbackUI(;)
#ifndef _SFX
// IFolderOperationsExtractCallback
@@ -295,6 +278,12 @@ public:
UString Password;
#endif
+
+ UString _lang_Extracting;
+ UString _lang_Testing;
+ UString _lang_Skipping;
+ UString _lang_Empty;
+
CExtractCallbackImp():
#ifndef _NO_CRYPTO
PasswordIsDefined(false),
diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp
index 537103ae..00b152c8 100644
--- a/CPP/7zip/UI/FileManager/FM.cpp
+++ b/CPP/7zip/UI/FileManager/FM.cpp
@@ -49,6 +49,9 @@ static UString g_MainPath;
static UString g_ArcFormat;
static bool g_Maximized = false;
+// HRESULT LoadGlobalCodecs();
+void FreeGlobalCodecs();
+
#ifndef UNDER_CE
DWORD g_ComCtl32Version;
@@ -568,6 +571,13 @@ static int WINAPI WinMain2(int nCmdShow)
if (!InitInstance (nCmdShow))
return FALSE;
+ // we will load Global_Codecs at first use instead.
+ /*
+ OutputDebugStringW(L"Before LoadGlobalCodecs");
+ LoadGlobalCodecs();
+ OutputDebugStringW(L"After LoadGlobalCodecs");
+ */
+
#ifndef _UNICODE
if (g_IsNT)
{
@@ -597,6 +607,10 @@ static int WINAPI WinMain2(int nCmdShow)
}
}
+ // Destructor of g_CodecsReleaser can release DLLs.
+ // But we suppose that it's better to release DLLs here (before destructor).
+ FreeGlobalCodecs();
+
g_HWND = 0;
#ifndef UNDER_CE
OleUninitialize();
@@ -780,35 +794,45 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
xSizes[1] = 0;
g_App.CreateDragTarget();
+
bool archiveIsOpened;
bool encrypted;
bool needOpenFile = false;
- if (!g_MainPath.IsEmpty() /* && g_OpenArchive */)
+
+ UString fullPath = g_MainPath;
+ if (!fullPath.IsEmpty() /* && g_OpenArchive */)
{
- if (NFile::NFind::DoesFileExist(us2fs(g_MainPath)))
+ if (!NFile::NName::IsAbsolutePath(fullPath))
+ {
+ FString fullPathF;
+ if (NFile::NName::GetFullPath(us2fs(fullPath), fullPathF))
+ fullPath = fs2us(fullPathF);
+ }
+ if (NFile::NFind::DoesFileExist(us2fs(fullPath)))
needOpenFile = true;
}
- HRESULT res = g_App.Create(hWnd, g_MainPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted);
+
+ HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted);
if (res == E_ABORT)
- {
return -1;
- }
+
if (needOpenFile && !archiveIsOpened || res != S_OK)
{
UString message = L"Error";
if (res == S_FALSE || res == S_OK)
{
message = MyFormatNew(encrypted ?
- IDS_CANT_OPEN_ENCRYPTED_ARCHIVE :
- IDS_CANT_OPEN_ARCHIVE,
- g_MainPath);
+ IDS_CANT_OPEN_ENCRYPTED_ARCHIVE :
+ IDS_CANT_OPEN_ARCHIVE,
+ fullPath);
}
else if (res != S_OK)
message = HResultToMessage(res);
ErrorMessage(message);
return -1;
}
+
// g_SplitterPos = 0;
// ::DragAcceptFiles(hWnd, TRUE);
@@ -816,6 +840,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
}
+
case WM_DESTROY:
{
// ::DragAcceptFiles(hWnd, FALSE);
@@ -839,11 +864,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
g_StartCaptureSplitterPos = g_Splitter.GetPos();
::SetCapture(hWnd);
break;
+
case WM_LBUTTONUP:
{
::ReleaseCapture();
break;
}
+
case WM_MOUSEMOVE:
{
if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd)
@@ -880,10 +907,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
break;
}
+
case WM_SETFOCUS:
// g_App.SetFocus(g_App.LastFocusedPanel);
g_App.SetFocusToLastItem();
break;
+
/*
case WM_ACTIVATE:
{
@@ -900,6 +929,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
}
*/
+
/*
case kLangWasChangedMessage:
MyLoadMenu();
@@ -910,11 +940,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_SETTINGCHANGE:
break;
*/
+
case WM_NOTIFY:
{
g_App.OnNotify((int)wParam, (LPNMHDR)lParam);
break;
}
+
/*
case WM_DROPFILES:
{
diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp
index 4a7f16a6..f18e5441 100644
--- a/CPP/7zip/UI/FileManager/FM.dsp
+++ b/CPP/7zip/UI/FileManager/FM.dsp
@@ -219,6 +219,14 @@ SOURCE=.\Test.bmp
# PROP Default_Filter ""
# Begin Source File
+SOURCE=.\AltStreamsFolder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\AltStreamsFolder.h
+# End Source File
+# Begin Source File
+
SOURCE=.\FSDrives.cpp
# End Source File
# Begin Source File
@@ -1026,6 +1034,10 @@ SOURCE=..\..\..\Windows\Window.h
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\..\Common\Common.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\ComTry.h
# End Source File
# Begin Source File
@@ -1399,6 +1411,14 @@ SOURCE=..\GUI\HashGUI.cpp
SOURCE=..\GUI\HashGUI.h
# End Source File
+# Begin Source File
+
+SOURCE=..\GUI\UpdateCallbackGUI2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\GUI\UpdateCallbackGUI2.h
+# End Source File
# End Group
# End Group
# Begin Group "Compress"
diff --git a/CPP/7zip/UI/FileManager/FM.mak b/CPP/7zip/UI/FileManager/FM.mak
index 234a5920..6a85ea2f 100644
--- a/CPP/7zip/UI/FileManager/FM.mak
+++ b/CPP/7zip/UI/FileManager/FM.mak
@@ -60,6 +60,7 @@ FM_OBJS = \
!IFNDEF UNDER_CE
FM_OBJS = $(FM_OBJS) \
+ $O\AltStreamsFolder.obj \
$O\FSDrives.obj \
$O\LinkDialog.obj \
$O\NetFolder.obj \
diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp
index 84639de7..69f89325 100644
--- a/CPP/7zip/UI/FileManager/FSDrives.cpp
+++ b/CPP/7zip/UI/FileManager/FSDrives.cpp
@@ -11,6 +11,7 @@
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileIO.h"
+#include "../../../Windows/FileName.h"
#include "../../../Windows/FileSystem.h"
#include "../../../Windows/PropVariant.h"
@@ -27,8 +28,8 @@ using namespace NWindows;
using namespace NFile;
using namespace NFind;
-static CFSTR kVolPrefix = FTEXT("\\\\.\\");
-static CFSTR kLongPrefix = FTEXT("\\\\?\\");
+static const CFSTR kVolPrefix = FTEXT("\\\\.\\");
+static const CFSTR kSuperPrefix = FTEXT("\\\\?\\");
FString CDriveInfo::GetDeviceFileIoName() const
{
@@ -53,6 +54,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
if (!inFile.GetLength(fileSize))
::GetLastError();
}
+
NIO::COutFile outFile;
if (writeToDisk)
{
@@ -62,6 +64,7 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
else
if (!outFile.Create(toPath, true))
return GetLastError();
+
CPhysTempBuffer tempBuffer;
tempBuffer.buffer = MidAlloc(bufferSize);
if (!tempBuffer.buffer)
@@ -93,12 +96,14 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
return E_FAIL;
pos += curSize;
}
+
return S_OK;
}
static const PROPID kProps[] =
{
kpidName,
+ // kpidOutName,
kpidTotalSize,
kpidFreeSpace,
kpidType,
@@ -107,7 +112,7 @@ static const PROPID kProps[] =
kpidClusterSize
};
-static const char *kDriveTypes[] =
+static const char * const kDriveTypes[] =
{
"Unknown"
, "No Root Dir"
@@ -219,6 +224,16 @@ STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT
{
case kpidIsDir: prop = !_volumeMode; break;
case kpidName: prop = di.Name; break;
+ case kpidOutName:
+ if (!di.Name.IsEmpty() && di.Name.Back() == ':')
+ {
+ FString s = di.Name;
+ s.DeleteBack();
+ AddExt(s, itemIndex);
+ prop = s;
+ }
+ break;
+
case kpidTotalSize: if (di.KnownSize) prop = di.DriveSize; break;
case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break;
case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break;
@@ -240,14 +255,11 @@ HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
return S_OK;
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
- if (_longMode)
- {
- RINOK(fsFolderSpec->Init((FString)kLongPrefix + name, 0));
- }
- else
- {
- RINOK(fsFolderSpec->Init(name, 0));
- }
+ FString path;
+ if (_superMode)
+ path = kSuperPrefix;
+ path += name;
+ RINOK(fsFolderSpec->Init(path));
*resultFolder = subFolder.Detach();
return S_OK;
}
@@ -295,8 +307,8 @@ STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value)
case kpidPath:
if (_volumeMode)
prop = kVolPrefix;
- else if (_longMode)
- prop = kLongPrefix;
+ else if (_superMode)
+ prop = kSuperPrefix;
else
prop = (UString)LangString(IDS_COMPUTER) + WCHAR_PATH_SEPARATOR;
break;
@@ -322,19 +334,20 @@ STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
return GetLastError();
}
-const wchar_t *CFSDrives::GetExt(unsigned index) const
+void CFSDrives::AddExt(FString &s, unsigned index) const
{
+ s += FTEXT('.');
const CDriveInfo &di = _drives[index];
- const wchar_t *ext;
+ const char *ext;
if (di.DriveType == DRIVE_CDROM)
- ext = L"iso";
- else if (di.FileSystemName.Find(L"NTFS") >= 0)
- ext = L"ntfs";
- else if (di.FileSystemName.Find(L"FAT") >= 0)
- ext = L"fat";
+ ext = "iso";
+ else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("NTFS"))
+ ext = "ntfs";
+ else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("FAT"))
+ ext = "fat";
else
- ext = L"img";
- return ext;
+ ext = "img";
+ s.AddAscii(ext);
}
HRESULT CFSDrives::GetFileSize(unsigned index, UInt64 &fileSize) const
@@ -352,12 +365,12 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
const wchar_t *path, IFolderOperationsExtractCallback *callback)
{
- if (moveMode)
- return E_NOTIMPL;
-
if (numItems == 0)
return S_OK;
+ if (moveMode)
+ return E_NOTIMPL;
+
if (!_volumeMode)
return E_NOTIMPL;
@@ -372,11 +385,14 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
RINOK(callback->SetTotal(totalSize));
RINOK(callback->SetNumFiles(numItems));
- UString destPath = path;
+ FString destPath = us2fs(path);
if (destPath.IsEmpty())
return E_INVALIDARG;
- bool directName = (destPath.Back() != WCHAR_PATH_SEPARATOR);
- if (directName)
+
+ bool isAltDest = NName::IsAltPathPrefix(destPath);
+ bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
+
+ if (isDirectPath)
{
if (numItems > 1)
return E_INVALIDARG;
@@ -389,19 +405,19 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
{
unsigned index = indices[i];
const CDriveInfo &di = _drives[index];
- UString destPath2 = destPath;
- UString name = fs2us(di.Name);
- if (!directName)
+ FString destPath2 = destPath;
+
+ if (!isDirectPath)
{
- UString destName = name;
- if (!destName.IsEmpty() && destName.Back() == L':')
+ FString destName = di.Name;
+ if (!destName.IsEmpty() && destName.Back() == ':')
{
destName.DeleteBack();
- destName += L'.';
- destName += GetExt(index);
+ AddExt(destName, index);
}
destPath2 += destName;
}
+
FString srcPath = di.GetDeviceFileIoName();
UInt64 fileSize = 0;
@@ -410,15 +426,23 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
return E_FAIL;
}
if (!di.KnownSize)
+ {
totalSize += fileSize;
- RINOK(callback->SetTotal(totalSize));
+ RINOK(callback->SetTotal(totalSize));
+ }
Int32 writeAskResult;
CMyComBSTR destPathResult;
RINOK(callback->AskWrite(fs2us(srcPath), BoolToInt(false), NULL, &fileSize,
- destPath2, &destPathResult, &writeAskResult));
+ fs2us(destPath2), &destPathResult, &writeAskResult));
+
if (!IntToBool(writeAskResult))
+ {
+ if (totalSize >= fileSize)
+ totalSize -= fileSize;
+ RINOK(callback->SetTotal(totalSize));
continue;
+ }
RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
@@ -427,11 +451,12 @@ STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
RINOK(CopyFileSpec(srcPath, us2fs(destPathResult), false, fileSize, bufferSize, completedSize, callback));
completedSize += fileSize;
}
+
return S_OK;
}
STDMETHODIMP CFSDrives::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
- const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
+ const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h
index a8e25d7d..f12e4da8 100644
--- a/CPP/7zip/UI/FileManager/FSDrives.h
+++ b/CPP/7zip/UI/FileManager/FSDrives.h
@@ -36,10 +36,10 @@ class CFSDrives:
{
CObjectVector<CDriveInfo> _drives;
bool _volumeMode;
- bool _longMode;
+ bool _superMode;
HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder);
- const wchar_t *GetExt(unsigned index) const;
+ void AddExt(FString &s, unsigned index) const;
HRESULT GetFileSize(unsigned index, UInt64 &fileSize) const;
public:
MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations)
@@ -49,10 +49,10 @@ public:
STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
- void Init(bool volMode = false, bool longMode = false)
+ void Init(bool volMode = false, bool superMode = false)
{
_volumeMode = volMode;
- _longMode = longMode;
+ _superMode = superMode;
}
};
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp
index a27066c3..e46afb9e 100644
--- a/CPP/7zip/UI/FileManager/FSFolder.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolder.cpp
@@ -29,7 +29,7 @@
// But real support version for that function is NT 3.1 (probably)
// So we must define GetCompressedFileSizeW
EXTERN_C_BEGIN
-WINBASEAPI DWORD WINAPI GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh );
+WINBASEAPI DWORD WINAPI GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh);
EXTERN_C_END
#endif
#endif
@@ -68,20 +68,23 @@ static const Byte kProps[] =
kpidPrefix
};
-HRESULT CFSFolder::Init(const FString &path, IFolderFolder *parentFolder)
+HRESULT CFSFolder::Init(const FString &path /* , IFolderFolder *parentFolder */)
{
- _parentFolder = parentFolder;
+ // _parentFolder = parentFolder;
_path = path;
_findChangeNotification.FindFirst(_path, false,
- FILE_NOTIFY_CHANGE_FILE_NAME |
- FILE_NOTIFY_CHANGE_DIR_NAME |
- FILE_NOTIFY_CHANGE_ATTRIBUTES |
- FILE_NOTIFY_CHANGE_SIZE |
- FILE_NOTIFY_CHANGE_LAST_WRITE /*|
- FILE_NOTIFY_CHANGE_LAST_ACCESS |
- FILE_NOTIFY_CHANGE_CREATION |
- FILE_NOTIFY_CHANGE_SECURITY */);
+ FILE_NOTIFY_CHANGE_FILE_NAME
+ | FILE_NOTIFY_CHANGE_DIR_NAME
+ | FILE_NOTIFY_CHANGE_ATTRIBUTES
+ | FILE_NOTIFY_CHANGE_SIZE
+ | FILE_NOTIFY_CHANGE_LAST_WRITE
+ /*
+ | FILE_NOTIFY_CHANGE_LAST_ACCESS
+ | FILE_NOTIFY_CHANGE_CREATION
+ | FILE_NOTIFY_CHANGE_SECURITY
+ */
+ );
if (!_findChangeNotification.IsHandleAllocated())
{
DWORD lastError = GetLastError();
@@ -99,7 +102,7 @@ HRESULT CFsFolderStat::Enumerate()
{
RINOK(Progress->SetCompleted(NULL));
}
- Path += FCHAR_PATH_SEPARATOR;
+ Path.Add_PathSepar();
unsigned len = Path.Len();
Path += FCHAR_ANY_MASK;
CEnumerator enumerator(Path);
@@ -124,7 +127,7 @@ HRESULT CFsFolderStat::Enumerate()
#ifndef UNDER_CE
-static bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size)
+bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size)
{
DWORD highPart;
DWORD lowPart = INVALID_FILE_SIZE;
@@ -140,10 +143,10 @@ static bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size)
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH)
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
{
- lowPart = ::GetCompressedFileSizeW(longPath, &highPart);
+ lowPart = ::GetCompressedFileSizeW(superPath, &highPart);
if (lowPart != INVALID_FILE_SIZE || ::GetLastError() == NO_ERROR)
{
size = ((UInt64)highPart << 32) | lowPart;
@@ -279,11 +282,10 @@ bool CFSFolder::LoadComments()
if (len >= (1 << 28))
return false;
AString s;
- char *p = s.GetBuffer((unsigned)((size_t)len + 1));
+ char *p = s.GetBuf((unsigned)(size_t)len);
UInt32 processedSize;
file.Read(p, (UInt32)len, processedSize);
- p[len] = 0;
- s.ReleaseBuffer();
+ s.ReleaseBuf_CalcLen((unsigned)(size_t)len);
if (processedSize != len)
return false;
file.Close();
@@ -293,14 +295,6 @@ bool CFSFolder::LoadComments()
return _comments.ReadFromString(unicodeString);
}
-static bool IsAscii(const AString &s)
-{
- for (unsigned i = 0; i < s.Len(); i++)
- if ((Byte)s[i] >= 0x80)
- return false;
- return true;
-}
-
bool CFSFolder::SaveComments()
{
AString utf;
@@ -309,7 +303,7 @@ bool CFSFolder::SaveComments()
_comments.SaveToString(unicode);
ConvertUnicodeToUTF8(unicode, utf);
}
- if (!IsAscii(utf))
+ if (!utf.IsAscii())
utf.Insert(0, "\xEF\xBB\xBF" "\r\n");
FString path = _path + kDescriptionFileName;
@@ -576,7 +570,7 @@ STDMETHODIMP CFSFolder::GetRawProp(UInt32
static inline CFSTR GetExtensionPtr(const FString &name)
{
- int dotPos = name.ReverseFind(FTEXT('.'));
+ int dotPos = name.ReverseFind_Dot();
return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
}
@@ -686,7 +680,7 @@ HRESULT CFSFolder::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
*resultFolder = 0;
CFSFolder *folderSpec = new CFSFolder;
CMyComPtr<IFolderFolder> subFolder = folderSpec;
- RINOK(folderSpec->Init(_path + name + FCHAR_PATH_SEPARATOR, 0));
+ RINOK(folderSpec->Init(_path + name + FCHAR_PATH_SEPARATOR));
*resultFolder = subFolder.Detach();
return S_OK;
}
@@ -700,6 +694,7 @@ void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const
prefix.Empty();
}
*/
+
/*
void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const
{
@@ -714,20 +709,17 @@ void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const
parent = cur.Parent;
}
- unsigned totalLen = len;
- wchar_t *p = prefix.GetBuffer(len);
+ wchar_t *p = prefix.GetBuf_SetEnd(len) + len;
parent = item.Parent;
while (parent >= 0)
{
const CDirItem &cur = Files[parent];
- // path = cur->Name + FCHAR_PATH_SEPARATOR + path;
- MyStringCopy(p + len - cur.Name.Len() - 1, (const wchar_t *)cur.Name);
- p[--len] = FCHAR_PATH_SEPARATOR;
- len -= cur.Name.Len();
+ *(--p) = FCHAR_PATH_SEPARATOR;
+ p -= cur.Name.Len();
+ wmemcpy(p, cur.Name, cur.Name.Len());
parent = cur.Parent;
}
- prefix.ReleaseBuffer(totalLen);
}
*/
@@ -752,24 +744,26 @@ STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **result
return BindToFolderSpec(us2fs(name), resultFolder);
}
-static CFSTR kLongPrefix = FTEXT("\\\\?\\");
+static const CFSTR kSuperPrefix = FTEXT("\\\\?\\");
STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
{
*resultFolder = 0;
+ /*
if (_parentFolder)
{
CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
*resultFolder = parentFolder.Detach();
return S_OK;
}
+ */
if (_path.IsEmpty())
return E_INVALIDARG;
- int pos = _path.ReverseFind(FCHAR_PATH_SEPARATOR);
+ int pos = _path.ReverseFind_PathSepar();
if (pos < 0 || pos != (int)_path.Len() - 1)
return E_FAIL;
FString parentPath = _path.Left(pos);
- pos = parentPath.ReverseFind(FCHAR_PATH_SEPARATOR);
+ pos = parentPath.ReverseFind_PathSepar();
if (pos < 0)
{
#ifdef UNDER_CE
@@ -783,9 +777,10 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
return S_OK;
}
+ /*
parentPath.DeleteFrom(pos + 1);
- if (parentPath == kLongPrefix)
+ if (parentPath == kSuperPrefix)
{
#ifdef UNDER_CE
*resultFolder = 0;
@@ -801,10 +796,10 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
FString parentPathReduced = parentPath.Left(pos);
#ifndef UNDER_CE
- pos = parentPathReduced.ReverseFind(FCHAR_PATH_SEPARATOR);
+ pos = parentPathReduced.ReverseFind_PathSepar();
if (pos == 1)
{
- if (parentPath[0] != FCHAR_PATH_SEPARATOR)
+ if (!IS_PATH_SEPAR_CHAR(parentPath[0]))
return E_FAIL;
CNetFolder *netFolderSpec = new CNetFolder;
CMyComPtr<IFolderFolder> netFolder = netFolderSpec;
@@ -818,6 +813,7 @@ STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;
RINOK(parentFolderSpec->Init(parentPath, 0));
*resultFolder = parentFolder.Detach();
+ */
return S_OK;
}
@@ -837,7 +833,7 @@ STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
switch (propID)
{
- case kpidType: prop = L"FSFolder"; break;
+ case kpidType: prop = "FSFolder"; break;
case kpidPath: prop = fs2us(_path); break;
}
prop.Detach(value);
@@ -874,7 +870,7 @@ STDMETHODIMP CFSFolder::Clone(IFolderFolder **resultFolder)
{
CFSFolder *fsFolderSpec = new CFSFolder;
CMyComPtr<IFolderFolder> folderNew = fsFolderSpec;
- fsFolderSpec->Init(_path, 0);
+ fsFolderSpec->Init(_path);
*resultFolder = folderNew.Detach();
return S_OK;
}
@@ -1060,7 +1056,7 @@ STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID,
CTextPair pair;
pair.ID = filename;
pair.ID.Trim();
- pair.Value = value->bstrVal;
+ pair.Value.SetFromBstr(value->bstrVal);
pair.Value.Trim();
if (pair.Value.IsEmpty())
_comments.DeletePair(filename);
diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h
index cb0d4ec2..057ba14c 100644
--- a/CPP/7zip/UI/FileManager/FSFolder.h
+++ b/CPP/7zip/UI/FileManager/FSFolder.h
@@ -8,9 +8,10 @@
#include "../../../Windows/FileFind.h"
+#include "../../Archive/IArchive.h"
+
#include "IFolder.h"
#include "TextPairs.h"
-#include "..\..\Archive\IArchive.h"
namespace NFsFolder {
@@ -133,7 +134,7 @@ private:
CObjectVector<CDirItem> Files;
FStringVector Folders;
// CObjectVector<CAltStream> Streams;
- CMyComPtr<IFolderFolder> _parentFolder;
+ // CMyComPtr<IFolderFolder> _parentFolder;
bool _commentsAreLoaded;
CPairsStorage _comments;
@@ -158,9 +159,9 @@ private:
#endif
public:
- HRESULT Init(const FString &path, IFolderFolder *parentFolder);
- #ifdef UNDER_CE
- HRESULT InitToRoot() { return Init(FTEXT("\\"), NULL); }
+ HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */);
+ #if !defined(_WIN32) || defined(UNDER_CE)
+ HRESULT InitToRoot() { return Init(FSTRING_PATH_SEPARATOR /* , NULL */); }
#endif
CFSFolder() : _flatMode(false)
@@ -178,6 +179,7 @@ public:
}
// void GetPrefix(const CDirItem &item, FString &prefix) const;
+
FString GetRelPath(const CDirItem &item) const;
void Clear()
@@ -188,6 +190,24 @@ public:
}
};
+struct CCopyStateIO
+{
+ IProgress *Progress;
+ UInt64 TotalSize;
+ UInt64 StartPos;
+ UInt64 CurrentSize;
+ bool DeleteSrcFile;
+
+ int ErrorFileIndex;
+ UString ErrorMessage;
+
+ CCopyStateIO(): DeleteSrcFile(false), TotalSize(0), StartPos(0) {}
+
+ HRESULT MyCopyFile(CFSTR inPath, CFSTR outPath);
+};
+
+HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName);
+
}
#endif
diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
index 3f2fc9af..54dabc57 100644
--- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
@@ -29,6 +29,75 @@ extern bool g_IsNT;
namespace NFsFolder {
+HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath)
+{
+ ErrorFileIndex = -1;
+ ErrorMessage.Empty();
+ CurrentSize = 0;
+
+ {
+ const size_t kBufSize = 1 << 16;
+ CByteArr buf(kBufSize);
+
+ NIO::CInFile inFile;
+ NIO::COutFile outFile;
+
+ if (!inFile.Open(inPath))
+ {
+ ErrorFileIndex = 0;
+ return S_OK;
+ }
+
+ if (!outFile.Create(outPath, true))
+ {
+ ErrorFileIndex = 1;
+ return S_OK;
+ }
+
+ for (;;)
+ {
+ UInt32 num;
+ if (!inFile.Read(buf, kBufSize, num))
+ {
+ ErrorFileIndex = 0;
+ return S_OK;
+ }
+ if (num == 0)
+ break;
+
+ UInt32 written = 0;
+ if (!outFile.Write(buf, num, written))
+ {
+ ErrorFileIndex = 1;
+ return S_OK;
+ }
+ if (written != num)
+ {
+ ErrorMessage = L"Write error";
+ return S_OK;
+ }
+ CurrentSize += num;
+ if (Progress)
+ {
+ UInt64 completed = StartPos + CurrentSize;
+ RINOK(Progress->SetCompleted(&completed));
+ }
+ }
+ }
+
+ if (DeleteSrcFile)
+ {
+ if (!DeleteFileAlways(inPath))
+ {
+ ErrorFileIndex = 0;
+ return S_OK;
+ }
+ }
+
+ return S_OK;
+}
+
+
/*
static bool IsItWindows2000orHigher()
{
@@ -43,8 +112,13 @@ static bool IsItWindows2000orHigher()
struct CProgressInfo
{
+ UInt64 TotalSize;
UInt64 StartPos;
+ UInt64 FileSize;
IProgress *Progress;
+ HRESULT ProgressResult;
+
+ void Init() { ProgressResult = S_OK; }
};
#ifndef PROGRESS_CONTINUE
@@ -71,7 +145,7 @@ DWORD
#endif
static DWORD CALLBACK CopyProgressRoutine(
- LARGE_INTEGER /* TotalFileSize */, // file size
+ LARGE_INTEGER TotalFileSize, // file size
LARGE_INTEGER TotalBytesTransferred, // bytes transferred
LARGE_INTEGER /* StreamSize */, // bytes in stream
LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream
@@ -82,14 +156,27 @@ static DWORD CALLBACK CopyProgressRoutine(
LPVOID lpData // from CopyFileEx
)
{
- CProgressInfo &progressInfo = *(CProgressInfo *)lpData;
- UInt64 completed = progressInfo.StartPos + TotalBytesTransferred.QuadPart;
- if (progressInfo.Progress->SetCompleted(&completed) != S_OK)
- return PROGRESS_CANCEL;
- return PROGRESS_CONTINUE;
+ TotalFileSize = TotalFileSize;
+ // TotalBytesTransferred = TotalBytesTransferred;
+ // StreamSize = StreamSize;
+ // StreamBytesTransferred = StreamBytesTransferred;
+ // dwStreamNumber = dwStreamNumber;
+ // dwCallbackReason = dwCallbackReason;
+
+ CProgressInfo &pi = *(CProgressInfo *)lpData;
+
+ if ((UInt64)TotalFileSize.QuadPart > pi.FileSize)
+ {
+ pi.TotalSize += (UInt64)TotalFileSize.QuadPart - pi.FileSize;
+ pi.FileSize = (UInt64)TotalFileSize.QuadPart;
+ pi.ProgressResult = pi.Progress->SetTotal(pi.TotalSize);
+ }
+ UInt64 completed = pi.StartPos + TotalBytesTransferred.QuadPart;
+ pi.ProgressResult = pi.Progress->SetCompleted(&completed);
+ return (pi.ProgressResult == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL);
}
-typedef BOOL (WINAPI * CopyFileExPointer)(
+typedef BOOL (WINAPI * Func_CopyFileExA)(
IN LPCSTR lpExistingFileName,
IN LPCSTR lpNewFileName,
IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
@@ -98,7 +185,7 @@ typedef BOOL (WINAPI * CopyFileExPointer)(
IN DWORD dwCopyFlags
);
-typedef BOOL (WINAPI * CopyFileExPointerW)(
+typedef BOOL (WINAPI * Func_CopyFileExW)(
IN LPCWSTR lpExistingFileName,
IN LPCWSTR lpNewFileName,
IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
@@ -107,110 +194,152 @@ typedef BOOL (WINAPI * CopyFileExPointerW)(
IN DWORD dwCopyFlags
);
-static bool FsCopyFile(CFSTR oldFile, CFSTR newFile, IProgress *progress, UInt64 &completedSize)
+typedef BOOL (WINAPI * Func_MoveFileWithProgressW)(
+ IN LPCWSTR lpExistingFileName,
+ IN LPCWSTR lpNewFileName,
+ IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
+ IN LPVOID lpData OPTIONAL,
+ IN DWORD dwFlags
+ );
+
+struct CCopyState
{
- CProgressInfo progressInfo;
- progressInfo.Progress = progress;
- progressInfo.StartPos = completedSize;
- BOOL CancelFlag = FALSE;
+ CProgressInfo ProgressInfo;
+ IFolderOperationsExtractCallback *Callback;
+ UInt64 TotalSize;
+ bool MoveMode;
+ bool UseReadWriteMode;
+
+ Func_CopyFileExW my_CopyFileExW;
+ #ifndef UNDER_CE
+ Func_MoveFileWithProgressW my_MoveFileWithProgressW;
+ #endif
#ifndef _UNICODE
- if (g_IsNT)
+ Func_CopyFileExA my_CopyFileExA;
+ #endif
+
+ void Prepare();
+ bool CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile);
+ bool CopyFile_Sys(CFSTR oldFile, CFSTR newFile);
+ bool MoveFile_Sys(CFSTR oldFile, CFSTR newFile);
+
+ HRESULT CallProgress();
+
+ bool IsCallbackProgressError() { return ProgressInfo.ProgressResult != S_OK; }
+};
+
+HRESULT CCopyState::CallProgress()
+{
+ return ProgressInfo.Progress->SetCompleted(&ProgressInfo.StartPos);
+}
+
+void CCopyState::Prepare()
+{
+ my_CopyFileExW = NULL;
+ #ifndef UNDER_CE
+ my_MoveFileWithProgressW = NULL;
#endif
+ #ifndef _UNICODE
+ my_CopyFileExA = NULL;
+ if (!g_IsNT)
{
- const wchar_t *k_DllName =
- #ifdef UNDER_CE
+ my_CopyFileExA = (Func_CopyFileExA)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "CopyFileExA");
+ }
+ else
+ #endif
+ {
+ HMODULE module = ::GetModuleHandleW(
+ #ifdef UNDER_CE
L"coredll.dll"
- #else
+ #else
L"kernel32.dll"
- #endif
- ;
- CopyFileExPointerW copyFunctionW = (CopyFileExPointerW)
- My_GetProcAddress(::GetModuleHandleW(k_DllName), "CopyFileExW");
-
+ #endif
+ );
+ my_CopyFileExW = (Func_CopyFileExW)My_GetProcAddress(module, "CopyFileExW");
+ #ifndef UNDER_CE
+ my_MoveFileWithProgressW = (Func_MoveFileWithProgressW)My_GetProcAddress(module, "MoveFileWithProgressW");
+ #endif
+ }
+}
+
+/* WinXP-64:
+ CopyFileW(fromFile, toFile:altStream)
+ OK - there are NO alt streams in fromFile
+ ERROR_INVALID_PARAMETER - there are alt streams in fromFile
+*/
+
+bool CCopyState::CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile)
+{
+ BOOL cancelFlag = FALSE;
+ if (my_CopyFileExW)
+ return BOOLToBool(my_CopyFileExW(oldFile, newFile, CopyProgressRoutine,
+ &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS));
+ return BOOLToBool(::CopyFileW(oldFile, newFile, TRUE));
+}
+
+bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ if (my_CopyFileExA)
+ {
+ BOOL cancelFlag = FALSE;
+ if (my_CopyFileExA(fs2fas(oldFile), fs2fas(newFile),
+ CopyProgressRoutine, &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS))
+ return true;
+ if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return false;
+ }
+ return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE));
+ }
+ else
+ #endif
+ {
IF_USE_MAIN_PATH_2(oldFile, newFile)
{
- if (copyFunctionW == 0)
- return BOOLToBool(::CopyFileW(fs2us(oldFile), fs2us(newFile), TRUE));
- if (copyFunctionW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
- &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))
+ if (CopyFile_NT(fs2us(oldFile), fs2us(newFile)))
return true;
}
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH_2)
{
- UString longPathExisting, longPathNew;
- if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2))
+ if (IsCallbackProgressError())
+ return false;
+ UString superPathOld, superPathNew;
+ if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
return false;
- if (copyFunctionW(longPathExisting, longPathNew, CopyProgressRoutine,
- &progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))
+ if (CopyFile_NT(superPathOld, superPathNew))
return true;
}
#endif
return false;
}
- #ifndef _UNICODE
- else
- {
- CopyFileExPointer copyFunction = (CopyFileExPointer)
- ::GetProcAddress(::GetModuleHandleA("kernel32.dll"),
- "CopyFileExA");
- if (copyFunction != 0)
- {
- if (copyFunction(fs2fas(oldFile), fs2fas(newFile),
- CopyProgressRoutine,&progressInfo, &CancelFlag, COPY_FILE_FAIL_IF_EXISTS))
- return true;
- if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
- return false;
- }
- return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE));
- }
- #endif
}
-typedef BOOL (WINAPI * MoveFileWithProgressPointer)(
- IN LPCWSTR lpExistingFileName,
- IN LPCWSTR lpNewFileName,
- IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
- IN LPVOID lpData OPTIONAL,
- IN DWORD dwFlags
- );
-
-#ifdef UNDER_CE
-#define NON_CE_VAR(_v_)
-#else
-#define NON_CE_VAR(_v_) _v_
-#endif
-
-static bool FsMoveFile(CFSTR oldFile, CFSTR newFile,
- IProgress * NON_CE_VAR(progress),
- UInt64 & NON_CE_VAR(completedSize))
+bool CCopyState::MoveFile_Sys(CFSTR oldFile, CFSTR newFile)
{
#ifndef UNDER_CE
// if (IsItWindows2000orHigher())
// {
- CProgressInfo progressInfo;
- progressInfo.Progress = progress;
- progressInfo.StartPos = completedSize;
-
- MoveFileWithProgressPointer moveFunction = (MoveFileWithProgressPointer)
- My_GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")),
- "MoveFileWithProgressW");
- if (moveFunction != 0)
+ if (my_MoveFileWithProgressW)
{
IF_USE_MAIN_PATH_2(oldFile, newFile)
{
- if (moveFunction(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
- &progressInfo, MOVEFILE_COPY_ALLOWED))
+ if (my_MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
+ &ProgressInfo, MOVEFILE_COPY_ALLOWED))
return true;
}
#ifdef WIN_LONG_PATH
if ((!(USE_MAIN_PATH_2) || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) && USE_SUPER_PATH_2)
{
- UString longPathExisting, longPathNew;
- if (!GetSuperPaths(oldFile, newFile, longPathExisting, longPathNew, USE_MAIN_PATH_2))
+ if (IsCallbackProgressError())
+ return false;
+ UString superPathOld, superPathNew;
+ if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
return false;
- if (moveFunction(longPathExisting, longPathNew, CopyProgressRoutine,
- &progressInfo, MOVEFILE_COPY_ALLOWED))
+ if (my_MoveFileWithProgressW(superPathOld, superPathNew, CopyProgressRoutine,
+ &ProgressInfo, MOVEFILE_COPY_ALLOWED))
return true;
}
#endif
@@ -226,7 +355,10 @@ static bool FsMoveFile(CFSTR oldFile, CFSTR newFile,
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
const wchar_t *message, const FString &fileName)
{
- return callback->ShowMessage(message + fs2us(fileName));
+ UString s = message;
+ s += L" : ";
+ s += fs2us(fileName);
+ return callback->ShowMessage(s);
}
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
@@ -235,41 +367,104 @@ static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
}
-static HRESULT FsCopyFile(
+static DWORD Return_LastError_or_FAIL()
+{
+ DWORD errorCode = GetLastError();
+ if (errorCode == 0)
+ errorCode = (DWORD)E_FAIL;
+ return errorCode;
+}
+
+static UString GetLastErrorMessage()
+{
+ return NError::MyFormatMessage(Return_LastError_or_FAIL());
+}
+
+HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName)
+{
+ return SendMessageError(callback, GetLastErrorMessage(), fileName);
+}
+
+static HRESULT CopyFile_Ask(
+ CCopyState &state,
const FString &srcPath,
const CFileInfo &srcFileInfo,
- const FString &destPathSpec,
- IFolderOperationsExtractCallback *callback,
- UInt64 &completedSize)
+ const FString &destPath)
{
- FString destPath = destPathSpec;
if (CompareFileNames(destPath, srcPath) == 0)
{
- RINOK(SendMessageError(callback, "can not copy file onto itself: ", destPath));
+ RINOK(SendMessageError(state.Callback,
+ state.MoveMode ?
+ "can not move file onto itself" :
+ "can not copy file onto itself"
+ , destPath));
return E_ABORT;
}
Int32 writeAskResult;
CMyComBSTR destPathResult;
- RINOK(callback->AskWrite(
+ RINOK(state.Callback->AskWrite(
fs2us(srcPath),
BoolToInt(false),
&srcFileInfo.MTime, &srcFileInfo.Size,
fs2us(destPath),
&destPathResult,
&writeAskResult));
+
if (IntToBool(writeAskResult))
{
- FString destPathNew = us2fs((const wchar_t *)(BSTR)destPathResult);
- RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
- if (!FsCopyFile(srcPath, destPathNew, callback, completedSize))
+ FString destPathNew = us2fs((LPCOLESTR)destPathResult);
+ RINOK(state.Callback->SetCurrentFilePath(fs2us(srcPath)));
+
+ if (state.UseReadWriteMode)
{
- RINOK(SendMessageError(callback, NError::MyFormatMessage(GetLastError()) + L" : ", destPathNew));
- return E_ABORT;
+ NFsFolder::CCopyStateIO state2;
+ state2.Progress = state.Callback;
+ state2.DeleteSrcFile = state.MoveMode;
+ state2.TotalSize = state.TotalSize;
+ state2.StartPos = state.ProgressInfo.StartPos;
+ RINOK(state2.MyCopyFile(srcPath, destPathNew));
+ if (state2.ErrorFileIndex >= 0)
+ {
+ if (state2.ErrorMessage.IsEmpty())
+ state2.ErrorMessage = GetLastErrorMessage();
+ FString errorName;
+ if (state2.ErrorFileIndex == 0)
+ errorName = srcPath;
+ else
+ errorName = destPathNew;
+ RINOK(SendMessageError(state.Callback, state2.ErrorMessage, errorName));
+ return E_ABORT;
+ }
+ state.ProgressInfo.StartPos += state2.CurrentSize;
+ }
+ else
+ {
+ state.ProgressInfo.FileSize = srcFileInfo.Size;
+ bool res;
+ if (state.MoveMode)
+ res = state.MoveFile_Sys(srcPath, destPathNew);
+ else
+ res = state.CopyFile_Sys(srcPath, destPathNew);
+ RINOK(state.ProgressInfo.ProgressResult);
+ if (!res)
+ {
+ // GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL.
+ RINOK(SendMessageError(state.Callback, GetLastErrorMessage(), destPathNew));
+ return E_ABORT;
+ }
+ state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;
}
}
- completedSize += srcFileInfo.Size;
- return callback->SetCompleted(&completedSize);
+ else
+ {
+ if (state.TotalSize >= srcFileInfo.Size)
+ {
+ state.TotalSize -= srcFileInfo.Size;
+ RINOK(state.ProgressInfo.Progress->SetTotal(state.TotalSize));
+ }
+ }
+ return state.CallProgress();
}
static FString CombinePath(const FString &folderPath, const FString &fileName)
@@ -288,123 +483,70 @@ static bool IsDestChild(const FString &src, const FString &dest)
}
static HRESULT CopyFolder(
- const FString &srcPath,
- const FString &destPath,
- IFolderOperationsExtractCallback *callback,
- UInt64 &completedSize)
+ CCopyState &state,
+ const FString &srcPath, // without TAIL separator
+ const FString &destPath) // without TAIL separator
{
- RINOK(callback->SetCompleted(&completedSize));
+ RINOK(state.CallProgress());
if (IsDestChild(srcPath, destPath))
{
- RINOK(SendMessageError(callback, "can not copy folder onto itself: ", destPath));
+ RINOK(SendMessageError(state.Callback,
+ state.MoveMode ?
+ "can not copy folder onto itself" :
+ "can not move folder onto itself"
+ , destPath));
return E_ABORT;
}
+ if (state.MoveMode)
+ {
+ if (state.MoveFile_Sys(srcPath, destPath))
+ return S_OK;
+
+ // MSDN: MoveFile() fails for dirs on different volumes.
+ }
+
if (!CreateComplexDir(destPath))
{
- RINOK(SendMessageError(callback, "can not create folder: ", destPath));
+ RINOK(SendMessageError(state.Callback, "can not create folder", destPath));
return E_ABORT;
}
+
CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK));
- CDirItem fi;
- while (enumerator.Next(fi))
+
+ for (;;)
{
+ NFind::CFileInfo fi;
+ bool found;
+ if (!enumerator.Next(fi, found))
+ {
+ SendLastErrorMessage(state.Callback, srcPath);
+ return S_OK;
+ }
+ if (!found)
+ break;
const FString srcPath2 = CombinePath(srcPath, fi.Name);
const FString destPath2 = CombinePath(destPath, fi.Name);
if (fi.IsDir())
{
- RINOK(CopyFolder(srcPath2, destPath2, callback, completedSize))
+ RINOK(CopyFolder(state, srcPath2, destPath2))
}
else
{
- RINOK(FsCopyFile(srcPath2, fi, destPath2, callback, completedSize));
+ RINOK(CopyFile_Ask(state, srcPath2, fi, destPath2));
}
}
- return S_OK;
-}
-
-/////////////////////////////////////////////////
-// Move Operations
-
-static HRESULT FsMoveFile(
- const FString &srcPath,
- const CFileInfo &srcFileInfo,
- const FString &destPath,
- IFolderOperationsExtractCallback *callback,
- UInt64 &completedSize)
-{
- if (CompareFileNames(destPath, srcPath) == 0)
- {
- RINOK(SendMessageError(callback, "can not move file onto itself: ", srcPath));
- return E_ABORT;
- }
-
- Int32 writeAskResult;
- CMyComBSTR destPathResult;
- RINOK(callback->AskWrite(
- fs2us(srcPath),
- BoolToInt(false),
- &srcFileInfo.MTime, &srcFileInfo.Size,
- fs2us(destPath),
- &destPathResult,
- &writeAskResult));
- if (IntToBool(writeAskResult))
- {
- FString destPathNew = us2fs((const wchar_t *)(BSTR)destPathResult);
- RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
- if (!FsMoveFile(srcPath, destPathNew, callback, completedSize))
- {
- RINOK(SendMessageError(callback, "can not move to file: ", destPathNew));
- }
- }
- completedSize += srcFileInfo.Size;
- RINOK(callback->SetCompleted(&completedSize));
- return S_OK;
-}
-
-static HRESULT FsMoveFolder(
- const FString &srcPath,
- const FString &destPath,
- IFolderOperationsExtractCallback *callback,
- UInt64 &completedSize)
-{
- if (IsDestChild(srcPath, destPath))
- {
- RINOK(SendMessageError(callback, "can not move folder onto itself: ", destPath));
- return E_ABORT;
- }
- if (FsMoveFile(srcPath, destPath, callback, completedSize))
- return S_OK;
-
- if (!CreateComplexDir(destPath))
+ if (state.MoveMode)
{
- RINOK(SendMessageError(callback, "can not create folder: ", destPath));
- return E_ABORT;
- }
- {
- CEnumerator enumerator(CombinePath(srcPath, FSTRING_ANY_MASK));
- CDirItem fi;
- while (enumerator.Next(fi))
+ if (!RemoveDir(srcPath))
{
- const FString srcPath2 = CombinePath(srcPath, fi.Name);
- const FString destPath2 = CombinePath(destPath, fi.Name);
- if (fi.IsDir())
- {
- RINOK(FsMoveFolder(srcPath2, destPath2, callback, completedSize));
- }
- else
- {
- RINOK(FsMoveFile(srcPath2, fi, destPath2, callback, completedSize));
- }
+ RINOK(SendMessageError(state.Callback, "can not remove folder", srcPath));
+ return E_ABORT;
}
}
- if (!RemoveDir(srcPath))
- {
- RINOK(SendMessageError(callback, "can not remove folder: ", srcPath));
- return E_ABORT;
- }
+
return S_OK;
}
@@ -415,33 +557,44 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
if (numItems == 0)
return S_OK;
- CFsFolderStat stat;
- stat.Progress = callback;
- RINOK(GetItemsFullSize(indices, numItems, stat));
- RINOK(callback->SetTotal(stat.Size));
- RINOK(callback->SetNumFiles(stat.NumFiles));
-
FString destPath = us2fs(path);
if (destPath.IsEmpty())
return E_INVALIDARG;
- bool directName = (destPath.Back() != FCHAR_PATH_SEPARATOR);
- if (directName)
+
+ bool isAltDest = NName::IsAltPathPrefix(destPath);;
+ bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
+
+ if (isDirectPath)
{
if (numItems > 1)
return E_INVALIDARG;
}
- else
- {
- // Does CreateComplexDir work in network ?
- if (!CreateComplexDir(destPath))
- {
- RINOK(SendMessageError(callback, "can not create folder: ", destPath));
- return E_ABORT;
- }
- }
+
+ CFsFolderStat stat;
+ stat.Progress = callback;
+ RINOK(GetItemsFullSize(indices, numItems, stat));
+
+ if (stat.NumFolders != 0 && isAltDest)
+ return E_NOTIMPL;
+
+ RINOK(callback->SetTotal(stat.Size));
+ RINOK(callback->SetNumFiles(stat.NumFiles));
UInt64 completedSize = 0;
RINOK(callback->SetCompleted(&completedSize));
+
+ CCopyState state;
+ state.ProgressInfo.TotalSize = stat.Size;
+ state.ProgressInfo.TotalSize = stat.Size;
+ state.ProgressInfo.StartPos = 0;
+ state.ProgressInfo.Progress = callback;
+ state.ProgressInfo.Init();
+ state.Callback = callback;
+ state.MoveMode = IntToBool(moveMode);
+ state.UseReadWriteMode = isAltDest;
+ state.Prepare();
+ state.TotalSize = stat.Size;
+
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
@@ -449,38 +602,25 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
continue;
const CDirItem &fi = Files[index];
FString destPath2 = destPath;
- if (!directName)
+ if (!isDirectPath)
destPath2 += fi.Name;
FString srcPath;
GetFullPath(fi, srcPath);
+
if (fi.IsDir())
{
- if (moveMode)
- {
- RINOK(FsMoveFolder(srcPath, destPath2, callback, completedSize));
- }
- else
- {
- RINOK(CopyFolder(srcPath, destPath2, callback, completedSize));
- }
+ RINOK(CopyFolder(state, srcPath, destPath2));
}
else
{
- if (moveMode)
- {
- RINOK(FsMoveFile(srcPath, fi, destPath2, callback, completedSize));
- }
- else
- {
- RINOK(FsCopyFile(srcPath, fi, destPath2, callback, completedSize));
- }
+ RINOK(CopyFile_Ask(state, srcPath, fi, destPath2));
}
}
return S_OK;
}
STDMETHODIMP CFSFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
- const wchar_t ** /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
+ const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
{
/*
UInt64 numFolders, numFiles, totalSize;
diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
index 2d3b1d92..dc46ff5b 100644
--- a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
+++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
@@ -55,12 +55,10 @@ static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, const UString &
}
*/
-static const FChar kExtensionDelimiter = FTEXT('.');
-
static void SplitNameToPureNameAndExtension(const FString &fullName,
FString &pureName, FString &extensionDelimiter, FString &extension)
{
- int index = fullName.ReverseFind(kExtensionDelimiter);
+ int index = fullName.ReverseFind_Dot();
if (index < 0)
{
pureName = fullName;
@@ -70,7 +68,7 @@ static void SplitNameToPureNameAndExtension(const FString &fullName,
else
{
pureName.SetFrom(fullName, index);
- extensionDelimiter = kExtensionDelimiter;
+ extensionDelimiter = FTEXT('.');
extension = fullName.Ptr(index + 1);
}
}
@@ -89,7 +87,7 @@ HRESULT OpenFileFolderPlugin(
FString extension, name, pureName, dot;
- int slashPos = path.ReverseFind(FCHAR_PATH_SEPARATOR);
+ int slashPos = path.ReverseFind_PathSepar();
FString dirPrefix;
FString fileName;
if (slashPos >= 0)
diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp
index 556c54fd..46000301 100644
--- a/CPP/7zip/UI/FileManager/FilePlugins.cpp
+++ b/CPP/7zip/UI/FileManager/FilePlugins.cpp
@@ -11,7 +11,7 @@
int CExtDatabase::FindExt(const UString &ext)
{
FOR_VECTOR (i, Exts)
- if (Exts[i].Ext.IsEqualToNoCase(ext))
+ if (Exts[i].Ext.IsEqualTo_NoCase(ext))
return i;
return -1;
}
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.rc b/CPP/7zip/UI/FileManager/FoldersPage.rc
index fb48ee6e..cb345ea6 100644
--- a/CPP/7zip/UI/FileManager/FoldersPage.rc
+++ b/CPP/7zip/UI/FileManager/FoldersPage.rc
@@ -1,7 +1,7 @@
#include "FoldersPageRes.h"
#include "../../GuiCommon.rc"
-#define xc 196
+#define xc 240
#define yc 100
IDD_FOLDERS MY_PAGE
diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h
index 60991a71..c5cff06e 100644
--- a/CPP/7zip/UI/FileManager/IFolder.h
+++ b/CPP/7zip/UI/FileManager/IFolder.h
@@ -36,6 +36,21 @@ FOLDER_INTERFACE(IFolderFolder, 0x00)
INTERFACE_FolderFolder(PURE)
};
+/*
+ IFolderAltStreams::
+ BindToAltStreams((UInt32)(Int32)-1, ... ) means alt streams of that folder
+*/
+
+#define INTERFACE_FolderAltStreams(x) \
+ STDMETHOD(BindToAltStreams)(UInt32 index, IFolderFolder **resultFolder) x; \
+ STDMETHOD(BindToAltStreams)(const wchar_t *name, IFolderFolder **resultFolder) x; \
+ STDMETHOD(AreAltStreamsSupported)(UInt32 index, Int32 *isSupported) x; \
+
+FOLDER_INTERFACE(IFolderAltStreams, 0x17)
+{
+ INTERFACE_FolderAltStreams(PURE)
+};
+
FOLDER_INTERFACE(IFolderWasChanged, 0x04)
{
STDMETHOD(WasChanged)(Int32 *wasChanged) PURE;
@@ -67,7 +82,7 @@ FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B)
Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, \
const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \
STDMETHOD(CopyFrom)(Int32 moveMode, const wchar_t *fromFolderPath, \
- const wchar_t **itemsPaths, UInt32 numItems, IProgress *progress) x; \
+ const wchar_t * const *itemsPaths, UInt32 numItems, IProgress *progress) x; \
STDMETHOD(SetProperty)(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress) x; \
STDMETHOD(CopyFromFile)(UInt32 index, const wchar_t *fullFilePath, IProgress *progress) x; \
diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp
index 54253295..d9dc6c52 100644
--- a/CPP/7zip/UI/FileManager/LangPage.cpp
+++ b/CPP/7zip/UI/FileManager/LangPage.cpp
@@ -63,8 +63,7 @@ bool CLangPage::OnInit()
if (!LangOpen(lang, dirPrefix + fi.Name))
{
- if (!error.IsEmpty())
- error += L' ';
+ error.Add_Space_if_NotEmpty();
error += fs2us(fi.Name);
continue;
}
@@ -80,7 +79,7 @@ bool CLangPage::OnInit()
index = (int)_langCombo.AddString(s);
_langCombo.SetItemData(index, _paths.Size());
_paths.Add(shortName);
- if (g_LangID.IsEqualToNoCase(shortName))
+ if (g_LangID.IsEqualTo_NoCase(shortName))
_langCombo.SetCurSel(index);
}
diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc
index 5aeaf406..164e2d30 100644
--- a/CPP/7zip/UI/FileManager/LangPage.rc
+++ b/CPP/7zip/UI/FileManager/LangPage.rc
@@ -1,7 +1,7 @@
#include "LangPageRes.h"
#include "../../GuiCommon.rc"
-#define xc 148
+#define xc 160
#define yc 100
IDD_LANG DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp
index 15d68f43..9723704a 100644
--- a/CPP/7zip/UI/FileManager/LangUtils.cpp
+++ b/CPP/7zip/UI/FileManager/LangUtils.cpp
@@ -115,6 +115,11 @@ UString LangString(UInt32 langID)
return MyLoadString(langID);
}
+void AddLangString(UString &s, UInt32 langID)
+{
+ s += LangString(langID);
+}
+
void LangString(UInt32 langID, UString &dest)
{
const wchar_t *s = g_Lang.Get(langID);
@@ -166,7 +171,7 @@ static void FindShortNames(UInt32 primeLang, UStringVector &names)
p++;
}
while (p != p2)
- s += (wchar_t)*p++;
+ s += (wchar_t)(Byte)*p++;
names.Add(s);
}
p = p2 + 1;
diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h
index 509a5ae3..d63a443c 100644
--- a/CPP/7zip/UI/FileManager/LangUtils.h
+++ b/CPP/7zip/UI/FileManager/LangUtils.h
@@ -25,13 +25,15 @@ void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems);
void LangSetWindowText(HWND window, UInt32 langID);
UString LangString(UInt32 langID);
+void AddLangString(UString &s, UInt32 langID);
void LangString(UInt32 langID, UString &dest);
void LangString_OnlyFromLangFile(UInt32 langID, UString &dest);
-
+
#else
inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); }
inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); }
+inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); }
#endif
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp
index a24ec601..bc482e4b 100644
--- a/CPP/7zip/UI/FileManager/LinkDialog.cpp
+++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp
@@ -321,14 +321,14 @@ void CApp::Link()
int index = indices[0];
const UString itemName = srcPanel.GetItemName(index);
- UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
+ UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
UString path = srcPath;
{
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
- path = destPanel._currentFolderPrefix;
+ path = destPanel.GetFsPath();
}
CLinkDialog dlg;
diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc
index 626f415e..f20c574e 100644
--- a/CPP/7zip/UI/FileManager/MenuPage.rc
+++ b/CPP/7zip/UI/FileManager/MenuPage.rc
@@ -1,7 +1,7 @@
#include "MenuPageRes.h"
#include "../../GuiCommon.rc"
-#define xc 196
+#define xc 240
#define yc 196
IDD_MENU MY_PAGE
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
index 401e48ef..b0f6615e 100644
--- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
+++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
@@ -13,6 +13,7 @@
#include "App.h"
#include "HelpUtils.h"
#include "LangUtils.h"
+#include "MyLoadMenu.h"
#include "RegistryUtils.h"
#include "resource.h"
@@ -100,19 +101,19 @@ public:
#define MIIM_FTYPE 0x00000100
#endif
-static UINT Get_fMaskForString()
+static UINT Get_fMask_for_String()
{
return g_IsNew_fMask ? MIIM_STRING : MIIM_TYPE;
}
-static UINT Get_fMaskForFTypeAndString()
+static UINT Get_fMask_for_FType_and_String()
{
return g_IsNew_fMask ? (MIIM_STRING | MIIM_FTYPE) : MIIM_TYPE;
}
*/
-static inline UINT Get_fMaskForString() { return MIIM_TYPE; }
-static inline UINT Get_fMaskForFTypeAndString() { return MIIM_TYPE; }
+static inline UINT Get_fMask_for_String() { return MIIM_TYPE; }
+static inline UINT Get_fMask_for_FType_and_String() { return MIIM_TYPE; }
static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)
{
@@ -121,7 +122,7 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)
for (int i = 0;; i++)
{
CMenuItem item;
- item.fMask = Get_fMaskForString() | MIIM_SUBMENU | MIIM_ID;
+ item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID;
item.fType = MFT_STRING;
if (!menu.GetItem(i, true, item))
break;
@@ -157,14 +158,13 @@ static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)
if (newString.IsEmpty())
continue;
- UString shorcutString = item.StringValue;
- int tabPos = shorcutString.ReverseFind(wchar_t('\t'));
+ int tabPos = item.StringValue.ReverseFind(L'\t');
if (tabPos >= 0)
- newString += shorcutString.Ptr(tabPos);
+ newString += item.StringValue.Ptr(tabPos);
}
{
item.StringValue = newString;
- item.fMask = Get_fMaskForString();
+ item.fMask = Get_fMask_for_String();
item.fType = MFT_STRING;
menu.SetItem(i, true, item);
}
@@ -203,7 +203,7 @@ static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec)
for (int i = 0;; i++)
{
CMenuItem item;
- item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString();
+ item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
item.fType = MFT_STRING;
if (!srcMenu.GetItem(i, true, item))
@@ -307,13 +307,14 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
subMenu.Attach(menu.GetSubMenu(0));
subMenu.RemoveAllItems();
int i;
+
for (i = 0; i < 10; i++)
{
UString s = LangString(IDS_BOOKMARK);
- s += L' ';
+ s.Add_Space();
wchar_t c = (wchar_t)(L'0' + i);
s += c;
- s += L"\tAlt+Shift+";
+ s.AddAscii("\tAlt+Shift+");
s += c;
subMenu.AppendItem(MF_STRING, kSetBookmarkMenuID + i, s);
}
@@ -332,7 +333,7 @@ void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
}
if (s.IsEmpty())
s = L'-';
- s += L"\tAlt+";
+ s.AddAscii("\tAlt+");
s += (wchar_t)(L'0' + i);
menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s);
}
@@ -348,8 +349,7 @@ void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id)
}
*/
-void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,
- bool isFsFolder, int numItems, bool allAreFiles)
+void CFileMenu::Load(HMENU hMenu, unsigned startPos)
{
CMenu destMenu;
destMenu.Attach(hMenu);
@@ -357,15 +357,17 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,
UString diffPath;
ReadRegDiff(diffPath);
- int numRealItems = startPos;
- for (int i = 0;; i++)
+ unsigned numRealItems = startPos;
+ for (unsigned i = 0;; i++)
{
CMenuItem item;
- item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMaskForFTypeAndString();
+ item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
item.fType = MFT_STRING;
+
if (!g_FileMenu.GetItem(i, true, item))
break;
+
{
if (!programMenu && item.wID == IDCLOSE)
continue;
@@ -376,6 +378,26 @@ void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,
bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles);
bool disable = (!isOneFsFile && (item.wID == IDM_SPLIT || item.wID == IDM_COMBINE));
+ if (readOnly)
+ {
+ switch (item.wID)
+ {
+ case IDM_RENAME:
+ case IDM_MOVE_TO:
+ case IDM_DELETE:
+ case IDM_COMMENT:
+ case IDM_CREATE_FOLDER:
+ case IDM_CREATE_FILE:
+ disable = true;
+ }
+ }
+
+ if (item.wID == IDM_LINK && numItems != 1)
+ disable = true;
+
+ if (item.wID == IDM_ALT_STREAMS)
+ disable = !isAltStreamsSupported;
+
bool isBigScreen = NControl::IsDialogSizeOK(40, 200);
if (!isBigScreen && (disable || item.IsSeparator()))
@@ -434,6 +456,7 @@ bool ExecuteFileCommand(int id)
case IDM_CREATE_FILE: g_App.CreateFile(); break;
#ifndef UNDER_CE
case IDM_LINK: g_App.Link(); break;
+ case IDM_ALT_STREAMS: g_App.OpenAltStreams(); break;
#endif
default: return false;
}
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h
index 53e9d0ef..02569e52 100644
--- a/CPP/7zip/UI/FileManager/MyLoadMenu.h
+++ b/CPP/7zip/UI/FileManager/MyLoadMenu.h
@@ -9,8 +9,28 @@ void OnMenuActivating(HWND hWnd, HMENU hMenu, int position);
bool OnMenuCommand(HWND hWnd, int id);
void MyLoadMenu();
-void LoadFileMenu(HMENU hMenu, int startPos, bool programMenu,
- bool isFsFolder, int numItems, bool allAreFiles);
+
+struct CFileMenu
+{
+ bool programMenu;
+ bool readOnly;
+ bool isFsFolder;
+ bool allAreFiles;
+ bool isAltStreamsSupported;
+ int numItems;
+
+ CFileMenu():
+ programMenu(false),
+ readOnly(false),
+ isFsFolder(false),
+ allAreFiles(false),
+ isAltStreamsSupported(true),
+ numItems(0)
+ {}
+
+ void Load(HMENU hMenu, unsigned startPos);
+};
+
bool ExecuteFileCommand(int id);
#endif
diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp
index f3d531ab..bfccc353 100644
--- a/CPP/7zip/UI/FileManager/NetFolder.cpp
+++ b/CPP/7zip/UI/FileManager/NetFolder.cpp
@@ -73,7 +73,15 @@ void CNetFolder::Init(const NWindows::NNet::CResourceW *netResource,
_netResourcePointer = &_netResource;
// if (_netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER)
- _path = _netResource.RemoteName + WCHAR_PATH_SEPARATOR;
+ _path = _netResource.RemoteName;
+
+ /* WinXP-64: When we move UP from Network share without _parentFolder chain,
+ we can get empty _netResource.RemoteName. Do we need to use Provider there ? */
+ if (_path.IsEmpty())
+ _path = _netResource.Provider;
+
+ if (!_path.IsEmpty())
+ _path.Add_PathSepar();
}
_parentFolder = parentFolder;
}
@@ -111,7 +119,7 @@ STDMETHODIMP CNetFolder::LoadItems()
if (!resource.RemoteNameIsDefined) // For Win 98, I don't know what's wrong
resource.RemoteName = resource.Comment;
resource.Name = resource.RemoteName;
- int pos = resource.Name.ReverseFind(WCHAR_PATH_SEPARATOR);
+ int pos = resource.Name.ReverseFind_PathSepar();
if (pos >= 0)
{
// _path = resource.Name.Left(pos + 1);
@@ -186,7 +194,7 @@ STDMETHODIMP CNetFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder
{
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
- RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR), this));
+ RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR))); // , this
*resultFolder = subFolder.Detach();
}
else
@@ -237,7 +245,7 @@ STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
- case kpidType: prop = L"NetFolder"; break;
+ case kpidType: prop = "NetFolder"; break;
case kpidPath: prop = _path; break;
}
prop.Detach(value);
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
index a657bc90..c6feb902 100644
--- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
@@ -50,7 +50,7 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID,
sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));
const UString &fileName = fileInfo.Name;
- int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR);
+ int slashPos = fileName.ReverseFind_PathSepar();
UString s1 = fileName.Left(slashPos + 1);
UString s2 = fileName.Ptr(slashPos + 1);
@@ -58,18 +58,18 @@ void COverwriteDialog::SetFileInfoControl(int textID, int iconID,
ReduceString(s2);
UString s = s1;
- s += L'\n';
+ s.Add_LF();
s += s2;
- s += L'\n';
+ s.Add_LF();
s += sizeString;
- s += L'\n';
+ s.Add_LF();
if (fileInfo.TimeIsDefined)
{
FILETIME localFileTime;
if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
throw 4190402;
- s += LangString(IDS_PROP_MTIME);
+ AddLangString(s, IDS_PROP_MTIME);
s += L": ";
wchar_t t[32];
ConvertFileTimeToString(localFileTime, t);
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
index d63bdc17..a7416a4c 100644
--- a/CPP/7zip/UI/FileManager/Panel.cpp
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -477,7 +477,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
_comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));
_comboBoxEdit._panel = this;
#ifndef _UNICODE
- if(g_IsNT)
+ if (g_IsNT)
_comboBoxEdit._origWindowProc =
(WNDPROC)_comboBoxEdit.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
else
@@ -675,7 +675,7 @@ void CPanel::MessageBoxError2Lines(LPCWSTR message, HRESULT errorCode)
UString m = message;
if (errorCode != 0)
{
- m += L'\n';
+ m.Add_LF();
m += HResultToMessage(errorCode);
}
MessageBoxMyError(m);
@@ -708,29 +708,32 @@ void CPanel::SetFocusToLastRememberedItem()
UString CPanel::GetFolderTypeID() const
{
- NCOM::CPropVariant prop;
- if (_folder->GetFolderProperty(kpidType, &prop) == S_OK)
- if (prop.vt == VT_BSTR)
- return (const wchar_t *)prop.bstrVal;
- return L"";
+ {
+ NCOM::CPropVariant prop;
+ if (_folder->GetFolderProperty(kpidType, &prop) == S_OK)
+ if (prop.vt == VT_BSTR)
+ return (const wchar_t *)prop.bstrVal;
+ }
+ return UString();
}
-bool CPanel::IsFolderTypeEqTo(const wchar_t *s) const
+bool CPanel::IsFolderTypeEqTo(const char *s) const
{
- return GetFolderTypeID() == s;
+ return StringsAreEqual_Ascii(GetFolderTypeID(), s);
}
-bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo(L"RootFolder"); }
-bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo(L"FSFolder"); }
-bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo(L"FSDrives"); }
+bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo("RootFolder"); }
+bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo("FSFolder"); }
+bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo("FSDrives"); }
+bool CPanel::IsAltStreamsFolder() const { return IsFolderTypeEqTo("AltStreamsFolder"); }
bool CPanel::IsArcFolder() const
{
- return GetFolderTypeID().IsPrefixedBy(L"7-Zip");
+ return GetFolderTypeID().IsPrefixedBy_Ascii_NoCase("7-Zip");
}
UString CPanel::GetFsPath() const
{
- if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix())
+ if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix() && !IsSuperDrivesPrefix())
return UString();
return _currentFolderPrefix;
}
@@ -744,12 +747,6 @@ UString CPanel::GetDriveOrNetworkPrefix() const
return drive;
}
-bool CPanel::DoesItSupportOperations() const
-{
- CMyComPtr<IFolderOperations> folderOperations;
- return _folder.QueryInterface(IID_IFolderOperations, &folderOperations) == S_OK;
-}
-
void CPanel::SetListViewMode(UInt32 index)
{
if (index >= 4)
@@ -805,7 +802,7 @@ void CPanel::AddToArchive()
{
CRecordVector<UInt32> indices;
GetOperatedItemIndices(indices);
- if (!IsFsOrDrivesFolder())
+ if (!Is_IO_FS_Folder())
{
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
@@ -817,20 +814,16 @@ void CPanel::AddToArchive()
}
UStringVector names;
- UString curPrefix = _currentFolderPrefix;
- UString destCurDirPrefix = _currentFolderPrefix;
+ const UString curPrefix = GetFsPath();
+ UString destCurDirPrefix = curPrefix;
if (IsFSDrivesFolder())
- {
destCurDirPrefix = ROOT_FS_FOLDER;
- if (!IsDeviceDrivesPrefix())
- curPrefix.Empty();
- }
FOR_VECTOR (i, indices)
- names.Add(curPrefix + GetItemRelPath(indices[i]));
+ names.Add(curPrefix + GetItemRelPath2(indices[i]));
bool fromPrev = (names.Size() > 1);
- const UString archiveName = CreateArchiveName(names.Front(), fromPrev, false);
- HRESULT res = CompressFiles(destCurDirPrefix, archiveName, L"",
+ const UString arcName = CreateArchiveName(names.Front(), fromPrev, false);
+ HRESULT res = CompressFiles(destCurDirPrefix, arcName, L"",
true, // addExtension
names, false, true, false);
if (res != S_OK)
@@ -841,23 +834,24 @@ void CPanel::AddToArchive()
// KillSelection();
}
-static UString GetSubFolderNameForExtract(const UString &archiveName)
+static UString GetSubFolderNameForExtract(const UString &arcPath)
{
- UString res = archiveName;
- int slashPos = res.ReverseFind(WCHAR_PATH_SEPARATOR);
- int dotPos = res.ReverseFind(L'.');
- if (dotPos < 0 || slashPos > dotPos)
- res += L'~';
+ UString s = arcPath;
+ int slashPos = s.ReverseFind_PathSepar();
+ int dotPos = s.ReverseFind_Dot();
+ if (dotPos <= slashPos + 1)
+ s += L'~';
else
{
- res.DeleteFrom(dotPos);
- res.TrimRight();
+ s.DeleteFrom(dotPos);
+ s.TrimRight();
}
- return res;
+ return s;
}
void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths, bool allowFolders)
{
+ const UString prefix = GetFsPath();
FOR_VECTOR (i, indices)
{
int index = indices[i];
@@ -866,7 +860,7 @@ void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &p
paths.Clear();
break;
}
- paths.Add(GetItemFullPath(index));
+ paths.Add(prefix + GetItemRelPath2(index));
}
if (paths.Size() == 0)
{
@@ -888,26 +882,31 @@ void CPanel::ExtractArchives()
GetFilePaths(indices, paths);
if (paths.IsEmpty())
return;
- UString folderName;
+
+ UString outFolder = GetFsPath();
if (indices.Size() == 1)
- folderName = GetSubFolderNameForExtract(GetItemRelPath(indices[0]));
+ outFolder += GetSubFolderNameForExtract(GetItemRelPath(indices[0]));
else
- folderName = L"*";
- ::ExtractArchives(paths, _currentFolderPrefix + folderName + UString(WCHAR_PATH_SEPARATOR)
+ outFolder += L'*';
+ outFolder.Add_PathSepar();
+
+ ::ExtractArchives(paths, outFolder
, true // showDialog
, false // elimDup
);
}
-void AddValuePair(UINT resourceID, UInt64 value, UString &s)
+/*
+static void AddValuePair(UINT resourceID, UInt64 value, UString &s)
{
- wchar_t sz[32];
- s += LangString(resourceID);
+ AddLangString(s, resourceID);
+ char sz[32];
s += L": ";
ConvertUInt64ToString(value, sz);
- s += sz;
- s += L'\n';
+ s.AddAsciiStr(sz);
+ s.Add_LF();
}
+*/
class CThreadTest: public CProgressThreadVirt
{
@@ -939,8 +938,8 @@ HRESULT CThreadTest::ProcessVirt()
AddValuePair(IDS_PROP_FILES, ExtractCallbackSpec->NumFiles, s);
// AddValuePair(IDS_PROP_SIZE, ExtractCallbackSpec->UnpackSize, s);
// AddSizePair(IDS_COMPRESSED_COLON, Stat.PackSize, s);
- s += L'\n';
- s += LangString(IDS_MESSAGE_NO_ERRORS);
+ s.Add_LF();
+ AddLangString(s, IDS_MESSAGE_NO_ERRORS);
FinalMessage.OkMessage.Message = s;
}
return S_OK;
@@ -948,18 +947,18 @@ HRESULT CThreadTest::ProcessVirt()
*/
/*
-static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s)
+static void AddSizePair(UInt32 langID, UInt64 value, UString &s)
{
- wchar_t sz[32];
- s += LangString(resourceID, langID);
+ char sz[32];
+ AddLangString(s, langID);
s += L' ';
ConvertUInt64ToString(value, sz);
- s += sz;
+ s.AddAsciiStr(sz);
ConvertUInt64ToString(value >> 20, sz);
- s += L" (";
- s += sz;
- s += L" MB)";
- s += L'\n';
+ s.AddAsciiStr(" (");
+ s.AddAsciiStr(sz);
+ s.AddAsciiStr(" MB)");
+ s.Add_LF();
}
*/
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
index dc293729..39915a27 100644
--- a/CPP/7zip/UI/FileManager/Panel.h
+++ b/CPP/7zip/UI/FileManager/Panel.h
@@ -11,6 +11,7 @@
#include "../../../Windows/DLL.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
#include "../../../Windows/Handle.h"
#include "../../../Windows/Synchronization.h"
@@ -43,10 +44,10 @@ const int kParentFolderID = 100;
const int kParentIndex = -1;
-#ifdef UNDER_CE
+#if !defined(_WIN32) || defined(UNDER_CE)
#define ROOT_FS_FOLDER L"\\"
#else
-#define ROOT_FS_FOLDER L"C:\\\\"
+#define ROOT_FS_FOLDER L"C:\\"
#endif
struct CPanelCallback
@@ -117,12 +118,13 @@ struct CTempFileInfo
struct CFolderLink: public CTempFileInfo
{
NWindows::NDLL::CLibrary Library;
- CMyComPtr<IFolderFolder> ParentFolder;
+ CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0])
+ UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level)
bool UsePassword;
UString Password;
bool IsVirtual;
- UString VirtualPath;
+ UString VirtualPath; // without tail slash
CFolderLink(): UsePassword(false), IsVirtual(false) {}
bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const
@@ -146,7 +148,7 @@ enum MyMessages
#endif
};
-UString GetFolderPath(IFolderFolder * folder);
+UString GetFolderPath(IFolderFolder *folder);
class CPanel;
@@ -380,27 +382,11 @@ public:
CMyComPtr<IFolderCompare> _folderCompare;
CMyComPtr<IFolderGetItemName> _folderGetItemName;
CMyComPtr<IArchiveGetRawProps> _folderRawProps;
+ CMyComPtr<IFolderAltStreams> _folderAltStreams;
+ CMyComPtr<IFolderOperations> _folderOperations;
- void ReleaseFolder()
- {
- _folderCompare.Release();
- _folderGetItemName.Release();
- _folderRawProps.Release();
- _folder.Release();
- _thereAreDeletedItems = false;
- }
-
- void SetNewFolder(IFolderFolder *newFolder)
- {
- ReleaseFolder();
- _folder = newFolder;
- if (_folder)
- {
- _folder.QueryInterface(IID_IFolderCompare, &_folderCompare);
- _folder.QueryInterface(IID_IFolderGetItemName, &_folderGetItemName);
- _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps);
- }
- }
+ void ReleaseFolder();
+ void SetNewFolder(IFolderFolder *newFolder);
// CMyComPtr<IFolderGetSystemIconIndex> _folderGetSystemIconIndex;
@@ -417,9 +403,11 @@ public:
bool IsItem_AltStream(int itemIndex) const;
UString GetItemName(int itemIndex) const;
- void GetItemNameFast(int itemIndex, UString &s) const;
+ UString GetItemName_for_Copy(int itemIndex) const;
+ void GetItemName(int itemIndex, UString &s) const;
UString GetItemPrefix(int itemIndex) const;
UString GetItemRelPath(int itemIndex) const;
+ UString GetItemRelPath2(int itemIndex) const;
UString GetItemFullPath(int itemIndex) const;
UInt64 GetItemSize(int itemIndex) const;
@@ -438,6 +426,7 @@ public:
void LoadFullPathAndShow();
void FoldersHistory();
void OpenParentFolder();
+ void CloseOneLevel();
void CloseOpenFolders();
void OpenRootFolder();
@@ -554,19 +543,65 @@ public:
void KillSelection();
UString GetFolderTypeID() const;
- bool IsFolderTypeEqTo(const wchar_t *s) const;
+
+ bool IsFolderTypeEqTo(const char *s) const;
bool IsRootFolder() const;
bool IsFSFolder() const;
bool IsFSDrivesFolder() const;
+ bool IsAltStreamsFolder() const;
bool IsArcFolder() const;
- bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); }
+
+ /*
+ c:\Dir
+ Computer\
+ \\?\
+ \\.\
+ */
+ bool Is_IO_FS_Folder() const
+ {
+ return IsFSFolder() || IsFSDrivesFolder() || IsAltStreamsFolder();
+ }
+
+ bool Is_Slow_Icon_Folder() const
+ {
+ return IsFSFolder() || IsAltStreamsFolder();
+ }
+
+ // bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); }
bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; }
+ bool IsSuperDrivesPrefix() const { return _currentFolderPrefix == L"\\\\?\\"; }
+
+ /*
+ c:\Dir
+ Computer\
+ \\?\
+ */
bool IsFsOrPureDrivesFolder() const { return IsFSFolder() || (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()); }
+ /*
+ c:\Dir
+ Computer\
+ \\?\
+ \\SERVER\
+ */
+ bool IsFolder_with_FsItems() const
+ {
+ if (IsFsOrPureDrivesFolder())
+ return true;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ FString prefix = us2fs(GetFsPath());
+ return (prefix.Len() == NWindows::NFile::NName::GetNetworkServerPrefixSize(prefix));
+ #else
+ return false;
+ #endif
+ }
+
UString GetFsPath() const;
UString GetDriveOrNetworkPrefix() const;
- bool DoesItSupportOperations() const;
+ bool DoesItSupportOperations() const { return _folderOperations != NULL; }
+ bool IsThereReadOnlyFolder() const;
+ bool CheckBeforeUpdate(UINT resourceID);
bool _processTimer;
bool _processNotify;
@@ -574,37 +609,35 @@ public:
class CDisableTimerProcessing
{
- bool _processTimerMem;
-
- CPanel &_panel;
+ CLASS_NO_COPY(CDisableTimerProcessing);
- CDisableTimerProcessing(const CDisableTimerProcessing &);
- CDisableTimerProcessing& operator=(const CDisableTimerProcessing &);
+ bool _processTimer;
+ CPanel &_panel;
+
public:
CDisableTimerProcessing(CPanel &panel): _panel(panel) { Disable(); }
~CDisableTimerProcessing() { Restore(); }
void Disable()
{
- _processTimerMem = _panel._processTimer;
+ _processTimer = _panel._processTimer;
_panel._processTimer = false;
}
void Restore()
{
- _panel._processTimer = _processTimerMem;
+ _panel._processTimer = _processTimer;
}
};
class CDisableNotify
{
- bool _processNotifyMem;
- bool _processStatusBarMem;
+ CLASS_NO_COPY(CDisableNotify);
- CPanel &_panel;
+ bool _processNotify;
+ bool _processStatusBar;
- CDisableNotify(const CDisableNotify &);
- CDisableNotify& operator=(const CDisableNotify &);
+ CPanel &_panel;
public:
@@ -612,20 +645,20 @@ public:
~CDisableNotify() { Restore(); }
void Disable()
{
- _processNotifyMem = _panel._processNotify;
- _processStatusBarMem = _panel._processStatusBar;
+ _processNotify = _panel._processNotify;
+ _processStatusBar = _panel._processStatusBar;
_panel._processNotify = false;
_panel._processStatusBar = false;
}
void SetMemMode_Enable()
{
- _processNotifyMem = true;
- _processStatusBarMem = true;
+ _processNotify = true;
+ _processStatusBar = true;
}
void Restore()
{
- _panel._processNotify = _processNotifyMem;
- _panel._processStatusBar = _processStatusBarMem;
+ _panel._processNotify = _processNotify;
+ _panel._processStatusBar = _processStatusBar;
}
};
@@ -647,10 +680,12 @@ public:
void MessageBoxLastError(LPCWSTR caption);
void MessageBoxLastError();
- void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID);
+ // void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID);
void MessageBoxErrorLang(UINT resourceID);
+ void OpenAltStreams();
+
void OpenFocusedItemAsInternal();
void OpenSelectedItems(bool internal);
diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp
index d11368cf..fb418963 100644
--- a/CPP/7zip/UI/FileManager/PanelCopy.cpp
+++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp
@@ -1,4 +1,4 @@
-/// PanelExtract.cpp
+/// PanelCopy.cpp
#include "StdAfx.h"
@@ -79,18 +79,25 @@ HRESULT CPanelCopyThread::ProcessVirt()
return Result;
}
+
+/*
+#ifdef EXTERNAL_CODECS
+
static void ThrowException_if_Error(HRESULT res)
{
if (res != S_OK)
throw CSystemException(res);
}
+#endif
+*/
+
+
HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &indices,
UStringVector *messages,
bool &usePassword, UString &password)
{
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
+ if (!_folderOperations)
{
UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
if (options.showErrorMessages)
@@ -100,8 +107,17 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
return E_FAIL;
}
- HRESULT res;
+ HRESULT res = S_OK;
+
{
+ /*
+ #ifdef EXTERNAL_CODECS
+ CExternalCodecs g_ExternalCodecs;
+ #endif
+ */
+ /* extracter.Hash uses g_ExternalCodecs
+ extracter must be declared after g_ExternalCodecs for correct destructor order !!! */
+
CPanelCopyThread extracter;
extracter.ExtractCallbackSpec = new CExtractCallbackImp;
@@ -113,11 +129,6 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
extracter.ExtractCallbackSpec->StreamMode = options.streamMode;
- #ifdef EXTERNAL_CODECS
- CExternalCodecs __externalCodecs;
- #else
- CMyComPtr<IUnknown> compressCodecsInfo;
- #endif
if (indices.Size() == 1)
extracter.FirstFilePath = GetItemRelPath(indices[0]);
@@ -131,19 +142,16 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
if (!options.hashMethods.IsEmpty())
{
- {
- CCodecs *codecs = new CCodecs;
- ThrowException_if_Error(codecs->Load());
- #ifdef EXTERNAL_CODECS
- __externalCodecs.GetCodecs = codecs;
- __externalCodecs.GetHashers = codecs;
- ThrowException_if_Error(__externalCodecs.LoadCodecs());
- #else
- compressCodecsInfo = codecs;
- #endif
- }
+ /* this code is used when we call CRC calculation for files in side archive
+ But new code uses global codecs so we don't need to call LoadGlobalCodecs again */
+
+ /*
+ #ifdef EXTERNAL_CODECS
+ ThrowException_if_Error(LoadGlobalCodecs());
+ #endif
+ */
- extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS options.hashMethods);
+ extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS_G options.hashMethods);
extracter.ExtractCallbackSpec->SetHashMethods(&extracter.Hash);
}
else if (options.testMode)
@@ -153,7 +161,6 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
extracter.Hash.Init();
-
UString title;
{
UInt32 titleID = IDS_COPYING;
@@ -185,7 +192,7 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAsk;
extracter.ExtractCallbackSpec->Init();
extracter.Indices = indices;
- extracter.FolderOperations = folderOperations;
+ extracter.FolderOperations = _folderOperations;
extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword;
extracter.ExtractCallbackSpec->Password = password;
@@ -244,10 +251,8 @@ struct CThreadUpdate
HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths,
bool showErrorMessages, UStringVector *messages)
{
- CMyComPtr<IFolderOperations> folderOperations;
- _folder.QueryInterface(IID_IFolderOperations, &folderOperations);
HRESULT res;
- if (!folderOperations)
+ if (!_folderOperations)
res = E_NOINTERFACE;
else
{
@@ -255,6 +260,7 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri
updater.MoveMode = moveMode;
updater.UpdateCallbackSpec = new CUpdateCallback100Imp;
updater.UpdateCallback = updater.UpdateCallbackSpec;
+ updater.UpdateCallbackSpec->Init();
updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog;
@@ -263,10 +269,18 @@ HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStri
updater.ProgressDialog.MainWindow = GetParent();
updater.ProgressDialog.MainTitle = progressWindowTitle;
- updater.ProgressDialog.MainAddTitle = title + UString(L' ');
+ updater.ProgressDialog.MainAddTitle = title + L' ';
- updater.UpdateCallbackSpec->Init(false, L"");
- updater.FolderOperations = folderOperations;
+ {
+ if (!_parentFolders.IsEmpty())
+ {
+ const CFolderLink &fl = _parentFolders.Back();
+ updater.UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
+ updater.UpdateCallbackSpec->Password = fl.Password;
+ }
+ }
+
+ updater.FolderOperations = _folderOperations;
updater.FolderPrefix = folderPrefix;
updater.FileNames.ClearAndReserve(filePaths.Size());
unsigned i;
diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp
index ab93ecba..3b0ee052 100644
--- a/CPP/7zip/UI/FileManager/PanelCrc.cpp
+++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp
@@ -6,6 +6,7 @@
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileIO.h"
+#include "../../../Windows/FileName.h"
#include "../Common/LoadCodecs.h"
@@ -19,12 +20,18 @@
using namespace NWindows;
using namespace NFile;
+#ifdef EXTERNAL_CODECS
+extern CExternalCodecs g_ExternalCodecs;
+HRESULT LoadGlobalCodecs();
+#endif
+
static const UInt32 kBufSize = (1 << 15);
struct CDirEnumerator
{
bool EnterToDirs;
FString BasePrefix;
+ FString BasePrefix_for_Open;
FStringVector FilePaths;
CObjectVector<NFind::CEnumerator> Enumerators;
@@ -54,22 +61,27 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r
{
filled = false;
resPath.Empty();
+
for (;;)
{
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ bool isRootPrefix = (BasePrefix.IsEmpty() || (NName::IsSuperPath(BasePrefix) && BasePrefix[NName::kSuperPathPrefixSize] == 0));
+ #endif
+
if (Enumerators.IsEmpty())
{
if (Index >= FilePaths.Size())
return S_OK;
const FString &path = FilePaths[Index++];
- int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR);
+ int pos = path.ReverseFind_PathSepar();
if (pos >= 0)
resPath.SetFrom(path, pos + 1);
- #ifdef _WIN32
- if (BasePrefix.IsEmpty() && path.Len() == 2 && path[1] == ':')
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (isRootPrefix && path.Len() == 2 && NName::IsDrivePath2(path))
{
// we use "c:" item as directory item
- fi.Clear();
+ fi.ClearBase();
fi.Name = path;
fi.SetAsDir();
fi.Size = 0;
@@ -82,9 +94,12 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r
resPath = path;
return error;
}
+
break;
}
+
bool found;
+
if (Enumerators.Back().Next(fi, found))
{
if (found)
@@ -101,18 +116,22 @@ DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &r
Prefixes.DeleteBack();
return error;
}
+
Enumerators.DeleteBack();
Prefixes.DeleteBack();
}
+
resPath += fi.Name;
+
if (EnterToDirs && fi.IsDir())
{
FString s = resPath;
- s += FCHAR_PATH_SEPARATOR;
+ s.Add_PathSepar();
Prefixes.Add(s);
s += FCHAR_ANY_MASK;
Enumerators.Add(NFind::CEnumerator(BasePrefix + s));
}
+
filled = true;
return S_OK;
}
@@ -137,10 +156,9 @@ void CThreadCrc::AddErrorMessage(DWORD systemError, const FChar *name)
void CThreadCrc::SetStatus(const UString &s2)
{
UString s = s2;
- if (Enumerator.BasePrefix)
+ if (!Enumerator.BasePrefix.IsEmpty())
{
- if (!s.IsEmpty())
- s += L' ';
+ s.Add_Space_if_NotEmpty();
s += fs2us(Enumerator.BasePrefix);
}
ProgressDialog.Sync.Set_Status(s);
@@ -201,10 +219,10 @@ HRESULT CThreadCrc::ProcessVirt()
*/
if (needPrint)
{
- RINOK(sync.ScanProgress(numFiles, totalSize, fs2us(path), fi.IsDir()));
+ RINOK(sync.ScanProgress(numFiles, totalSize, path, fi.IsDir()));
}
}
- RINOK(sync.ScanProgress(numFiles, totalSize, L"", false));
+ RINOK(sync.ScanProgress(numFiles, totalSize, FString(), false));
// sync.SetNumFilesTotal(numFiles);
// sync.SetProgress(totalSize, 0);
// SetStatus(LangString(IDS_CHECKSUM_CALCULATING));
@@ -235,7 +253,7 @@ HRESULT CThreadCrc::ProcessVirt()
if (!fi.IsDir())
{
NIO::CInFile inFile;
- tempPath = Enumerator.BasePrefix;
+ tempPath = Enumerator.BasePrefix_for_Open;
tempPath += path;
if (!inFile.Open(tempPath))
{
@@ -289,13 +307,8 @@ HRESULT CThreadCrc::ProcessVirt()
return S_OK;
}
-static void ThrowException_if_Error(HRESULT res)
-{
- if (res != S_OK)
- throw CSystemException(res);
-}
-void CApp::CalculateCrc(const UString &methodName)
+HRESULT CApp::CalculateCrc2(const UString &methodName)
{
int srcPanelIndex = GetFocusedPanelIndex();
CPanel &srcPanel = Panels[srcPanelIndex];
@@ -303,9 +316,9 @@ void CApp::CalculateCrc(const UString &methodName)
CRecordVector<UInt32> indices;
srcPanel.GetOperatedIndicesSmart(indices);
if (indices.IsEmpty())
- return;
+ return S_OK;
- if (!srcPanel.IsFsOrDrivesFolder())
+ if (!srcPanel.Is_IO_FS_Folder())
{
CCopyToOptions options;
options.streamMode = true;
@@ -313,27 +326,13 @@ void CApp::CalculateCrc(const UString &methodName)
options.hashMethods.Add(methodName);
UStringVector messages;
- HRESULT res = srcPanel.CopyTo(options, indices, &messages);
- if (res != S_OK)
- {
- if (res != E_ABORT)
- srcPanel.MessageBoxError(res);
- }
- return;
+ return srcPanel.CopyTo(options, indices, &messages);
}
- CCodecs *codecs = new CCodecs;
#ifdef EXTERNAL_CODECS
- CExternalCodecs __externalCodecs;
- __externalCodecs.GetCodecs = codecs;
- __externalCodecs.GetHashers = codecs;
- #else
- CMyComPtr<IUnknown> compressCodecsInfo = codecs;
- #endif
- ThrowException_if_Error(codecs->Load());
- #ifdef EXTERNAL_CODECS
- ThrowException_if_Error(__externalCodecs.LoadCodecs());
+ LoadGlobalCodecs();
+
#endif
{
@@ -341,11 +340,23 @@ void CApp::CalculateCrc(const UString &methodName)
{
UStringVector methods;
methods.Add(methodName);
- t.Hash.SetMethods(EXTERNAL_CODECS_VARS methods);
+ RINOK(t.Hash.SetMethods(EXTERNAL_CODECS_VARS_G methods));
}
FOR_VECTOR (i, indices)
t.Enumerator.FilePaths.Add(us2fs(srcPanel.GetItemRelPath(indices[i])));
- t.Enumerator.BasePrefix = us2fs(srcPanel.GetFsPath());
+
+ UString basePrefix = srcPanel.GetFsPath();
+ UString basePrefix2 = basePrefix;
+ if (basePrefix2.Back() == ':')
+ {
+ int pos = basePrefix2.ReverseFind_PathSepar();
+ if (pos >= 0)
+ basePrefix2.DeleteFrom(pos + 1);
+ }
+
+ t.Enumerator.BasePrefix = us2fs(basePrefix);
+ t.Enumerator.BasePrefix_for_Open = us2fs(basePrefix2);
+
t.Enumerator.EnterToDirs = !GetFlatMode();
t.ProgressDialog.ShowCompressionInfo = false;
@@ -354,10 +365,22 @@ void CApp::CalculateCrc(const UString &methodName)
t.ProgressDialog.MainWindow = _window;
t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE);
- t.ProgressDialog.MainAddTitle = title + UString(L' ');
+ t.ProgressDialog.MainAddTitle = title;
+ t.ProgressDialog.MainAddTitle.Add_Space();
- if (t.Create(title, _window) != S_OK)
- return;
+ RINOK(t.Create(title, _window));
}
RefreshTitleAlways();
+ return S_OK;
+}
+
+void CApp::CalculateCrc(const UString &methodName)
+{
+ HRESULT res = CalculateCrc2(methodName);
+ if (res != S_OK && res != E_ABORT)
+ {
+ int srcPanelIndex = GetFocusedPanelIndex();
+ CPanel &srcPanel = Panels[srcPanelIndex];
+ srcPanel.MessageBoxError(res);
+ }
}
diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp
index 9434d156..e20ddd63 100644
--- a/CPP/7zip/UI/FileManager/PanelDrag.cpp
+++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp
@@ -296,9 +296,11 @@ static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &na
void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
{
- CDisableTimerProcessing disableTimerProcessing2(*this);
if (!DoesItSupportOperations())
return;
+
+ CDisableTimerProcessing disableTimerProcessing2(*this);
+
CRecordVector<UInt32> indices;
GetOperatedItemIndices(indices);
if (indices.Size() == 0)
@@ -312,7 +314,7 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
bool isFSFolder = IsFSFolder();
if (isFSFolder)
- dirPrefix = us2fs(_currentFolderPrefix);
+ dirPrefix = us2fs(GetFsPath());
else
{
tempDirectory.Create(kTempDirPrefix);
@@ -580,7 +582,9 @@ bool CDropTarget::IsItSameDrive() const
return false;
if (!IsFsFolderPath())
return false;
+
UString drive;
+
if (m_Panel->IsFSFolder())
{
drive = m_Panel->GetDriveOrNetworkPrefix();
@@ -594,13 +598,14 @@ bool CDropTarget::IsItSameDrive() const
if (m_SourcePaths.Size() == 0)
return false;
+
FOR_VECTOR (i, m_SourcePaths)
{
- if (MyStringCompareNoCase_N(m_SourcePaths[i], drive, drive.Len()) != 0)
+ if (!m_SourcePaths[i].IsPrefixedBy_NoCase(drive))
return false;
}
+
return true;
-
}
DWORD CDropTarget::GetEffect(DWORD keyState, POINTL /* pt */, DWORD allowedEffect)
@@ -635,13 +640,11 @@ UString CDropTarget::GetTargetPath() const
{
if (!IsFsFolderPath())
return UString();
- UString path = m_Panel->_currentFolderPrefix;
- if (m_Panel->IsFSDrivesFolder())
- path.Empty();
+ UString path = m_Panel->GetFsPath();
if (m_SubFolderIndex >= 0 && !m_SubFolderName.IsEmpty())
{
path += m_SubFolderName;
- path += WCHAR_PATH_SEPARATOR;
+ path.Add_PathSepar();
}
return path;
}
@@ -728,7 +731,7 @@ STDMETHODIMP CDropTarget::Drop(IDataObject *dataObject, DWORD keyState,
UString path = GetTargetPath();
if (m_IsAppTarget && m_Panel)
if (m_Panel->IsFSFolder())
- path = m_Panel->_currentFolderPrefix;
+ path = m_Panel->GetFsPath();
m_Panel->DropObject(dataObject, path);
}
}
@@ -779,7 +782,7 @@ static bool AreThereNamesFromTemp(const UStringVector &fileNames)
if (tempPath.IsEmpty())
return false;
FOR_VECTOR (i, fileNames)
- if (MyStringCompareNoCase_N(fileNames[i], tempPath, tempPath.Len()) == 0)
+ if (fileNames[i].IsPrefixedBy_NoCase(tempPath))
return true;
return false;
}
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
index 83993bb1..cd70c727 100644
--- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
+++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
@@ -28,10 +28,38 @@ using namespace NWindows;
using namespace NFile;
using namespace NFind;
+void CPanel::ReleaseFolder()
+{
+ _folder.Release();
+
+ _folderCompare.Release();
+ _folderGetItemName.Release();
+ _folderRawProps.Release();
+ _folderAltStreams.Release();
+ _folderOperations.Release();
+
+ _thereAreDeletedItems = false;
+}
+
+void CPanel::SetNewFolder(IFolderFolder *newFolder)
+{
+ ReleaseFolder();
+ _folder = newFolder;
+ if (_folder)
+ {
+ _folder.QueryInterface(IID_IFolderCompare, &_folderCompare);
+ _folder.QueryInterface(IID_IFolderGetItemName, &_folderGetItemName);
+ _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps);
+ _folder.QueryInterface(IID_IFolderAltStreams, &_folderAltStreams);
+ _folder.QueryInterface(IID_IFolderOperations, &_folderOperations);
+ }
+}
+
void CPanel::SetToRootFolder()
{
ReleaseFolder();
_library.Free();
+
CRootFolder *rootFolderSpec = new CRootFolder;
SetNewFolder(rootFolderSpec);
rootFolderSpec->Init();
@@ -39,105 +67,188 @@ void CPanel::SetToRootFolder()
HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted)
{
+ UString path = fullPath;
+ #ifdef _WIN32
+ path.Replace(L'/', WCHAR_PATH_SEPARATOR);
+ #endif
+
archiveIsOpened = false;
encrypted = false;
+
CDisableTimerProcessing disableTimerProcessing(*this);
CDisableNotify disableNotify(*this);
- if (_parentFolders.Size() > 0)
+ for (; !_parentFolders.IsEmpty(); CloseOneLevel())
{
- const UString &virtPath = _parentFolders.Back().VirtualPath;
- if (fullPath.IsPrefixedBy(virtPath))
+ // ---------- we try to use open archive ----------
+
+ const CFolderLink &link = _parentFolders.Back();
+ const UString &virtPath = link.VirtualPath;
+ if (!path.IsPrefixedBy(virtPath))
+ continue;
+ UString relatPath = path.Ptr(virtPath.Len());
+ if (!relatPath.IsEmpty())
{
- for (;;)
- {
- CMyComPtr<IFolderFolder> newFolder;
- HRESULT res = _folder->BindToParentFolder(&newFolder);
- if (!newFolder || res != S_OK)
- break;
- SetNewFolder(newFolder);
- }
- UStringVector parts;
- SplitPathToParts(fullPath.Ptr(virtPath.Len()), parts);
- FOR_VECTOR (i, parts)
+ if (!IS_PATH_SEPAR(relatPath[0]))
+ continue;
+ else
+ relatPath.Delete(0);
+ }
+
+ UString relatPath2 = relatPath;
+ if (!relatPath2.IsEmpty() && !IS_PATH_SEPAR(relatPath2.Back()))
+ relatPath2.Add_PathSepar();
+
+ for (;;)
+ {
+ const UString foldPath = GetFolderPath(_folder);
+ if (relatPath2 == foldPath)
+ break;
+ if (relatPath.IsPrefixedBy(foldPath))
{
- const UString &s = parts[i];
- if ((i == 0 || i == parts.Size() - 1) && s.IsEmpty())
- continue;
- CMyComPtr<IFolderFolder> newFolder;
- HRESULT res = _folder->BindToFolder(s, &newFolder);
- if (!newFolder || res != S_OK)
- break;
- SetNewFolder(newFolder);
+ path = relatPath.Ptr(foldPath.Len());
+ break;
}
- return S_OK;
+ CMyComPtr<IFolderFolder> newFolder;
+ if (_folder->BindToParentFolder(&newFolder) != S_OK)
+ throw 20140918;
+ if (!newFolder) // we exit from loop above if (relatPath.IsPrefixedBy(empty path for root folder)
+ throw 20140918;
+ SetNewFolder(newFolder);
}
+ break;
}
- CloseOpenFolders();
- UString sysPath = fullPath;
- CFileInfo fileInfo;
- UStringVector reducedParts;
- while (!sysPath.IsEmpty())
+ if (_parentFolders.IsEmpty())
{
- if (fileInfo.Find(us2fs(sysPath)))
- break;
- int pos = sysPath.ReverseFind(WCHAR_PATH_SEPARATOR);
- if (pos < 0)
+ // ---------- we open file or folder from file system ----------
+
+ CloseOpenFolders();
+ UString sysPath = path;
+
+ unsigned prefixSize = NName::GetRootPrefixSize(sysPath);
+ if (prefixSize == 0 || sysPath[prefixSize] == 0)
sysPath.Empty();
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (!sysPath.IsEmpty() && sysPath.Back() == ':' &&
+ (sysPath.Len() != 2 || !NName::IsDrivePath2(sysPath)))
+ {
+ UString baseFile = sysPath;
+ baseFile.DeleteBack();
+ if (NFind::DoesFileOrDirExist(us2fs(baseFile)))
+ sysPath.Empty();
+ }
+ #endif
+
+ CFileInfo fileInfo;
+
+ while (!sysPath.IsEmpty())
+ {
+ if (fileInfo.Find(us2fs(sysPath)))
+ break;
+ int pos = sysPath.ReverseFind_PathSepar();
+ if (pos < 0)
+ sysPath.Empty();
+ else
+ {
+ /*
+ if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1)
+ reducedParts.Add(sysPath.Ptr(pos + 1));
+ */
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (pos == 2 && NName::IsDrivePath2(sysPath) && sysPath.Len() > 3)
+ pos++;
+ #endif
+
+ sysPath.DeleteFrom(pos);
+ }
+ }
+
+ SetToRootFolder();
+
+ CMyComPtr<IFolderFolder> newFolder;
+
+ if (sysPath.IsEmpty())
+ {
+ _folder->BindToFolder(path, &newFolder);
+ }
+ else if (fileInfo.IsDir())
+ {
+ NName::NormalizeDirPathPrefix(sysPath);
+ _folder->BindToFolder(sysPath, &newFolder);
+ }
else
{
- if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1)
- reducedParts.Add(sysPath.Ptr(pos + 1));
- sysPath.DeleteFrom(pos);
+ FString dirPrefix, fileName;
+ NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
+ HRESULT res;
+ // = OpenItemAsArchive(fs2us(fileName), arcFormat, encrypted);
+ {
+ CTempFileInfo tfi;
+ tfi.RelPath = fs2us(fileName);
+ tfi.FolderPath = dirPrefix;
+ tfi.FilePath = us2fs(sysPath);
+ res = OpenItemAsArchive(NULL, tfi, sysPath, arcFormat, encrypted);
+ }
+
+ if (res == S_FALSE)
+ _folder->BindToFolder(fs2us(dirPrefix), &newFolder);
+ else
+ {
+ RINOK(res);
+ archiveIsOpened = true;
+ _parentFolders.Back().ParentFolderPath = fs2us(dirPrefix);
+ path.DeleteFrontal(sysPath.Len());
+ if (!path.IsEmpty() && IS_PATH_SEPAR(path[0]))
+ path.Delete(0);
+ }
}
- }
- SetToRootFolder();
- CMyComPtr<IFolderFolder> newFolder;
- if (sysPath.IsEmpty())
- {
- if (_folder->BindToFolder(fullPath, &newFolder) == S_OK)
- SetNewFolder(newFolder);
- }
- else if (fileInfo.IsDir())
- {
- NName::NormalizeDirPathPrefix(sysPath);
- if (_folder->BindToFolder(sysPath, &newFolder) == S_OK)
+ if (newFolder)
+ {
SetNewFolder(newFolder);
+ // LoadFullPath();
+ return S_OK;
+ }
}
- else
+
{
- FString dirPrefix, fileName;
- NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
- if (_folder->BindToFolder(fs2us(dirPrefix), &newFolder) == S_OK)
+ // ---------- we open folder remPath in archive and sub archives ----------
+
+ for (unsigned curPos = 0; curPos != path.Len();)
{
- SetNewFolder(newFolder);
- LoadFullPath();
+ UString s = path.Ptr(curPos);
+ int slashPos = NName::FindSepar(s);
+ unsigned skipLen = s.Len();
+ if (slashPos >= 0)
{
- HRESULT res = OpenItemAsArchive(fs2us(fileName), arcFormat, encrypted);
- if (res != S_FALSE)
- {
- RINOK(res);
- }
- /*
- if (res == E_ABORT)
- return res;
- */
- if (res == S_OK)
+ s.DeleteFrom(slashPos);
+ skipLen = slashPos + 1;
+ }
+
+ CMyComPtr<IFolderFolder> newFolder;
+ _folder->BindToFolder(s, &newFolder);
+ if (newFolder)
+ curPos += skipLen;
+ else if (_folderAltStreams)
+ {
+ int pos = s.Find(L':');
+ if (pos >= 0)
{
- archiveIsOpened = true;
- for (int i = reducedParts.Size() - 1; i >= 0; i--)
- {
- CMyComPtr<IFolderFolder> newFolder;
- _folder->BindToFolder(reducedParts[i], &newFolder);
- if (!newFolder)
- break;
- SetNewFolder(newFolder);
- }
+ UString baseName = s;
+ baseName.DeleteFrom(pos);
+ if (_folderAltStreams->BindToAltStreams(baseName, &newFolder) == S_OK && newFolder)
+ curPos += pos + 1;
}
}
+
+ if (!newFolder)
+ break;
+
+ SetNewFolder(newFolder);
}
}
+
return S_OK;
}
@@ -163,10 +274,12 @@ void CPanel::OpenBookmark(int index)
UString GetFolderPath(IFolderFolder *folder)
{
- NCOM::CPropVariant prop;
- if (folder->GetFolderProperty(kpidPath, &prop) == S_OK)
- if (prop.vt == VT_BSTR)
- return (wchar_t *)prop.bstrVal;
+ {
+ NCOM::CPropVariant prop;
+ if (folder->GetFolderProperty(kpidPath, &prop) == S_OK)
+ if (prop.vt == VT_BSTR)
+ return (wchar_t *)prop.bstrVal;
+ }
return UString();
}
@@ -176,9 +289,10 @@ void CPanel::LoadFullPath()
FOR_VECTOR (i, _parentFolders)
{
const CFolderLink &folderLink = _parentFolders[i];
- _currentFolderPrefix += GetFolderPath(folderLink.ParentFolder);
+ _currentFolderPrefix += folderLink.ParentFolderPath;
+ // GetFolderPath(folderLink.ParentFolder);
_currentFolderPrefix += folderLink.RelPath;
- _currentFolderPrefix += WCHAR_PATH_SEPARATOR;
+ _currentFolderPrefix.Add_PathSepar();
}
if (_folder)
_currentFolderPrefix += GetFolderPath(_folder);
@@ -364,7 +478,7 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
{
UString name = pathParts[i];
sumPass += name;
- sumPass += WCHAR_PATH_SEPARATOR;
+ sumPass.Add_PathSepar();
CFileInfo info;
DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
if (info.Find(us2fs(sumPass)))
@@ -496,73 +610,104 @@ void CPanel::FoldersHistory()
void CPanel::OpenParentFolder()
{
LoadFullPath(); // Maybe we don't need it ??
- UString focucedName;
- if (!_currentFolderPrefix.IsEmpty() &&
- _currentFolderPrefix.Back() == WCHAR_PATH_SEPARATOR)
+
+ UString parentFolderPrefix;
+ UString focusedName;
+
+ if (!_currentFolderPrefix.IsEmpty())
{
- focucedName = _currentFolderPrefix;
- focucedName.DeleteBack();
- if (focucedName != L"\\\\.")
+ wchar_t c = _currentFolderPrefix.Back();
+ if (c == WCHAR_PATH_SEPARATOR || c == ':')
{
- int pos = focucedName.ReverseFind(WCHAR_PATH_SEPARATOR);
- if (pos >= 0)
- focucedName.DeleteFrontal(pos + 1);
+ focusedName = _currentFolderPrefix;
+ focusedName.DeleteBack();
+ /*
+ if (c == ':' && !focusedName.IsEmpty() && focusedName.Back() == WCHAR_PATH_SEPARATOR)
+ {
+ focusedName.DeleteBack();
+ }
+ else
+ */
+ if (focusedName != L"\\\\." &&
+ focusedName != L"\\\\?")
+ {
+ int pos = focusedName.ReverseFind_PathSepar();
+ if (pos >= 0)
+ {
+ parentFolderPrefix = focusedName;
+ parentFolderPrefix.DeleteFrom(pos + 1);
+ focusedName.DeleteFrontal(pos + 1);
+ }
+ }
}
}
CDisableTimerProcessing disableTimerProcessing(*this);
CDisableNotify disableNotify(*this);
+
CMyComPtr<IFolderFolder> newFolder;
_folder->BindToParentFolder(&newFolder);
+
+ // newFolder.Release(); // for test
+
if (newFolder)
SetNewFolder(newFolder);
else
{
- if (_parentFolders.IsEmpty())
+ bool needSetFolder = true;
+ if (!_parentFolders.IsEmpty())
{
- SetToRootFolder();
- if (focucedName.IsEmpty())
- focucedName = GetItemName(0);
+ {
+ const CFolderLink &link = _parentFolders.Back();
+ parentFolderPrefix = link.ParentFolderPath;
+ focusedName = link.RelPath;
+ }
+ CloseOneLevel();
+ needSetFolder = (!_folder);
}
- else
+
+ if (needSetFolder)
{
- ReleaseFolder();
- _library.Free();
- CFolderLink &link = _parentFolders.Back();
- SetNewFolder(link.ParentFolder);
- _library.Attach(link.Library.Detach());
- focucedName = link.RelPath;
- if (_parentFolders.Size() > 1)
- OpenParentArchiveFolder();
- _parentFolders.DeleteBack();
- if (_parentFolders.IsEmpty())
- _flatMode = _flatModeForDisk;
+ {
+ bool archiveIsOpened;
+ bool encrypted;
+ BindToPath(parentFolderPrefix, UString(), archiveIsOpened, encrypted);
+ }
}
}
-
+
UStringVector selectedItems;
/*
- if (!focucedName.IsEmpty())
- selectedItems.Add(focucedName);
+ if (!focusedName.IsEmpty())
+ selectedItems.Add(focusedName);
*/
LoadFullPath();
// ::SetCurrentDirectory(::_currentFolderPrefix);
- RefreshListCtrl(focucedName, -1, true, selectedItems);
+ RefreshListCtrl(focusedName, -1, true, selectedItems);
// _listView.EnsureVisible(_listView.GetFocusedItem(), false);
}
-void CPanel::CloseOpenFolders()
+void CPanel::CloseOneLevel()
{
- while (_parentFolders.Size() > 0)
+ ReleaseFolder();
+ _library.Free();
{
- ReleaseFolder();
- _library.Free();
- SetNewFolder(_parentFolders.Back().ParentFolder);
- _library.Attach(_parentFolders.Back().Library.Detach());
- if (_parentFolders.Size() > 1)
- OpenParentArchiveFolder();
- _parentFolders.DeleteBack();
+ CFolderLink &link = _parentFolders.Back();
+ if (link.ParentFolder)
+ SetNewFolder(link.ParentFolder);
+ _library.Attach(link.Library.Detach());
}
+ if (_parentFolders.Size() > 1)
+ OpenParentArchiveFolder();
+ _parentFolders.DeleteBack();
+ if (_parentFolders.IsEmpty())
+ _flatMode = _flatModeForDisk;
+}
+
+void CPanel::CloseOpenFolders()
+{
+ while (!_parentFolders.IsEmpty())
+ CloseOneLevel();
_flatMode = _flatModeForDisk;
ReleaseFolder();
_library.Free();
@@ -618,3 +763,45 @@ void CPanel::OpenFolder(int index)
_listView.SetItemState_Selected(_listView.GetFocusedItem());
_listView.EnsureVisible(_listView.GetFocusedItem(), false);
}
+
+void CPanel::OpenAltStreams()
+{
+ CRecordVector<UInt32> indices;
+ GetOperatedItemIndices(indices);
+ Int32 realIndex = -1;
+ if (indices.Size() > 1)
+ return;
+ if (indices.Size() == 1)
+ realIndex = indices[0];
+
+ if (_folderAltStreams)
+ {
+ CMyComPtr<IFolderFolder> newFolder;
+ _folderAltStreams->BindToAltStreams(realIndex, &newFolder);
+ if (newFolder)
+ {
+ CDisableTimerProcessing disableTimerProcessing(*this);
+ CDisableNotify disableNotify(*this);
+ SetNewFolder(newFolder);
+ RefreshListCtrl(UString(), -1, true, UStringVector());
+ return;
+ }
+ return;
+ }
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ UString path;
+ if (realIndex >= 0)
+ path = GetItemFullPath(realIndex);
+ else
+ {
+ path = GetFsPath();
+ if (!NName::IsDriveRootPath_SuperAllowed(us2fs(path)))
+ if (!path.IsEmpty() && IS_PATH_SEPAR(path.Back()))
+ path.DeleteBack();
+ }
+
+ path += L':';
+ BindToPathAndRefresh(path);
+ #endif
+}
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
index d9beedb8..a485522f 100644
--- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -157,7 +157,8 @@ public:
static bool IsNameVirus(const UString &name)
{
- return (name.Find(L" ") >= 0);
+ // return (name.Find(L" ") >= 0);
+ return (wcsstr(name, L" ") != NULL);
}
struct CTmpProcessInfo: public CTempFileInfo
@@ -223,7 +224,13 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,
folderLink.Password = password;
folderLink.UsePassword = encrypted;
- folderLink.ParentFolder = _folder;
+ if (_folder)
+ folderLink.ParentFolderPath = GetFolderPath(_folder);
+ else
+ folderLink.ParentFolderPath = _currentFolderPrefix;
+ if (!_parentFolders.IsEmpty())
+ folderLink.ParentFolder = _folder;
+
_parentFolders.Add(folderLink);
_parentFolders.Back().Library.Attach(_library.Detach());
@@ -272,7 +279,7 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,
if (!values[0].IsEmpty())
{
if (!s2.IsEmpty())
- s2 += L"\n";
+ s2.Add_LF();
s2 += L"[";
s2 += values[2];
s2 += L"] Error: ";
@@ -283,7 +290,7 @@ HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,
if (!s.IsEmpty())
s += L"--------------------\n";
s += values[1];
- s += L"\n";
+ s.Add_LF();
s += s2;
}
}
@@ -305,8 +312,8 @@ HRESULT CPanel::OpenItemAsArchive(const UString &relPath, const UString &arcForm
{
CTempFileInfo tfi;
tfi.RelPath = relPath;
- tfi.FolderPath = us2fs(_currentFolderPrefix);
- const UString fullPath = _currentFolderPrefix + relPath;
+ tfi.FolderPath = us2fs(GetFsPath());
+ const UString fullPath = GetFsPath() + relPath;
tfi.FilePath = us2fs(fullPath);
return OpenItemAsArchive(NULL, tfi, fullPath, arcFormat, encrypted);
}
@@ -316,7 +323,7 @@ HRESULT CPanel::OpenItemAsArchive(int index)
CDisableTimerProcessing disableTimerProcessing1(*this);
CDisableNotify disableNotify(*this);
bool encrypted;
- HRESULT res = OpenItemAsArchive(GetItemRelPath(index), UString(), encrypted);
+ HRESULT res = OpenItemAsArchive(GetItemRelPath2(index), UString(), encrypted);
if (res != S_OK)
{
RefreshTitle(true); // in case of error we must refresh changed title of 7zFM
@@ -379,7 +386,7 @@ static const char *kStartExtensions =
static bool FindExt(const char *p, const UString &name)
{
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
if (dotPos < 0 || dotPos == (int)name.Len() - 1)
return false;
@@ -409,10 +416,7 @@ static bool DoItemAlwaysStart(const UString &name)
return FindExt(kStartExtensions, name);
}
-static UString GetQuotedString(const UString &s)
-{
- return UString(L'\"') + s + UString(L'\"');
-}
+UString GetQuotedString(const UString &s);
static HRESULT StartEditApplication(const UString &path, bool useEditor, HWND window, CProcess &process)
{
@@ -455,13 +459,17 @@ void CApp::DiffFiles()
{
const CPanel &destPanel = Panels[1 - LastFocusedPanel];
path1 = panel.GetItemFullPath(indices[0]);
- const UString relPath = panel.GetItemRelPath(indices[0]);
CRecordVector<UInt32> indices2;
destPanel.GetSelectedItemsIndices(indices2);
if (indices2.Size() == 1)
path2 = destPanel.GetItemFullPath(indices2[0]);
else
+ {
+ UString relPath = panel.GetItemRelPath2(indices[0]);
+ if (panel._flatMode && !destPanel._flatMode)
+ relPath = panel.GetItemName(indices[0]);
path2 = destPanel._currentFolderPrefix + relPath;
+ }
}
else
return;
@@ -471,7 +479,9 @@ void CApp::DiffFiles()
if (command.IsEmpty())
return;
- UString param = GetQuotedString(path1) + L' ' + GetQuotedString(path2);
+ UString param = GetQuotedString(path1);
+ param.Add_Space();
+ param += GetQuotedString(path2);
HRESULT res = MyCreateProcess(command, param);
if (res == SZ_OK)
@@ -573,11 +583,11 @@ void CPanel::OpenFolderExternal(int index)
UString name;
if (index == kParentIndex)
{
- int pos = fsPrefix.ReverseFind(WCHAR_PATH_SEPARATOR);
+ int pos = fsPrefix.ReverseFind_PathSepar();
if (pos >= 0 && pos == (int)fsPrefix.Len() - 1)
{
UString s = fsPrefix.Left(pos);
- pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);
+ pos = s.ReverseFind_PathSepar();
if (pos >= 0)
fsPrefix.SetFrom(s, pos + 1);
}
@@ -591,7 +601,7 @@ void CPanel::OpenFolderExternal(int index)
void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal)
{
CDisableTimerProcessing disableTimerProcessing(*this);
- UString name = GetItemRelPath(index);
+ UString name = GetItemRelPath2(index);
if (IsNameVirus(name))
{
MessageBoxErrorLang(IDS_VIRUS);
@@ -650,8 +660,7 @@ HRESULT CThreadCopyFrom::ProcessVirt()
HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath,
bool usePassword, const UString &password)
{
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
+ if (!_folderOperations)
{
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return E_FAIL;
@@ -663,8 +672,13 @@ HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath,
t.UpdateCallbackSpec->ProgressDialog = &t.ProgressDialog;
t.ItemIndex = index;
t.FullPath = fullFilePath;
- t.FolderOperations = folderOperations;
- t.UpdateCallbackSpec->Init(usePassword, password);
+ t.FolderOperations = _folderOperations;
+
+ t.UpdateCallbackSpec->Init();
+ t.UpdateCallbackSpec->PasswordIsDefined = usePassword;
+ t.UpdateCallbackSpec->Password = password;
+
+
RINOK(t.Create(GetItemName(index), (HWND)*this));
return t.Result;
}
@@ -862,8 +876,11 @@ STDMETHODIMP CBufSeqOutStream_WithFile::Write(const void *data, UInt32 size, UIn
{
if (_size - _pos >= size)
{
- memcpy(_buffer + _pos, data, size);
- _pos += size;
+ if (size != 0)
+ {
+ memcpy(_buffer + _pos, data, size);
+ _pos += size;
+ }
if (processedSize)
*processedSize = (UInt32)size;
return S_OK;
@@ -931,8 +948,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
return;
}
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
+ if (!_folderOperations)
{
MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
@@ -951,7 +967,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
FString tempDir = tempDirectory.GetPath();
FString tempDirNorm = tempDir;
NName::NormalizeDirPathPrefix(tempDirNorm);
- const FString tempFilePath = tempDirNorm + us2fs(GetCorrectFsPath(name));
+ const FString tempFilePath = tempDirNorm + us2fs(Get_Correct_FsFile_Name(name));
CTempFileInfo tempFileInfo;
tempFileInfo.FileIndex = index;
@@ -1029,7 +1045,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
bool isAltStream = IsItem_AltStream(index);
CCopyToOptions options;
- options.includeAltStreams = false;
+ options.includeAltStreams = true;
options.replaceAltStreamChars = isAltStream;
if (tryAsArchive)
@@ -1137,11 +1153,11 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
return;
CProcess process;
- /* HRESULT res; */
+ // HRESULT res;
if (editMode)
/* res = */ StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process);
else
- /* res = */ StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process);
+ /* res = */ StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process);
if ((HANDLE)process == 0)
return;
diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp
index 8d74b8cd..491a36ad 100644
--- a/CPP/7zip/UI/FileManager/PanelItems.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItems.cpp
@@ -4,6 +4,7 @@
#include "../../../../C/Sort.h"
+#include "../../../Windows/FileName.h"
#include "../../../Windows/Menu.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/PropVariantConv.h"
@@ -103,7 +104,7 @@ HRESULT CPanel::InitColumns()
_properties.Clear();
_needSaveInfo = true;
- bool isFsFolder = IsFSFolder();
+ bool isFsFolder = IsFSFolder() || IsAltStreamsFolder();
{
UInt32 numProps;
@@ -401,7 +402,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
int cursorIndex = -1;
CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
- if (!IsFSFolder() || _showRealFileIcons)
+ if (!Is_Slow_Icon_Folder() || _showRealFileIcons)
_folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
if (!IsFSFolder())
@@ -436,7 +437,8 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
int subItem = 0;
item.iSubItem = subItem++;
item.lParam = kParentIndex;
- item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);
+ // item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);
+ item.pszText = LPSTR_TEXTCALLBACKW;
UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);
if (item.iImage < 0)
@@ -451,19 +453,23 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
UString correctedName;
UString itemName;
UString relPath;
+
for (UInt32 i = 0; i < numItems; i++)
{
const wchar_t *name = NULL;
unsigned nameLen = 0;
+
if (_folderGetItemName)
_folderGetItemName->GetItemName(i, &name, &nameLen);
- if (name == NULL)
+ if (!name)
{
- GetItemNameFast(i, itemName);
+ GetItemName(i, itemName);
name = itemName;
nameLen = itemName.Len();
}
+
bool selected = false;
+
if (!focusedName.IsEmpty() || !selectedNames.IsEmpty())
{
relPath.Empty();
@@ -495,6 +501,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
if (selectedNames.FindInSorted(relPath) >= 0)
selected = true;
}
+
_selectedStatusVector.AddInReserved(selected);
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
@@ -567,6 +574,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
// }
bool defined = false;
+
if (folderGetSystemIconIndex)
{
folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
@@ -585,6 +593,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
item.iImage = _extToIconMap.GetIconIndex(attrib, name);
}
}
+
if (item.iImage < 0)
item.iImage = 0;
@@ -592,6 +601,7 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool
return E_FAIL;
listViewItemCount++;
}
+
// OutputDebugStringA("End2\n");
if (_listView.GetItemCount() > 0 && cursorIndex >= 0)
@@ -831,7 +841,24 @@ UString CPanel::GetItemName(int itemIndex) const
return prop.bstrVal;
}
-void CPanel::GetItemNameFast(int itemIndex, UString &s) const
+UString CPanel::GetItemName_for_Copy(int itemIndex) const
+{
+ if (itemIndex == kParentIndex)
+ return L"..";
+ {
+ NCOM::CPropVariant prop;
+ if (_folder->GetProperty(itemIndex, kpidOutName, &prop) == S_OK)
+ {
+ if (prop.vt == VT_BSTR)
+ return prop.bstrVal;
+ if (prop.vt != VT_EMPTY)
+ throw 2723401;
+ }
+ }
+ return GetItemName(itemIndex);
+}
+
+void CPanel::GetItemName(int itemIndex, UString &s) const
{
if (itemIndex == kParentIndex)
{
@@ -843,8 +870,7 @@ void CPanel::GetItemNameFast(int itemIndex, UString &s) const
throw 2723400;
if (prop.vt != VT_BSTR)
throw 2723401;
- s.Empty();
- s += prop.bstrVal;
+ s.SetFromBstr(prop.bstrVal);
}
UString CPanel::GetItemPrefix(int itemIndex) const
@@ -856,7 +882,7 @@ UString CPanel::GetItemPrefix(int itemIndex) const
throw 2723400;
UString prefix;
if (prop.vt == VT_BSTR)
- prefix = prop.bstrVal;
+ prefix.SetFromBstr(prop.bstrVal);
return prefix;
}
@@ -865,9 +891,22 @@ UString CPanel::GetItemRelPath(int itemIndex) const
return GetItemPrefix(itemIndex) + GetItemName(itemIndex);
}
+UString CPanel::GetItemRelPath2(int itemIndex) const
+{
+ UString s = GetItemRelPath(itemIndex);
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (s.Len() == 2 && NFile::NName::IsDrivePath2(s))
+ {
+ if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix())
+ s.Add_PathSepar();
+ }
+ #endif
+ return s;
+}
+
UString CPanel::GetItemFullPath(int itemIndex) const
{
- return _currentFolderPrefix + GetItemRelPath(itemIndex);
+ return GetFsPath() + GetItemRelPath2(itemIndex);
}
bool CPanel::GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const
@@ -928,6 +967,7 @@ void CPanel::ReadListViewInfo()
void CPanel::SaveListViewInfo()
{
unsigned i;
+
for (i = 0; i < _visibleProperties.Size(); i++)
{
CItemProperty &prop = _visibleProperties[i];
@@ -945,6 +985,7 @@ void CPanel::SaveListViewInfo()
PROPID sortPropID = _sortID;
_visibleProperties.Sort();
+
for (i = 0; i < _visibleProperties.Size(); i++)
{
const CItemProperty &prop = _visibleProperties[i];
@@ -954,6 +995,7 @@ void CPanel::SaveListViewInfo()
columnInfo.Width = prop.Width;
viewInfo.Columns.Add(columnInfo);
}
+
for (i = 0; i < _properties.Size(); i++)
{
const CItemProperty &prop = _properties[i];
@@ -1025,21 +1067,24 @@ void CPanel::ShowColumnsContextMenu(int x, int y)
else
{
int visibleIndex = _visibleProperties.FindItemWithID(prop.ID);
- _visibleProperties.Delete(visibleIndex);
- /*
- if (_sortIndex == index)
+ if (visibleIndex >= 0)
{
+ _visibleProperties.Delete(visibleIndex);
+ /*
+ if (_sortIndex == index)
+ {
_sortIndex = 0;
_ascending = true;
+ }
+ */
+ if (_sortID == prop.ID)
+ {
+ _sortID = kpidName;
+ _ascending = true;
+ }
+
+ _listView.DeleteColumn(visibleIndex);
}
- */
- if (_sortID == prop.ID)
- {
- _sortID = kpidName;
- _ascending = true;
- }
-
- _listView.DeleteColumn(visibleIndex);
}
}
}
diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
index 7be6aa62..2f37db14 100644
--- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp
+++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
@@ -19,30 +19,57 @@
using namespace NWindows;
-static void ConvertSizeToString(UInt64 value, wchar_t *dest)
+#define INT_TO_STR_SPEC(v) \
+ while (v >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(v % 10)); v /= 10; } \
+ *s++ = (unsigned char)('0' + (unsigned)v);
+
+static void ConvertSizeToString(UInt64 val, wchar_t *s) throw()
{
- char s[32];
- ConvertUInt64ToString(value, s);
- unsigned i = MyStringLen(s);
- unsigned pos = ARRAY_SIZE(s);
- s[--pos] = 0;
- while (i > 3)
+ unsigned char temp[32];
+ unsigned i = 0;
+
+ if (val <= (UInt32)0xFFFFFFFF)
+ {
+ UInt32 val32 = (UInt32)val;
+ INT_TO_STR_SPEC(val32)
+ }
+ else
{
- s[--pos] = s[--i];
- s[--pos] = s[--i];
- s[--pos] = s[--i];
- s[--pos] = L' ';
+ INT_TO_STR_SPEC(val)
}
- while (i > 0)
- s[--pos] = s[--i];
- for (;;)
+ if (i < 3)
{
- char c = s[pos++];
- *dest++ = (unsigned char)c;
- if (c == 0)
- break;
+ if (i != 0)
+ {
+ *s++ = temp[i - 1];
+ if (i == 2)
+ *s++ = temp[0];
+ }
+ *s = 0;
+ return;
+ }
+
+ unsigned r = i % 3;
+ if (r != 0)
+ {
+ s[0] = temp[--i];
+ if (r == 2)
+ s[1] = temp[--i];
+ s += r;
}
+
+ do
+ {
+ s[0] = ' ';
+ s[1] = temp[i - 1];
+ s[2] = temp[i - 2];
+ s[3] = temp[i - 3];
+ s += 4;
+ }
+ while (i -= 3);
+
+ *s = 0;
}
UString ConvertSizeToString(UInt64 value)
@@ -52,29 +79,62 @@ UString ConvertSizeToString(UInt64 value)
return s;
}
-static inline char GetHex(Byte value)
+static inline unsigned GetHex(unsigned v)
{
- return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+ return (v < 10) ? ('0' + v) : ('A' + (v - 10));
}
-void HexToString(char *dest, const Byte *data, UInt32 size)
+/*
+static void HexToString(char *dest, const Byte *data, UInt32 size)
{
for (UInt32 i = 0; i < size; i++)
{
- Byte b = data[i];
- dest[0] = GetHex((Byte)((b >> 4) & 0xF));
- dest[1] = GetHex((Byte)(b & 0xF));
+ unsigned b = data[i];
+ dest[0] = GetHex((b >> 4) & 0xF);
+ dest[1] = GetHex(b & 0xF);
dest += 2;
}
*dest = 0;
}
+*/
-LRESULT CPanel::SetItemText(LVITEMW &item)
+bool IsSizeProp(UINT propID) throw()
{
+ switch (propID)
+ {
+ case kpidSize:
+ case kpidPackSize:
+ case kpidNumSubDirs:
+ case kpidNumSubFiles:
+ case kpidOffset:
+ case kpidLinks:
+ case kpidNumBlocks:
+ case kpidNumVolumes:
+ case kpidPhySize:
+ case kpidHeadersSize:
+ case kpidTotalSize:
+ case kpidFreeSpace:
+ case kpidClusterSize:
+ case kpidNumErrors:
+ case kpidNumStreams:
+ case kpidNumAltStreams:
+ case kpidAltStreamsSize:
+ case kpidVirtualSize:
+ case kpidUnpackSize:
+ case kpidTotalPhySize:
+ case kpidTailSize:
+ case kpidEmbeddedStubSize:
+ return true;
+ }
+ return false;
+}
+LRESULT CPanel::SetItemText(LVITEMW &item)
+{
if (_dontShowMode)
return 0;
UInt32 realIndex = GetRealIndex(item);
+
/*
if ((item.mask & LVIF_IMAGE) != 0)
{
@@ -107,10 +167,31 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
if ((item.mask & LVIF_TEXT) == 0)
return 0;
- if (realIndex == kParentIndex)
+ LPWSTR text = item.pszText;
+
+ if (item.cchTextMax > 0)
+ text[0] = 0;
+
+ if (item.cchTextMax <= 1)
return 0;
+
const CItemProperty &property = _visibleProperties[item.iSubItem];
PROPID propID = property.ID;
+
+ if (realIndex == kParentIndex)
+ {
+ if (propID == kpidName)
+ {
+ if (item.cchTextMax > 2)
+ {
+ text[0] = '.';
+ text[1] = '.';
+ text[2] = 0;
+ }
+ }
+ return 0;
+ }
+
if (property.IsRawProp)
{
@@ -118,10 +199,10 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
UInt32 dataSize;
UInt32 propType;
RINOK(_folderRawProps->GetRawProp(realIndex, propID, &data, &dataSize, &propType));
- int limit = item.cchTextMax - 1;
+ unsigned limit = item.cchTextMax - 1;
if (dataSize == 0)
{
- item.pszText[0] = 0;
+ text[0] = 0;
return 0;
}
@@ -131,15 +212,15 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
ConvertNtReparseToString((const Byte *)data, dataSize, s);
if (!s.IsEmpty())
{
- int i;
+ unsigned i;
for (i = 0; i < limit; i++)
{
wchar_t c = s[i];
if (c == 0)
break;
- item.pszText[i] = c;
+ text[i] = c;
}
- item.pszText[i] = 0;
+ text[i] = 0;
return 0;
}
}
@@ -149,45 +230,45 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
ConvertNtSecureToString((const Byte *)data, dataSize, s);
if (!s.IsEmpty())
{
- int i;
+ unsigned i;
for (i = 0; i < limit; i++)
{
- wchar_t c = s[i];
+ wchar_t c = (Byte)s[i];
if (c == 0)
break;
- item.pszText[i] = c;
+ text[i] = c;
}
- item.pszText[i] = 0;
+ text[i] = 0;
return 0;
}
}
{
- const UInt32 kMaxDataSize = 64;
+ const unsigned kMaxDataSize = 64;
if (dataSize > kMaxDataSize)
{
- char temp[64];
+ char temp[32];
MyStringCopy(temp, "data:");
ConvertUInt32ToString(dataSize, temp + 5);
- int i;
+ unsigned i;
for (i = 0; i < limit; i++)
{
- wchar_t c = temp[i];
+ wchar_t c = (Byte)temp[i];
if (c == 0)
break;
- item.pszText[i] = c;
+ text[i] = c;
}
- item.pszText[i] = 0;
+ text[i] = 0;
}
else
{
- if ((int)dataSize > limit)
+ if (dataSize > limit)
dataSize = limit;
- WCHAR *dest = item.pszText;
+ WCHAR *dest = text;
for (UInt32 i = 0; i < dataSize; i++)
{
- Byte b = ((const Byte *)data)[i];
- dest[0] = GetHex((Byte)((b >> 4) & 0xF));
- dest[1] = GetHex((Byte)(b & 0xF));
+ unsigned b = ((const Byte *)data)[i];
+ dest[0] = (WCHAR)GetHex((b >> 4) & 0xF);
+ dest[1] = (WCHAR)GetHex(b & 0xF);
dest += 2;
}
*dest = 0;
@@ -230,11 +311,7 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
*/
if (item.cchTextMax < 32)
- {
- if (item.cchTextMax > 0)
- item.pszText[0] = 0;
return 0;
- }
if (propID == kpidName)
{
@@ -245,35 +322,36 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
_folderGetItemName->GetItemName(realIndex, &name, &nameLen);
if (name)
{
- int dest = 0;
- int limit = item.cchTextMax - 1;
- for (int i = 0; dest < limit;)
+ unsigned dest = 0;
+ unsigned limit = item.cchTextMax - 1;
+ for (unsigned i = 0; dest < limit;)
{
wchar_t c = name[i++];
if (c == 0)
break;
- item.pszText[dest++] = c;
+ text[dest++] = c;
if (c != ' ')
continue;
if (name[i + 1] != ' ')
continue;
- int t = 2;
+ unsigned t = 2;
for (; name[i + t] == ' '; t++);
if (t >= 4 && dest + 4 <= limit)
{
- item.pszText[dest++] = '.';
- item.pszText[dest++] = '.';
- item.pszText[dest++] = '.';
- item.pszText[dest++] = ' ';
+ text[dest++] = '.';
+ text[dest++] = '.';
+ text[dest++] = '.';
+ text[dest++] = ' ';
i += t;
}
}
- item.pszText[dest] = 0;
+ text[dest] = 0;
return 0;
}
}
}
+
if (propID == kpidPrefix)
{
if (_folderGetItemName)
@@ -283,73 +361,65 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
_folderGetItemName->GetItemPrefix(realIndex, &name, &nameLen);
if (name)
{
- int dest = 0;
- int limit = item.cchTextMax - 1;
- for (int i = 0; dest < limit;)
+ unsigned dest = 0;
+ unsigned limit = item.cchTextMax - 1;
+ for (unsigned i = 0; dest < limit;)
{
wchar_t c = name[i++];
if (c == 0)
break;
- item.pszText[dest++] = c;
+ text[dest++] = c;
}
- item.pszText[dest] = 0;
+ text[dest] = 0;
return 0;
}
}
}
+
HRESULT res = _folder->GetProperty(realIndex, propID, &prop);
+
if (res != S_OK)
{
- MyStringCopy(item.pszText, L"Error: ");
+ MyStringCopy(text, L"Error: ");
// s = UString(L"Error: ") + HResultToMessage(res);
}
- else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && (
- propID == kpidSize ||
- propID == kpidPackSize ||
- propID == kpidNumSubDirs ||
- propID == kpidNumSubFiles ||
- propID == kpidPosition ||
- propID == kpidNumBlocks ||
- propID == kpidClusterSize ||
- propID == kpidTotalSize ||
- propID == kpidFreeSpace ||
- propID == kpidUnpackSize
- ))
+ else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID))
{
UInt64 v = 0;
ConvertPropVariantToUInt64(prop, v);
- ConvertSizeToString(v, item.pszText);
+ ConvertSizeToString(v, text);
}
else if (prop.vt == VT_BSTR)
{
- int limit = item.cchTextMax - 1;
+ unsigned limit = item.cchTextMax - 1;
const wchar_t *src = prop.bstrVal;
- int i;
+ unsigned i;
for (i = 0; i < limit; i++)
{
wchar_t c = src[i];
if (c == 0) break;
if (c == 0xA) c = ' ';
if (c == 0xD) c = ' ';
- item.pszText[i] = c;
+ text[i] = c;
}
- item.pszText[i] = 0;
+ text[i] = 0;
}
else
{
char temp[64];
ConvertPropertyToShortString(temp, prop, propID, false);
- int i;
- int limit = item.cchTextMax - 1;
+ unsigned i;
+ unsigned limit = item.cchTextMax - 1;
for (i = 0; i < limit; i++)
{
- wchar_t c = temp[i];
+ wchar_t c = (Byte)temp[i];
if (c == 0)
break;
- item.pszText[i] = c;
+ text[i] = c;
}
- item.pszText[i] = 0;
+ text[i] = 0;
}
+
return 0;
}
@@ -606,7 +676,7 @@ void CPanel::Refresh_StatusBar()
if (indices.Size() > 0)
{
- // for (int ttt = 0; ttt < 1000; ttt++) {
+ // for (unsigned ttt = 0; ttt < 1000; ttt++) {
UInt64 totalSize = 0;
FOR_VECTOR (i, indices)
totalSize += GetItemSize(indices[i]);
@@ -632,10 +702,10 @@ void CPanel::Refresh_StatusBar()
char dateString2[32];
dateString2[0] = 0;
ConvertPropertyToShortString(dateString2, prop, kpidMTime, false);
- for (int i = 0;; i++)
+ for (unsigned i = 0;; i++)
{
char c = dateString2[i];
- dateString[i] = c;
+ dateString[i] = (Byte)c;
if (c == 0)
break;
}
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp
index d7108204..5a527cb4 100644
--- a/CPP/7zip/UI/FileManager/PanelMenu.cpp
+++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp
@@ -49,11 +49,12 @@ void CPanel::InvokeSystemCommand(const char *command)
contextMenu->InvokeCommand(&ci);
}
-static const wchar_t *kSeparator = L"----------------------------\n";
-static const wchar_t *kSeparatorSmall = L"----\n";
-static const wchar_t *kPropValueSeparator = L": ";
+static const char *kSeparator = "----------------------------\n";
+static const char *kSeparatorSmall = "----\n";
+static const char *kPropValueSeparator = ": ";
-extern UString ConvertSizeToString(UInt64 value);
+extern UString ConvertSizeToString(UInt64 value) throw();
+bool IsSizeProp(UINT propID) throw();
UString GetOpenArcErrorMessage(UInt32 errorFlags);
@@ -74,20 +75,7 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR,
val = GetOpenArcErrorMessage(flags);
}
if (val.IsEmpty())
- if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && (
- propID == kpidSize ||
- propID == kpidPackSize ||
- propID == kpidNumSubDirs ||
- propID == kpidNumSubFiles ||
- propID == kpidNumBlocks ||
- propID == kpidClusterSize ||
- propID == kpidTotalSize ||
- propID == kpidFreeSpace ||
- propID == kpidPhySize ||
- propID == kpidHeadersSize ||
- propID == kpidFreeSpace ||
- propID == kpidUnpackSize
- ))
+ if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID))
{
UInt64 v = 0;
ConvertPropVariantToUInt64(prop, v);
@@ -99,13 +87,13 @@ static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR,
if (!val.IsEmpty())
{
s += GetNameOfProperty(propID, nameBSTR);
- s += kPropValueSeparator;
+ s.AddAscii(kPropValueSeparator);
/*
if (propID == kpidComment)
- s += L'\n';
+ s.Add_LF();
*/
s += val;
- s += L'\n';
+ s.Add_LF();
}
}
}
@@ -210,21 +198,21 @@ void CPanel::Properties()
}
}
message += GetNameOfProperty(propID, name);
- message += kPropValueSeparator;
- message += GetUnicodeString(s);
- message += L'\n';
+ message.AddAscii(kPropValueSeparator);
+ message.AddAscii(s);
+ message.Add_LF();
}
}
}
- message += kSeparator;
+ message.AddAscii(kSeparator);
}
/*
- message += LangString(IDS_PROP_FILE_TYPE, 0x02000214);
+ AddLangString(message, IDS_PROP_FILE_TYPE);
message += kPropValueSeparator;
message += GetFolderTypeID();
- message += L"\n";
+ message.Add_LF();
*/
{
@@ -277,7 +265,7 @@ void CPanel::Properties()
{
const int kNumSpecProps = ARRAY_SIZE(kSpecProps);
- message += kSeparator;
+ message.AddAscii(kSeparator);
for (Int32 i = -(int)kNumSpecProps; i < (Int32)numProps; i++)
{
@@ -302,7 +290,7 @@ void CPanel::Properties()
UInt32 numProps;
if (getProps->GetArcNumProps2(level, &numProps) == S_OK)
{
- message += kSeparatorSmall;
+ message.AddAscii(kSeparatorSmall);
for (Int32 i = 0; i < (Int32)numProps; i++)
{
CMyComBSTR name;
@@ -414,9 +402,7 @@ HRESULT CPanel::CreateShellContextMenu(
FOR_VECTOR (i, operatedIndices)
{
LPITEMIDLIST pidl;
- UString fileName = GetItemRelPath(operatedIndices[i]);
- if (IsFSDrivesFolder())
- fileName += WCHAR_PATH_SEPARATOR;
+ UString fileName = GetItemRelPath2(operatedIndices[i]);
RINOK(parentFolder->ParseDisplayName(GetParent(), 0,
(wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0));
pidls.AddInReserved(pidl);
@@ -574,11 +560,11 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec,
if (contextMenu.QueryInterface(IID_IInitContextMenu, &initContextMenu) != S_OK)
return;
*/
- UString currentFolderUnicode = _currentFolderPrefix;
+ UString currentFolderUnicode = GetFsPath();
UStringVector names;
unsigned i;
for (i = 0; i < operatedIndices.Size(); i++)
- names.Add(currentFolderUnicode + GetItemRelPath(operatedIndices[i]));
+ names.Add(currentFolderUnicode + GetItemRelPath2(operatedIndices[i]));
CRecordVector<const wchar_t *> namePointers;
for (i = 0; i < operatedIndices.Size(); i++)
namePointers.Add(names[i]);
@@ -598,6 +584,74 @@ void CPanel::CreateSevenZipMenu(HMENU menuSpec,
}
}
+static bool IsReadOnlyFolder(IFolderFolder *folder)
+{
+ if (!folder)
+ return false;
+
+ bool res = false;
+ {
+ NCOM::CPropVariant prop;
+ if (folder->GetFolderProperty(kpidReadOnly, &prop) == S_OK)
+ if (prop.vt == VT_BOOL)
+ res = VARIANT_BOOLToBool(prop.boolVal);
+ }
+ return res;
+}
+
+bool CPanel::IsThereReadOnlyFolder() const
+{
+ if (!_folderOperations)
+ return true;
+ if (IsReadOnlyFolder(_folder))
+ return true;
+ FOR_VECTOR (i, _parentFolders)
+ {
+ if (IsReadOnlyFolder(_parentFolders[i].ParentFolder))
+ return true;
+ }
+ return false;
+}
+
+bool CPanel::CheckBeforeUpdate(UINT resourceID)
+{
+ if (!_folderOperations)
+ {
+ MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
+ // resourceID = resourceID;
+ // MessageBoxErrorForUpdate(E_NOINTERFACE, resourceID);
+ return false;
+ }
+
+ for (int i = (int)_parentFolders.Size(); i >= 0; i--)
+ {
+ IFolderFolder *folder;
+ if (i == (int)_parentFolders.Size())
+ folder = _folder;
+ else
+ folder = _parentFolders[i].ParentFolder;
+
+ if (!IsReadOnlyFolder(folder))
+ continue;
+
+ UString s;
+ AddLangString(s, resourceID);
+ s.Add_LF();
+ AddLangString(s, IDS_OPERATION_IS_NOT_SUPPORTED);
+ s.Add_LF();
+ if (i == 0)
+ s += GetFolderPath(folder);
+ else
+ s += _parentFolders[i - 1].VirtualPath;
+ s.Add_LF();
+ AddLangString(s, IDS_PROP_READ_ONLY);
+ MessageBoxMyError(s);
+ return false;
+ }
+
+ return true;
+}
+
void CPanel::CreateFileMenu(HMENU menuSpec,
CMyComPtr<IContextMenu> &sevenZipContextMenu,
CMyComPtr<IContextMenu> &systemContextMenu,
@@ -631,8 +685,38 @@ void CPanel::CreateFileMenu(HMENU menuSpec,
if (IsItem_Folder(operatedIndices[i]))
break;
bool allAreFiles = (i == operatedIndices.Size());
- LoadFileMenu(menu, menu.GetItemCount(), programMenu,
- IsFSFolder(), operatedIndices.Size(), allAreFiles);
+
+ CFileMenu fm;
+
+ fm.readOnly = IsThereReadOnlyFolder();
+ fm.isFsFolder = Is_IO_FS_Folder();
+ fm.programMenu = programMenu;
+ fm.allAreFiles = allAreFiles;
+ fm.numItems = operatedIndices.Size();
+
+ fm.isAltStreamsSupported = false;
+
+ if (_folderAltStreams)
+ {
+ if (operatedIndices.Size() <= 1)
+ {
+ Int32 realIndex = -1;
+ if (operatedIndices.Size() == 1)
+ realIndex = operatedIndices[0];
+ Int32 val = 0;
+ if (_folderAltStreams->AreAltStreamsSupported(realIndex, &val) == S_OK)
+ fm.isAltStreamsSupported = IntToBool(val);
+ }
+ }
+ else
+ {
+ if (fm.numItems == 0)
+ fm.isAltStreamsSupported = IsFSFolder();
+ else
+ fm.isAltStreamsSupported = IsFolder_with_FsItems();
+ }
+
+ fm.Load(menu, menu.GetItemCount());
}
bool CPanel::InvokePluginCommand(int id)
@@ -654,26 +738,31 @@ bool CPanel::InvokePluginCommand(int id,
else
offset = id - kSevenZipStartMenuID;
- #ifndef use_CMINVOKECOMMANDINFOEXR
- CMINVOKECOMMANDINFO
+ #ifdef use_CMINVOKECOMMANDINFOEX
+ CMINVOKECOMMANDINFOEX
#else
- CMINVOKECOMMANDINFOEX
+ CMINVOKECOMMANDINFO
#endif
- commandInfo;
+ commandInfo;
+
memset(&commandInfo, 0, sizeof(commandInfo));
commandInfo.cbSize = sizeof(commandInfo);
+
commandInfo.fMask = 0
- #ifdef use_CMINVOKECOMMANDINFOEXR
- | CMIC_MASK_UNICODE
+ #ifdef use_CMINVOKECOMMANDINFOEX
+ | CMIC_MASK_UNICODE
#endif
- ;
+ ;
+
commandInfo.hwnd = GetParent();
commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset));
commandInfo.lpParameters = NULL;
CSysString currentFolderSys = GetSystemString(_currentFolderPrefix);
commandInfo.lpDirectory = (LPCSTR)(LPCTSTR)(currentFolderSys);
commandInfo.nShow = SW_SHOW;
- #ifdef use_CMINVOKECOMMANDINFOEXR
+
+ #ifdef use_CMINVOKECOMMANDINFOEX
+
commandInfo.lpParametersW = NULL;
commandInfo.lpTitle = "";
commandInfo.lpVerbW = (LPCWSTR)(MAKEINTRESOURCEW(offset));
@@ -684,7 +773,9 @@ bool CPanel::InvokePluginCommand(int id,
// commandInfo.ptInvoke.y = yPos;
commandInfo.ptInvoke.x = 0;
commandInfo.ptInvoke.y = 0;
+
#endif
+
HRESULT result;
if (isSystemMenu)
result = systemContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp
index 28c945e5..62a08e13 100644
--- a/CPP/7zip/UI/FileManager/PanelOperations.cpp
+++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp
@@ -85,16 +85,15 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr
ProgressDialog.Sync.FinalMessage.ErrorMessage.Title = titleError;
Result = S_OK;
- bool usePassword = false;
- UString password;
+ UpdateCallbackSpec->Init();
+
if (panel._parentFolders.Size() > 0)
{
const CFolderLink &fl = panel._parentFolders.Back();
- usePassword = fl.UsePassword;
- password = fl.Password;
+ UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
+ UpdateCallbackSpec->Password = fl.Password;
}
- UpdateCallbackSpec->Init(usePassword, password);
ProgressDialog.MainWindow = panel._mainWindow; // panel.GetParent()
ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE);
@@ -108,6 +107,7 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr
typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp);
#endif
+/*
void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID)
{
if (errorCode == E_NOINTERFACE)
@@ -115,6 +115,7 @@ void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID)
else
MessageBoxError(errorCode, LangString(resourceID));
}
+*/
void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
{
@@ -137,8 +138,8 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
CDynamicBuffer<CHAR> buffer;
FOR_VECTOR (i, indices)
{
- const AString path = GetSystemString(GetFsPath() + GetItemRelPath(indices[i]));
- memcpy(buffer.GetCurPtrAndGrow(path.Len() + 1), (const CHAR *)path, (path.Len() + 1) * sizeof(CHAR));
+ const AString path = GetSystemString(GetItemFullPath(indices[i]));
+ buffer.AddData(path, path.Len() + 1);
}
*buffer.GetCurPtrAndGrow(1) = 0;
SHFILEOPSTRUCTA fo;
@@ -163,13 +164,14 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
{
CDynamicBuffer<WCHAR> buffer;
unsigned maxLen = 0;
+ const UString prefix = GetFsPath();
FOR_VECTOR (i, indices)
{
// L"\\\\?\\") doesn't work here.
- const UString path = GetFsPath() + GetItemRelPath(indices[i]);
+ const UString path = prefix + GetItemRelPath2(indices[i]);
if (path.Len() > maxLen)
maxLen = path.Len();
- memcpy(buffer.GetCurPtrAndGrow(path.Len() + 1), (const WCHAR *)path, (path.Len() + 1) * sizeof(WCHAR));
+ buffer.AddData(path, path.Len() + 1);
}
*buffer.GetCurPtrAndGrow(1) = 0;
if (maxLen >= MAX_PATH)
@@ -220,19 +222,15 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
// DeleteItemsInternal
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
- {
- MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_DELETING);
+ if (!CheckBeforeUpdate(IDS_ERROR_DELETING))
return;
- }
UInt32 titleID, messageID;
UString messageParam;
if (indices.Size() == 1)
{
int index = indices[0];
- messageParam = GetItemRelPath(index);
+ messageParam = GetItemRelPath2(index);
if (IsItem_Folder(index))
{
titleID = IDS_CONFIRM_FOLDER_DELETE;
@@ -256,7 +254,7 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
CDisableNotify disableNotify(*this);
{
CThreadFolderOperations op(FOLDER_TYPE_DELETE);
- op.FolderOperations = folderOperations;
+ op.FolderOperations = _folderOperations;
op.Indices = indices;
op.DoOperation(*this,
LangString(IDS_DELETING),
@@ -271,25 +269,14 @@ BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh)
int realIndex = GetRealIndex(lpnmh->item);
if (realIndex == kParentIndex)
return TRUE;
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
+ if (IsThereReadOnlyFolder())
return TRUE;
return FALSE;
}
-static UString GetLastPart(const UString name)
-{
- int slashPos = name.ReverseFind(L'/');
- #ifdef _WIN32
- int slash1Pos = name.ReverseFind(L'\\');
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
- return name.Ptr(slashPos + 1);
-}
-
bool IsCorrectFsName(const UString &name)
{
- const UString lastPart = GetLastPart(name);
+ const UString lastPart = name.Ptr(name.ReverseFind_PathSepar() + 1);
return
lastPart != L"." &&
lastPart != L"..";
@@ -299,7 +286,7 @@ bool CorrectFsPath(const UString &relBase, const UString &path, UString &result)
bool CPanel::CorrectFsPath(const UString &path2, UString &result)
{
- return ::CorrectFsPath(_currentFolderPrefix, path2, result);
+ return ::CorrectFsPath(GetFsPath(), path2, result);
}
BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
@@ -307,12 +294,10 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
if (lpnmh->item.pszText == NULL)
return FALSE;
CDisableTimerProcessing disableTimerProcessing2(*this);
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
- {
- MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_ERROR_RENAMING);
+
+ if (!CheckBeforeUpdate(IDS_ERROR_RENAMING))
return FALSE;
- }
+
UString newName = lpnmh->item.pszText;
if (!IsCorrectFsName(newName))
{
@@ -342,7 +327,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
CDisableNotify disableNotify(*this);
{
CThreadFolderOperations op(FOLDER_TYPE_RENAME);
- op.FolderOperations = folderOperations;
+ op.FolderOperations = _folderOperations;
op.Index = realIndex;
op.Name = newName;
/* HRESULTres = */ op.DoOperation(*this,
@@ -377,12 +362,9 @@ bool Dlg_CreateFolder(HWND wnd, UString &destName);
void CPanel::CreateFolder()
{
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
- {
- MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FOLDER_ERROR);
+ if (!CheckBeforeUpdate(IDS_CREATE_FOLDER_ERROR))
return;
- }
+
CDisableTimerProcessing disableTimerProcessing2(*this);
CSelectedState state;
SaveSelectedState(state);
@@ -412,7 +394,7 @@ void CPanel::CreateFolder()
CDisableNotify disableNotify(*this);
{
CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER);
- op.FolderOperations = folderOperations;
+ op.FolderOperations = _folderOperations;
op.Name = newName;
res = op.DoOperation(*this,
LangString(IDS_CREATE_FOLDER),
@@ -439,12 +421,9 @@ void CPanel::CreateFolder()
void CPanel::CreateFile()
{
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
- {
- MessageBoxErrorForUpdate(E_NOINTERFACE, IDS_CREATE_FILE_ERROR);
+ if (!CheckBeforeUpdate(IDS_CREATE_FILE_ERROR))
return;
- }
+
CDisableTimerProcessing disableTimerProcessing2(*this);
CSelectedState state;
SaveSelectedState(state);
@@ -471,10 +450,11 @@ void CPanel::CreateFile()
newName = correctName;
}
- HRESULT result = folderOperations->CreateFile(newName, 0);
+ HRESULT result = _folderOperations->CreateFile(newName, 0);
if (result != S_OK)
{
- MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR);
+ MessageBoxError(result, LangString(IDS_CREATE_FILE_ERROR));
+ // MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR);
return;
}
int pos = newName.Find(WCHAR_PATH_SEPARATOR);
@@ -489,6 +469,8 @@ void CPanel::CreateFile()
void CPanel::RenameFile()
{
+ if (!CheckBeforeUpdate(IDS_ERROR_RENAMING))
+ return;
int index = _listView.GetFocusedItem();
if (index >= 0)
_listView.EditLabel(index);
@@ -496,6 +478,8 @@ void CPanel::RenameFile()
void CPanel::ChangeComment()
{
+ if (!CheckBeforeUpdate(IDS_COMMENT))
+ return;
CDisableTimerProcessing disableTimerProcessing2(*this);
int index = _listView.GetFocusedItem();
if (index < 0)
@@ -505,13 +489,6 @@ void CPanel::ChangeComment()
return;
CSelectedState state;
SaveSelectedState(state);
- CMyComPtr<IFolderOperations> folderOperations;
- if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
- {
- MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
- return;
- }
-
UString comment;
{
NCOM::CPropVariant propVariant;
@@ -522,17 +499,19 @@ void CPanel::ChangeComment()
else if (propVariant.vt != VT_EMPTY)
return;
}
- UString name = GetItemRelPath(realIndex);
+ UString name = GetItemRelPath2(realIndex);
CComboDialog dlg;
- dlg.Title = name + L' ' + LangString(IDS_COMMENT);
+ dlg.Title = name;
+ dlg.Title += L" : ";
+ AddLangString(dlg.Title, IDS_COMMENT);
dlg.Value = comment;
LangString(IDS_COMMENT2, dlg.Static);
if (dlg.Create(GetParent()) != IDOK)
return;
- NCOM::CPropVariant propVariant = (const wchar_t *)dlg.Value;
+ NCOM::CPropVariant propVariant = dlg.Value.Ptr();
CDisableNotify disableNotify(*this);
- HRESULT result = folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL);
+ HRESULT result = _folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL);
if (result != S_OK)
{
if (result == E_NOINTERFACE)
diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp
index a40997c2..7b53eb00 100644
--- a/CPP/7zip/UI/FileManager/PanelSelect.cpp
+++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp
@@ -22,7 +22,9 @@ void CPanel::OnShiftSelectMessage()
return;
int startItem = MyMin(focusedItem, _prevFocusedItem);
int finishItem = MyMax(focusedItem, _prevFocusedItem);
- for (int i = 0; i < _listView.GetItemCount(); i++)
+
+ int numItems = _listView.GetItemCount();
+ for (int i = 0; i < numItems; i++)
{
int realIndex = GetRealItemIndex(i);
if (realIndex == kParentIndex)
@@ -34,6 +36,7 @@ void CPanel::OnShiftSelectMessage()
_listView.RedrawItem(i);
}
}
+
_prevFocusedItem = focusedItem;
}
@@ -45,6 +48,7 @@ void CPanel::OnArrowWithShift()
if (focusedItem < 0)
return;
int realIndex = GetRealItemIndex(focusedItem);
+
if (_selectionIsDefined)
{
if (realIndex != kParentIndex)
@@ -64,6 +68,7 @@ void CPanel::OnArrowWithShift()
_selectedStatusVector[realIndex] = _selectMark;
}
}
+
_prevFocusedItem = focusedItem;
PostMessage(kShiftSelectMessage);
_listView.RedrawItem(focusedItem);
@@ -165,13 +170,6 @@ void CPanel::SelectByType(bool selectMode)
UString name = GetItemName(realIndex);
bool isItemFolder = IsItem_Folder(realIndex);
- /*
- UInt32 numItems;
- _folder->GetNumberOfItems(&numItems);
- if ((UInt32)_selectedStatusVector.Size() != numItems)
- throw 11111;
- */
-
if (isItemFolder)
{
FOR_VECTOR (i, _selectedStatusVector)
@@ -180,11 +178,11 @@ void CPanel::SelectByType(bool selectMode)
}
else
{
- int pos = name.ReverseFind(L'.');
+ int pos = name.ReverseFind_Dot();
if (pos < 0)
{
FOR_VECTOR (i, _selectedStatusVector)
- if (IsItem_Folder(i) == isItemFolder && GetItemName(i).ReverseFind(L'.') < 0)
+ if (IsItem_Folder(i) == isItemFolder && GetItemName(i).ReverseFind_Dot() < 0)
_selectedStatusVector[i] = selectMode;
}
else
@@ -196,6 +194,7 @@ void CPanel::SelectByType(bool selectMode)
_selectedStatusVector[i] = selectMode;
}
}
+
UpdateSelection();
}
@@ -253,10 +252,11 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
{
if (itemActivate->hdr.hwndFrom != HWND(_listView))
return;
- // It will be work only for Version 4.71 (IE 4);
+ // It will work only for Version 4.71 (IE 4);
int indexInList = itemActivate->iItem;
if (indexInList < 0)
return;
+
#ifndef UNDER_CE
if ((itemActivate->uKeyFlags & LVKF_SHIFT) != 0)
{
@@ -264,9 +264,11 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
int focusedIndex = _startGroupSelect;
if (focusedIndex < 0)
return;
- unsigned startItem = MyMin((unsigned)focusedIndex, (unsigned)indexInList);
- unsigned finishItem = MyMax((unsigned)focusedIndex, (unsigned)indexInList);
- FOR_VECTOR (i, _selectedStatusVector)
+ int startItem = MyMin(focusedIndex, indexInList);
+ int finishItem = MyMax(focusedIndex, indexInList);
+
+ int numItems = _listView.GetItemCount();
+ for (int i = 0; i < numItems; i++)
{
int realIndex = GetRealItemIndex(i);
if (realIndex == kParentIndex)
@@ -283,6 +285,7 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
#endif
{
_startGroupSelect = indexInList;
+
#ifndef UNDER_CE
if ((itemActivate->uKeyFlags & LVKF_CONTROL) != 0)
{
@@ -295,5 +298,6 @@ void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
}
#endif
}
+
return;
}
diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp
index fe5d3ffd..82d6756e 100644
--- a/CPP/7zip/UI/FileManager/PanelSort.cpp
+++ b/CPP/7zip/UI/FileManager/PanelSort.cpp
@@ -76,7 +76,7 @@ static int CompareFileNames_Le16(const Byte *s1, unsigned size1, const Byte *s2,
static inline const wchar_t *GetExtensionPtr(const UString &name)
{
- int dotPos = name.ReverseFind(L'.');
+ int dotPos = name.ReverseFind_Dot();
return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
}
diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
index ce15fcc5..a8c0d352 100644
--- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
+++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
@@ -138,7 +138,7 @@ HRESULT CThreadSplit::ProcessVirt()
if (!outFile.Create(name, false))
{
HRESULT res = GetLastError();
- SetErrorPath1(name);
+ AddErrorPath(name);
return res;
}
}
@@ -165,7 +165,7 @@ void CApp::Split()
{
int srcPanelIndex = GetFocusedPanelIndex();
CPanel &srcPanel = Panels[srcPanelIndex];
- if (!srcPanel.IsFSFolder())
+ if (!srcPanel.Is_IO_FS_Folder())
{
srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED);
return;
@@ -187,13 +187,13 @@ void CApp::Split()
}
const UString itemName = srcPanel.GetItemName(index);
- UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
+ UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
UString path = srcPath;
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
- path = destPanel._currentFolderPrefix;
+ path = destPanel.GetFsPath();
CSplitDialog splitDialog;
splitDialog.FilePath = srcPanel.GetItemRelPath(index);
splitDialog.Path = path;
@@ -243,12 +243,13 @@ void CApp::Split()
progressDialog.MainWindow = _window;
progressDialog.MainTitle = progressWindowTitle;
- progressDialog.MainAddTitle = title + L' ';
+ progressDialog.MainAddTitle = title;
+ progressDialog.MainAddTitle.Add_Space();
progressDialog.Sync.Set_TitleFileName(itemName);
spliter.FilePath = us2fs(srcPath + itemName);
- spliter.VolBasePath = us2fs(path + itemName);
+ spliter.VolBasePath = us2fs(path + srcPanel.GetItemName_for_Copy(index));
spliter.VolumeSizes = splitDialog.VolumeSizes;
// if (splitDialog.VolumeSizes.Size() == 0) return;
@@ -285,7 +286,7 @@ HRESULT CThreadCombine::ProcessVirt()
if (!outFile.Create(OutputPath, false))
{
HRESULT res = GetLastError();
- SetErrorPath1(OutputPath);
+ AddErrorPath(OutputPath);
return res;
}
@@ -304,7 +305,7 @@ HRESULT CThreadCombine::ProcessVirt()
if (!inFile.Open(nextName))
{
HRESULT res = GetLastError();
- SetErrorPath1(nextName);
+ AddErrorPath(nextName);
return res;
}
sync.Set_FilePath(fs2us(nextName));
@@ -314,7 +315,7 @@ HRESULT CThreadCombine::ProcessVirt()
if (!inFile.Read(buffer, kBufSize, processedSize))
{
HRESULT res = GetLastError();
- SetErrorPath1(nextName);
+ AddErrorPath(nextName);
return res;
}
if (processedSize == 0)
@@ -323,7 +324,7 @@ HRESULT CThreadCombine::ProcessVirt()
if (!outFile.Write(buffer, needSize, processedSize))
{
HRESULT res = GetLastError();
- SetErrorPath1(OutputPath);
+ AddErrorPath(OutputPath);
return res;
}
if (needSize != processedSize)
@@ -364,13 +365,13 @@ void CApp::Combine()
}
const UString itemName = srcPanel.GetItemName(index);
- UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
+ UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
UString path = srcPath;
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
- path = destPanel._currentFolderPrefix;
+ path = destPanel.GetFsPath();
CVolSeqName volSeqName;
if (!volSeqName.ParseName(itemName))
@@ -408,7 +409,7 @@ void CApp::Combine()
UString info;
AddValuePair2(info, IDS_PROP_FILES, combiner.Names.Size(), combiner.TotalSize);
- info += L"\n";
+ info.Add_LF();
info += srcPath;
unsigned i;
@@ -425,7 +426,7 @@ void CApp::Combine()
CCopyDialog copyDialog;
copyDialog.Value = path;
LangString(IDS_COMBINE, copyDialog.Title);
- copyDialog.Title += ' ';
+ copyDialog.Title.Add_Space();
copyDialog.Title += srcPanel.GetItemRelPath(index);
LangString(IDS_COMBINE_TO, copyDialog.Static);
copyDialog.Info = info;
@@ -468,7 +469,8 @@ void CApp::Combine()
progressDialog.MainWindow = _window;
progressDialog.MainTitle = progressWindowTitle;
- progressDialog.MainAddTitle = title + L' ';
+ progressDialog.MainAddTitle = title;
+ progressDialog.MainAddTitle.Add_Space();
combiner.InputDirPrefix = us2fs(srcPath);
diff --git a/CPP/7zip/UI/FileManager/PluginInterface.h b/CPP/7zip/UI/FileManager/PluginInterface.h
index 3ce5fa8e..37654a03 100644
--- a/CPP/7zip/UI/FileManager/PluginInterface.h
+++ b/CPP/7zip/UI/FileManager/PluginInterface.h
@@ -11,7 +11,7 @@
PLUGIN_INTERFACE(IInitContextMenu, 0x00)
{
- STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t **names, UInt32 numFiles) PURE;
+ STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t * const *names, UInt32 numFiles) PURE;
};
PLUGIN_INTERFACE(IPluginOptionsCallback, 0x01)
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
index c9ca3942..231d0ace 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -28,7 +28,7 @@ static const UINT kTimerElapse =
#ifdef UNDER_CE
500
#else
- 100
+ 200
#endif
;
@@ -104,13 +104,13 @@ HRESULT CProgressSync::CheckStop()
}
}
-HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir)
+HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir)
{
{
CRITICAL_LOCK
_totalFiles = numFiles;
_totalBytes = totalSize;
- _filePath = fileName;
+ _filePath = fs2us(fileName);
_isDir = isDir;
// _completedBytes = 0;
CHECK_STOP
@@ -118,10 +118,14 @@ HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const USt
return CheckStop();
}
-void CProgressSync::Set_NumFilesTotal(UInt64 val)
+HRESULT CProgressSync::Set_NumFilesTotal(UInt64 val)
{
- CRITICAL_LOCK
- _totalFiles = val;
+ {
+ CRITICAL_LOCK
+ _totalFiles = val;
+ CHECK_STOP
+ }
+ return CheckStop();
}
void CProgressSync::Set_NumBytesTotal(UInt64 val)
@@ -171,16 +175,34 @@ void CProgressSync::Set_TitleFileName(const UString &fileName)
CRITICAL_LOCK
_titleFileName = fileName;
}
+
void CProgressSync::Set_Status(const UString &s)
{
CRITICAL_LOCK
_status = s;
}
-void CProgressSync::Set_FilePath(const UString &path, bool isDir)
+HRESULT CProgressSync::Set_Status2(const UString &s, const wchar_t *path, bool isDir)
+{
+ {
+ CRITICAL_LOCK
+ _status = s;
+ if (path)
+ _filePath = path;
+ else
+ _filePath.Empty();
+ _isDir = isDir;
+ }
+ return CheckStop();
+}
+
+void CProgressSync::Set_FilePath(const wchar_t *path, bool isDir)
{
CRITICAL_LOCK
- _filePath = path;
+ if (path)
+ _filePath = path;
+ else
+ _filePath.Empty();
_isDir = isDir;
}
@@ -199,7 +221,7 @@ void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t
if (message && *message != 0 )
{
if (!s.IsEmpty())
- s += L'\n';
+ s.Add_LF();
s += message;
if (!s.IsEmpty() && s.Back() == L'\n')
s.DeleteBack();
@@ -633,7 +655,6 @@ static unsigned GetPower64(UInt64 val)
if (high == 0)
return GetPower32((UInt32)val);
return GetPower32(high) + 32;
-
}
static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider)
@@ -867,7 +888,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
s1 = _filePath;
else
{
- int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);
+ int slashPos = _filePath.ReverseFind_PathSepar();
if (slashPos >= 0)
{
s1.SetFrom(_filePath, slashPos + 1);
@@ -878,7 +899,7 @@ void CProgressDialog::UpdateStatInfo(bool showAll)
}
ReduceString(s1, _numReduceSymbols);
ReduceString(s2, _numReduceSymbols);
- s1 += L'\n';
+ s1.Add_LF();
s1 += s2;
SetItemText(IDT_PROGRESS_FILE_NAME, s1);
}
@@ -1025,22 +1046,22 @@ void CProgressDialog::SetTitleText()
if (Sync.Get_Paused())
{
s += _paused_String;
- s += L' ';
+ s.Add_Space();
}
if (IS_DEFINED_VAL(_prevPercentValue))
{
- wchar_t temp[32];
+ char temp[32];
ConvertUInt64ToString(_prevPercentValue, temp);
- s += temp;
+ s.AddAscii(temp);
s += L'%';
}
if (!_foreground)
{
- s += L' ';
+ s.Add_Space();
s += _backgrounded_String;
}
- s += L' ';
+ s.Add_Space();
#ifndef _SFX
{
unsigned len = s.Len();
@@ -1055,7 +1076,7 @@ void CProgressDialog::SetTitleText()
{
UString fileName = _titleFileName;
ReduceString(fileName, kTitleFileNameSizeLimit);
- s += L' ';
+ s.Add_Space();
s += fileName;
}
SetText(s);
@@ -1239,7 +1260,7 @@ static void AddMessageToString(UString &dest, const UString &src)
if (!src.IsEmpty())
{
if (!dest.IsEmpty())
- dest += L'\n';
+ dest.Add_LF();
dest += src;
}
}
@@ -1266,8 +1287,15 @@ void CProgressThreadVirt::Process()
m = HResultToMessage(Result);
}
AddMessageToString(m, FinalMessage.ErrorMessage.Message);
- AddMessageToString(m, fs2us(ErrorPath1));
- AddMessageToString(m, fs2us(ErrorPath2));
+
+ {
+ FOR_VECTOR(i, ErrorPaths)
+ {
+ if (i >= 32)
+ break;
+ AddMessageToString(m, fs2us(ErrorPaths[i]));
+ }
+ }
CProgressSync &sync = ProgressDialog.Sync;
NSynchronization::CCriticalSectionLock lock(sync._cs);
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h
index ea1559a7..03f836da 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.h
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h
@@ -80,9 +80,9 @@ public:
}
HRESULT CheckStop();
- HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const UString &fileName, bool isDir = false);
+ HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false);
- void Set_NumFilesTotal(UInt64 val);
+ HRESULT Set_NumFilesTotal(UInt64 val);
void Set_NumBytesTotal(UInt64 val);
void Set_NumFilesCur(UInt64 val);
HRESULT Set_NumBytesCur(const UInt64 *val);
@@ -91,7 +91,8 @@ public:
void Set_TitleFileName(const UString &fileName);
void Set_Status(const UString &s);
- void Set_FilePath(const UString &path, bool isDir = false);
+ HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false);
+ void Set_FilePath(const wchar_t *path, bool isDir = false);
void AddError_Message(const wchar_t *message);
void AddError_Message_Name(const wchar_t *message, const wchar_t *name);
@@ -274,9 +275,8 @@ public:
class CProgressThreadVirt
{
- FString ErrorPath1;
- FString ErrorPath2;
protected:
+ FStringVector ErrorPaths;
CProgressFinalMessage FinalMessage;
// error if any of HRESULT, ErrorMessage, ErrorPath
@@ -299,8 +299,7 @@ public:
return 0;
}
- void SetErrorPath1(const FString &path) { ErrorPath1 = path; }
- void SetErrorPath2(const FString &path) { ErrorPath2 = path; }
+ void AddErrorPath(const FString &path) { ErrorPaths.Add(path); }
HRESULT Create(const UString &title, HWND parentWindow = 0);
CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}
diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc
index 43c4584f..8b8c7899 100644
--- a/CPP/7zip/UI/FileManager/PropertyName.rc
+++ b/CPP/7zip/UI/FileManager/PropertyName.rc
@@ -94,4 +94,6 @@ BEGIN
IDS_PROP_HARD_LINK "Hard Link"
IDS_PROP_INODE "iNode"
IDS_PROP_STREAM_ID "Stream ID"
+ IDS_PROP_READ_ONLY "Read-only"
+ IDS_PROP_OUT_NAME "Out Name"
END
diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h
index 199aa6da..3696ed2e 100644
--- a/CPP/7zip/UI/FileManager/PropertyNameRes.h
+++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h
@@ -90,3 +90,5 @@
#define IDS_PROP_HARD_LINK 1090
#define IDS_PROP_INODE 1091
#define IDS_PROP_STREAM_ID 1092
+#define IDS_PROP_READ_ONLY 1093
+#define IDS_PROP_OUT_NAME 1094
diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
index ee944350..93ba40c2 100644
--- a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
+++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
@@ -86,8 +86,7 @@ bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext)
bool CShellExtInfo::IsIt7Zip() const
{
- UString s = GetUnicodeString(k7zipPrefix);
- return MyStringCompareNoCase_N(GetUnicodeString(ProgramKey), s, s.Len()) == 0;
+ return IsString1PrefixedByString2_NoCase(GetUnicodeString(ProgramKey), GetUnicodeString(k7zipPrefix));
}
LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext)
diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp
index 234c51dd..c5b57821 100644
--- a/CPP/7zip/UI/FileManager/RootFolder.cpp
+++ b/CPP/7zip/UI/FileManager/RootFolder.cpp
@@ -10,11 +10,25 @@
#include "../../PropID.h"
+#if defined(_WIN32) && !defined(UNDER_CE)
+#define USE_WIN_PATHS
+#endif
+
+static const unsigned kNumRootFolderItems =
+ #ifdef USE_WIN_PATHS
+ 4
+ #else
+ 1
+ #endif
+ ;
+
+
#include "FSFolder.h"
#include "LangUtils.h"
-#ifndef UNDER_CE
+#ifdef USE_WIN_PATHS
#include "NetFolder.h"
#include "FSDrives.h"
+#include "AltStreamsFolder.h"
#endif
#include "RootFolder.h"
#include "SysIconUtils.h"
@@ -30,10 +44,10 @@ static const PROPID kProps[] =
UString RootFolder_GetName_Computer(int &iconIndex)
{
- #ifdef UNDER_CE
- GetRealIconIndex(FTEXT("\\"), FILE_ATTRIBUTE_DIRECTORY, iconIndex);
- #else
+ #ifdef USE_WIN_PATHS
iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES);
+ #else
+ GetRealIconIndex(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, iconIndex);
#endif
return LangString(IDS_COMPUTER);
}
@@ -53,21 +67,21 @@ UString RootFolder_GetName_Documents(int &iconIndex)
enum
{
ROOT_INDEX_COMPUTER = 0
- #ifndef UNDER_CE
+ #ifdef USE_WIN_PATHS
, ROOT_INDEX_DOCUMENTS
, ROOT_INDEX_NETWORK
, ROOT_INDEX_VOLUMES
#endif
};
-#ifndef UNDER_CE
+#ifdef USE_WIN_PATHS
static const wchar_t *kVolPrefix = L"\\\\.";
#endif
void CRootFolder::Init()
{
_names[ROOT_INDEX_COMPUTER] = RootFolder_GetName_Computer(_iconIndices[ROOT_INDEX_COMPUTER]);
- #ifndef UNDER_CE
+ #ifdef USE_WIN_PATHS
_names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]);
_names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]);
_names[ROOT_INDEX_VOLUMES] = kVolPrefix;
@@ -124,8 +138,7 @@ UString GetMyDocsPath()
us = GetUnicodeString(s2);
}
#endif
- if (us.Len() > 0 && us.Back() != WCHAR_PATH_SEPARATOR)
- us += WCHAR_PATH_SEPARATOR;
+ NFile::NName::NormalizeDirPathPrefix(us);
return us;
}
@@ -133,14 +146,8 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde
{
*resultFolder = NULL;
CMyComPtr<IFolderFolder> subFolder;
- #ifdef UNDER_CE
- if (index == ROOT_INDEX_COMPUTER)
- {
- NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder;
- subFolder = fsFolder;
- fsFolder->InitToRoot();
- }
- #else
+
+ #ifdef USE_WIN_PATHS
if (index == ROOT_INDEX_COMPUTER || index == ROOT_INDEX_VOLUMES)
{
CFSDrives *fsDrivesSpec = new CFSDrives;
@@ -160,12 +167,20 @@ STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolde
{
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
subFolder = fsFolderSpec;
- RINOK(fsFolderSpec->Init(us2fs(s), NULL));
+ RINOK(fsFolderSpec->Init(us2fs(s)));
}
}
+ #else
+ if (index == ROOT_INDEX_COMPUTER)
+ {
+ NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder;
+ subFolder = fsFolder;
+ fsFolder->InitToRoot();
+ }
#endif
else
return E_INVALIDARG;
+
*resultFolder = subFolder.Detach();
return S_OK;
}
@@ -185,6 +200,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
*resultFolder = 0;
UString name2 = name;
name2.Trim();
+
if (name2.IsEmpty())
{
CRootFolder *rootFolderSpec = new CRootFolder;
@@ -193,21 +209,25 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
*resultFolder = rootFolder.Detach();
return S_OK;
}
- for (int i = 0; i < kNumRootFolderItems; i++)
+
+ for (unsigned i = 0; i < kNumRootFolderItems; i++)
if (AreEqualNames(name2, _names[i]))
return BindToFolder((UInt32)i, resultFolder);
- #ifdef UNDER_CE
- if (name2 == L"\\")
- return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
- #else
+
+ #ifdef USE_WIN_PATHS
if (AreEqualNames(name2, L"My Documents") ||
AreEqualNames(name2, L"Documents"))
return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder);
+ #else
+ if (name2 == WSTRING_PATH_SEPARATOR)
+ return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
#endif
+
if (AreEqualNames(name2, L"My Computer") ||
AreEqualNames(name2, L"Computer"))
return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
- if (name2 == UString(WCHAR_PATH_SEPARATOR))
+
+ if (name2 == WSTRING_PATH_SEPARATOR)
{
CMyComPtr<IFolderFolder> subFolder = this;
*resultFolder = subFolder.Detach();
@@ -219,7 +239,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
CMyComPtr<IFolderFolder> subFolder;
- #ifndef UNDER_CE
+ #ifdef USE_WIN_PATHS
if (name2.IsPrefixedBy(kVolPrefix))
{
CFSDrives *folderSpec = new CFSDrives;
@@ -232,16 +252,22 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
subFolder = folderSpec;
folderSpec->Init(false, true);
}
+ else if (name2.Back() == ':')
+ {
+ NAltStreamsFolder::CAltStreamsFolder *folderSpec = new NAltStreamsFolder::CAltStreamsFolder;
+ subFolder = folderSpec;
+ if (folderSpec->Init(us2fs(name2)) != S_OK)
+ return E_INVALIDARG;
+ }
else
#endif
{
- if (name2[name2.Len() - 1] != WCHAR_PATH_SEPARATOR)
- name2 += WCHAR_PATH_SEPARATOR;
+ NFile::NName::NormalizeDirPathPrefix(name2);
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
subFolder = fsFolderSpec;
- if (fsFolderSpec->Init(us2fs(name2), 0) != S_OK)
+ if (fsFolderSpec->Init(us2fs(name2)) != S_OK)
{
- #ifndef UNDER_CE
+ #ifdef USE_WIN_PATHS
if (name2[0] == WCHAR_PATH_SEPARATOR)
{
CNetFolder *netFolderSpec = new CNetFolder;
@@ -253,6 +279,7 @@ STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resu
return E_INVALIDARG;
}
}
+
*resultFolder = subFolder.Detach();
return S_OK;
}
@@ -267,11 +294,11 @@ IMP_IFolderFolder_Props(CRootFolder)
STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
{
- NWindows::NCOM::CPropVariant prop;
- switch(propID)
+ NCOM::CPropVariant prop;
+ switch (propID)
{
- case kpidType: prop = L"RootFolder"; break;
- case kpidPath: prop = L""; break;
+ case kpidType: prop = "RootFolder"; break;
+ case kpidPath: prop = ""; break;
}
prop.Detach(value);
return S_OK;
diff --git a/CPP/7zip/UI/FileManager/RootFolder.h b/CPP/7zip/UI/FileManager/RootFolder.h
index e9ef2d8c..e2537837 100644
--- a/CPP/7zip/UI/FileManager/RootFolder.h
+++ b/CPP/7zip/UI/FileManager/RootFolder.h
@@ -7,21 +7,15 @@
#include "IFolder.h"
-const int kNumRootFolderItems =
- #ifdef UNDER_CE
- 1
- #else
- 4
- #endif
- ;
+const unsigned kNumRootFolderItems_Max = 4;
class CRootFolder:
public IFolderFolder,
public IFolderGetSystemIconIndex,
public CMyUnknownImp
{
- UString _names[kNumRootFolderItems];
- int _iconIndices[kNumRootFolderItems];
+ UString _names[kNumRootFolderItems_Max];
+ int _iconIndices[kNumRootFolderItems_Max];
public:
MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex)
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc
index 3e4a611e..c724fcb7 100644
--- a/CPP/7zip/UI/FileManager/SettingsPage.rc
+++ b/CPP/7zip/UI/FileManager/SettingsPage.rc
@@ -1,7 +1,7 @@
#include "SettingsPageRes.h"
#include "../../GuiCommon.rc"
-#define xc 200
+#define xc 240
#define yc 120
IDD_SETTINGS MY_PAGE
diff --git a/CPP/7zip/UI/FileManager/SplitDialog.cpp b/CPP/7zip/UI/FileManager/SplitDialog.cpp
index d35d76c9..d7d14d7c 100644
--- a/CPP/7zip/UI/FileManager/SplitDialog.cpp
+++ b/CPP/7zip/UI/FileManager/SplitDialog.cpp
@@ -38,7 +38,7 @@ bool CSplitDialog::OnInit()
{
UString title;
GetText(title);
- title += L' ';
+ title.Add_Space();
title += FilePath;
SetText(title);
}
diff --git a/CPP/7zip/UI/FileManager/StringUtils.cpp b/CPP/7zip/UI/FileManager/StringUtils.cpp
index fb38a735..10056549 100644
--- a/CPP/7zip/UI/FileManager/StringUtils.cpp
+++ b/CPP/7zip/UI/FileManager/StringUtils.cpp
@@ -54,14 +54,17 @@ void SplitString(const UString &srcString, UStringVector &destStrings)
destStrings.Add(s);
}
+/*
UString JoinStrings(const UStringVector &srcStrings)
{
+
UString s;
FOR_VECTOR (i, srcStrings)
{
if (i != 0)
- s += L' ';
+ s.Add_Space();
s += srcStrings[i];
}
return s;
}
+*/
diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp
index a40c4e3d..a7f0c3fb 100644
--- a/CPP/7zip/UI/FileManager/SystemPage.cpp
+++ b/CPP/7zip/UI/FileManager/SystemPage.cpp
@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "../../../Common/StringConvert.h"
+#include "../../../Common/Defs.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/ErrorMsg.h"
@@ -16,6 +17,10 @@
using namespace NWindows;
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
static const UInt32 kLangIDs[] =
{
IDT_SYSTEM_ASSOCIATE
@@ -48,8 +53,8 @@ int CSystemPage::AddIcon(const UString &iconPath, int iconIndex)
// we expand path from REG_EXPAND_SZ registry item.
UString path;
DWORD size = MAX_PATH + 10;
- DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuffer((int)size + 1), size);
- path.ReleaseBuffer();
+ DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuf(size + 2), size);
+ path.ReleaseBuf_CalcLen(size);
if (needLen == 0 || needLen >= size)
path = iconPath;
int num = ExtractIconExW(path, iconIndex, NULL, &hicon, 1);
@@ -140,32 +145,49 @@ bool CSystemPage::OnInit()
_listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE), 72);
- CSysString s;
+ UString s;
#if NUM_EXT_GROUPS == 1
- s = TEXT("Program");
+ s.SetFromAscii("Program");
#else
#ifndef UNDER_CE
- DWORD size = 256;
- BOOL res = GetUserName(s.GetBuffer(size), &size);
- s.ReleaseBuffer();
+ const unsigned kSize = 256;
+ BOOL res;
+
+ DWORD size = kSize;
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ AString s2;
+ res = GetUserNameA(s2.GetBuf(size), &size);
+ s2.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize));
+ s = GetUnicodeString(s2);
+ }
+ else
+ #endif
+ {
+ res = GetUserNameW(s.GetBuf(size), &size);
+ s.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize));
+ }
+
if (!res)
#endif
- s = TEXT("Current User");
+ s.SetFromAscii("Current User");
#endif
- LVCOLUMN ci;
+ LV_COLUMNW ci;
ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
- ci.cx = 100;
- ci.pszText = (TCHAR *)(const TCHAR *)s;
- ci.iSubItem = 1;
+ ci.cx = 128;
ci.fmt = LVCFMT_CENTER;
+ ci.pszText = (WCHAR *)(const WCHAR *)s;
+ ci.iSubItem = 1;
_listView.InsertColumn(1, &ci);
#if NUM_EXT_GROUPS > 1
{
+ LangString(IDS_SYSTEM_ALL_USERS, s);
+ ci.pszText = (WCHAR *)(const WCHAR *)s;
ci.iSubItem = 2;
- ci.pszText = (LPTSTR)TEXT("All Users");
_listView.InsertColumn(2, &ci);
}
#endif
diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h
index 0bf6aae7..d38bd1b0 100644
--- a/CPP/7zip/UI/FileManager/SystemPage.h
+++ b/CPP/7zip/UI/FileManager/SystemPage.h
@@ -40,7 +40,7 @@ struct CModifiedExtInfo: public NRegistryAssoc::CShellExtInfo
Other = true;
if (IsIt7Zip())
{
- Other7Zip = !iconPath.IsEqualToNoCase(IconPath);
+ Other7Zip = !iconPath.IsEqualTo_NoCase(IconPath);
if (!Other7Zip)
{
State = kExtState_7Zip;
diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc
index 42e72cf1..3bb143a4 100644
--- a/CPP/7zip/UI/FileManager/SystemPage.rc
+++ b/CPP/7zip/UI/FileManager/SystemPage.rc
@@ -1,18 +1,18 @@
#include "SystemPageRes.h"
#include "../../GuiCommon.rc"
-#define xc 200
-#define yc 250
+#define xc 240
+#define yc 252
IDD_SYSTEM DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
CAPTION "System"
BEGIN
LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8
- PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 72, m + 12, 40, bys
- PUSHBUTTON "+", IDB_SYSTEM_ALL, 140, m + 12, 40, bys
+ PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 80, m + 12, 40, bys
+ PUSHBUTTON "+", IDB_SYSTEM_ALL, 166, m + 12, 40, bys
CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32",
LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
- m, m + 32, xc, (yc - m - 32 - 1)
+ m, m + 32, xc, (yc - 32)
END
#ifdef UNDER_CE
@@ -32,7 +32,12 @@ BEGIN
PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 60, m + 12, 40, bys
CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32",
LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
- m, m + 32, xc, (yc - m - 32 - 1 - 8)
+ m, m + 32, xc, (yc - 32)
END
#endif
+
+STRINGTABLE
+BEGIN
+ IDS_SYSTEM_ALL_USERS "All users"
+END
diff --git a/CPP/7zip/UI/FileManager/SystemPageRes.h b/CPP/7zip/UI/FileManager/SystemPageRes.h
index edc576f7..c8944482 100644
--- a/CPP/7zip/UI/FileManager/SystemPageRes.h
+++ b/CPP/7zip/UI/FileManager/SystemPageRes.h
@@ -2,6 +2,7 @@
#define IDD_SYSTEM_2 12200
#define IDT_SYSTEM_ASSOCIATE 2201
+#define IDS_SYSTEM_ALL_USERS 2202
#define IDL_SYSTEM_ASSOCIATE 100
#define IDB_SYSTEM_CURRENT 101
diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp
index 354b479f..0fac2506 100644
--- a/CPP/7zip/UI/FileManager/TextPairs.cpp
+++ b/CPP/7zip/UI/FileManager/TextPairs.cpp
@@ -185,6 +185,6 @@ void CPairsStorage::SaveToString(UString &text) const
text += L' ';
text += pair.Value;
text += L'\x0D';
- text += L'\n';
+ text.Add_LF();
}
}
diff --git a/CPP/7zip/UI/FileManager/TextPairs.h b/CPP/7zip/UI/FileManager/TextPairs.h
index d27cd97c..0a71d044 100644
--- a/CPP/7zip/UI/FileManager/TextPairs.h
+++ b/CPP/7zip/UI/FileManager/TextPairs.h
@@ -19,7 +19,7 @@ class CPairsStorage
int FindID(const UString &id) const;
void Sort();
public:
- void Clear() { Pairs.Clear(); };
+ void Clear() { Pairs.Clear(); }
bool ReadFromString(const UString &text);
void SaveToString(UString &text) const;
diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp
index 4141f01d..67e70fb7 100644
--- a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp
+++ b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp
@@ -2,15 +2,29 @@
#include "StdAfx.h"
-#include "PasswordDialog.h"
+#include "../../../Windows/ErrorMsg.h"
+
+#include "../GUI/resource3.h"
+
+#include "LangUtils.h"
#include "UpdateCallback100.h"
-STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles)
+STDMETHODIMP CUpdateCallback100Imp::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 /* isDir */)
+{
+ return ProgressDialog->Sync.ScanProgress(numFiles, totalSize, us2fs(path));
+}
+
+STDMETHODIMP CUpdateCallback100Imp::ScanError(const wchar_t *path, HRESULT errorCode)
{
- ProgressDialog->Sync.Set_NumFilesTotal(numFiles);
+ ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
return S_OK;
}
+STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles)
+{
+ return ProgressDialog->Sync.Set_NumFilesTotal(numFiles);
+}
+
STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size)
{
ProgressDialog->Sync.Set_NumBytesTotal(size);
@@ -30,35 +44,63 @@ STDMETHODIMP CUpdateCallback100Imp::SetRatioInfo(const UInt64 *inSize, const UIn
STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name)
{
- ProgressDialog->Sync.Set_FilePath(name);
- return S_OK;
+ return SetOperation_Base(NUpdateNotifyOp::kAdd, name, false);
}
STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name)
{
- ProgressDialog->Sync.Set_FilePath(name);
- return S_OK;
+ return SetOperation_Base(NUpdateNotifyOp::kDelete, name, false);
}
STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* operationResult */)
{
- ProgressDialog->Sync.Set_NumFilesCur(++_numFiles);
+ ProgressDialog->Sync.Set_NumFilesCur(++NumFiles);
+ return S_OK;
+}
+
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);
+
+HRESULT CUpdateCallback100Imp::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
+{
+ if (opRes != NArchive::NExtract::NOperationResult::kOK)
+ {
+ UString s;
+ SetExtractErrorMessage(opRes, isEncrypted, name, s);
+ ProgressDialog->Sync.AddError_Message(s);
+ }
return S_OK;
}
+HRESULT CUpdateCallback100Imp::ReportUpdateOperation(UInt32 notifyOp, const wchar_t *name, Int32 isDir)
+{
+ return SetOperation_Base(notifyOp, name, IntToBool(isDir));
+}
+
STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message)
{
ProgressDialog->Sync.AddError_Message(message);
return S_OK;
}
+HRESULT CUpdateCallback100Imp::OpenFileError(const wchar_t *path, HRESULT errorCode)
+{
+ ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
+ return S_OK;
+}
+
+STDMETHODIMP CUpdateCallback100Imp::ReadingFileError(const wchar_t *path, HRESULT errorCode)
+{
+ ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
+ return S_OK;
+}
+
STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
*password = NULL;
- *passwordIsDefined = BoolToInt(_passwordIsDefined);
- if (!_passwordIsDefined)
+ *passwordIsDefined = BoolToInt(PasswordIsDefined);
+ if (!PasswordIsDefined)
return S_OK;
- return StringToBstr(_password, password);
+ return StringToBstr(Password, password);
}
STDMETHODIMP CUpdateCallback100Imp::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
@@ -74,14 +116,9 @@ STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, con
STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)
{
*password = NULL;
- if (!_passwordIsDefined)
+ if (!PasswordIsDefined)
{
- CPasswordDialog dialog;
- ProgressDialog->WaitCreating();
- if (dialog.Create(*ProgressDialog) != IDOK)
- return E_ABORT;
- _password = dialog.Password;
- _passwordIsDefined = true;
+ RINOK(ShowAskPasswordDialog())
}
- return StringToBstr(_password, password);
+ return StringToBstr(Password, password);
}
diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.h b/CPP/7zip/UI/FileManager/UpdateCallback100.h
index 944453a1..7cbc11e3 100644
--- a/CPP/7zip/UI/FileManager/UpdateCallback100.h
+++ b/CPP/7zip/UI/FileManager/UpdateCallback100.h
@@ -9,26 +9,29 @@
#include "../Agent/IFolderArchive.h"
+#include "../GUI/UpdateCallbackGUI2.h"
+
#include "ProgressDialog2.h"
class CUpdateCallback100Imp:
public IFolderArchiveUpdateCallback,
+ public IFolderArchiveUpdateCallback2,
+ public IFolderScanProgress,
public ICryptoGetTextPassword2,
public ICryptoGetTextPassword,
public IArchiveOpenCallback,
public ICompressProgressInfo,
+ public CUpdateCallbackGUI2,
public CMyUnknownImp
{
- bool _passwordIsDefined;
- UString _password;
- UInt64 _numFiles;
public:
- CProgressDialog *ProgressDialog;
- CUpdateCallback100Imp(): ProgressDialog(0) {}
+ // CUpdateCallback100Imp() {}
- MY_UNKNOWN_IMP5(
+ MY_UNKNOWN_IMP7(
IFolderArchiveUpdateCallback,
+ IFolderArchiveUpdateCallback2,
+ IFolderScanProgress,
ICryptoGetTextPassword2,
ICryptoGetTextPassword,
IArchiveOpenCallback,
@@ -37,18 +40,13 @@ public:
INTERFACE_IProgress(;)
INTERFACE_IArchiveOpenCallback(;)
INTERFACE_IFolderArchiveUpdateCallback(;)
+ INTERFACE_IFolderArchiveUpdateCallback2(;)
+ INTERFACE_IFolderScanProgress(;)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
-
- void Init(bool passwordIsDefined, const UString &password)
- {
- _passwordIsDefined = passwordIsDefined;
- _password = password;
- _numFiles = 0;
- }
};
#endif
diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp
index 9688a4a5..2818d0f3 100644
--- a/CPP/7zip/UI/FileManager/ViewSettings.cpp
+++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp
@@ -302,7 +302,7 @@ void ReadCopyHistory(UStringVector &folders)
void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s)
{
for (unsigned i = 0; i < list.Size();)
- if (s.IsEqualToNoCase(list[i]))
+ if (s.IsEqualTo_NoCase(list[i]))
list.Delete(i);
else
i++;
diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile
index 96ae902f..d9e81780 100644
--- a/CPP/7zip/UI/FileManager/makefile
+++ b/CPP/7zip/UI/FileManager/makefile
@@ -97,6 +97,7 @@ EXPLORER_OBJS = \
GUI_OBJS = \
$O\HashGUI.obj \
+ $O\UpdateCallbackGUI2.obj \
COMPRESS_OBJS = \
$O\CopyCoder.obj \
diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h
index 55af3555..23e64edc 100644
--- a/CPP/7zip/UI/FileManager/resource.h
+++ b/CPP/7zip/UI/FileManager/resource.h
@@ -45,6 +45,7 @@
#define IDM_CREATE_FILE 556
// #define IDM_EXIT 557
#define IDM_LINK 558
+#define IDM_ALT_STREAMS 559
#define IDM_SELECT_ALL 600
#define IDM_DESELECT_ALL 601
diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc
index 61cf33e8..fb57e4f0 100644
--- a/CPP/7zip/UI/FileManager/resource.rc
+++ b/CPP/7zip/UI/FileManager/resource.rc
@@ -48,6 +48,7 @@ BEGIN
MENUITEM "Create File\tCtrl+N", IDM_CREATE_FILE
MENUITEM SEPARATOR
MENUITEM "&Link...", IDM_LINK
+ MENUITEM "&Alternate streams", IDM_ALT_STREAMS
MENUITEM SEPARATOR
MENUITEM "E&xit\tAlt+F4", IDCLOSE
END
@@ -252,5 +253,6 @@ END
#include "SplitDialog.rc"
#include "SystemPage.rc"
#include "../GUI/Extract.rc"
+#include "../GUI/resource3.rc"
#include "../Explorer/resource2.rc"
#include "resourceGui.rc"
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
index 1f4bcab5..2f118846 100644
--- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
+++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../../C/CpuArch.h"
+
#include "../../../Common/Defs.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/MyException.h"
@@ -15,10 +17,14 @@
#include "../FileManager/HelpUtils.h"
+#include "../../MyVersion.h"
+
#include "BenchmarkDialog.h"
using namespace NWindows;
+void GetCpuName(AString &s);
+
static LPCWSTR kHelpTopic = L"fm/benchmark.htm";
static const UINT_PTR kTimerID = 4;
@@ -72,7 +78,7 @@ static const int kMinDicLogSize = 21;
#endif
static const UInt32 kMinDicSize = (1 << kMinDicLogSize);
static const UInt32 kMaxDicSize =
- #ifdef _WIN64
+ #ifdef MY_CPU_64BIT
(1 << 30);
#else
(1 << 27);
@@ -111,6 +117,34 @@ bool CBenchmarkDialog::OnInit()
_consoleEdit.SendMessage(WM_SETFONT, (WPARAM)_font._font, TRUE);
}
+ {
+ TCHAR s[40];
+ s[0] = '/';
+ s[1] = ' ';
+ ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
+ SetItemText(IDT_BENCH_HARDWARE_THREADS, s);
+ }
+
+ {
+ UString s;
+ {
+ AString cpuName;
+ GetCpuName(cpuName);
+ s.SetFromAscii(cpuName);
+ SetItemText(IDT_BENCH_CPU, s);
+ }
+
+ s.SetFromAscii("7-Zip " MY_VERSION " ["
+ #ifdef MY_CPU_64BIT
+ "64-bit"
+ #elif defined MY_CPU_32BIT
+ "32-bit"
+ #endif
+ "]");
+ SetItemText(IDT_BENCH_VER, s);
+ }
+
+
UInt32 numCPUs = NSystem::GetNumberOfProcessors();
if (numCPUs < 1)
numCPUs = 1;
@@ -270,9 +304,7 @@ void CBenchmarkDialog::OnChangeSettings()
{
EnableItem(IDB_STOP, true);
UInt32 dictionary = OnChangeDictionary();
- TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 };
- ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
- SetItemText(IDT_BENCH_HARDWARE_THREADS, s);
+
for (int i = 0; i < ARRAY_SIZE(g_IDs); i++)
SetItemText(g_IDs[i], kProcessingString);
_startTime = GetTickCount();
@@ -394,6 +426,14 @@ bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
ConvertUInt64ToString(Sync.NumPasses, s);
SetItemText(IDT_BENCH_PASSES_VAL, s);
+ /*
+ if (Sync.FreqWasChanged)
+ {
+ SetItemText(IDT_BENCH_FREQ, Sync.Freq);
+ Sync.FreqWasChanged = false;
+ }
+ */
+
{
UInt32 dicSizeTemp = (UInt32)MyMax(Sync.ProcessedSize, UInt64(1) << 20);
dicSizeTemp = MyMin(dicSizeTemp, Sync.DictionarySize),
@@ -498,11 +538,26 @@ struct CBenchCallback: public IBenchCallback
UInt32 dictionarySize;
CProgressSyncInfo *Sync;
+ // void AddCpuFreq(UInt64 cpuFreq);
HRESULT SetFreq(bool showFreq, UInt64 cpuFreq);
HRESULT SetEncodeResult(const CBenchInfo &info, bool final);
HRESULT SetDecodeResult(const CBenchInfo &info, bool final);
};
+/*
+void CBenchCallback::AddCpuFreq(UInt64 cpuFreq)
+{
+ NSynchronization::CCriticalSectionLock lock(Sync->CS);
+ {
+ wchar_t s[32];
+ ConvertUInt64ToString(cpuFreq, s);
+ Sync->Freq.Add_Space_if_NotEmpty();
+ Sync->Freq += s;
+ Sync->FreqWasChanged = true;
+ }
+}
+*/
+
HRESULT CBenchCallback::SetFreq(bool /* showFreq */, UInt64 /* cpuFreq */)
{
return S_OK;
@@ -605,6 +660,7 @@ HRESULT CThreadBenchmark::Process()
CBenchCallback2 callback2;
callback2.Sync = &sync;
HRESULT result;
+
try
{
CObjectVector<CProperty> props;
@@ -624,11 +680,11 @@ HRESULT CThreadBenchmark::Process()
}
{
CProperty prop;
- prop.Name = L"d";
+ prop.Name = L'd';
wchar_t s[16];
ConvertUInt32ToString(dictionarySize, s);
prop.Name += s;
- prop.Name += 'b';
+ prop.Name += L'b';
props.Add(prop);
}
}
@@ -724,7 +780,7 @@ HRESULT Benchmark(
const CProperty &prop = props[i];
UString name = prop.Name;
name.MakeLower_Ascii();
- if (name.IsEqualToNoCase(L"m") && prop.Value == L"*")
+ if (name.IsEqualTo_Ascii_NoCase("m") && prop.Value == L"*")
{
bd.TotalMode = true;
continue;
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.h b/CPP/7zip/UI/GUI/BenchmarkDialog.h
index 82531117..a5f0292a 100644
--- a/CPP/7zip/UI/GUI/BenchmarkDialog.h
+++ b/CPP/7zip/UI/GUI/BenchmarkDialog.h
@@ -51,11 +51,15 @@ public:
AString Text;
bool TextWasChanged;
+ // UString Freq;
+ // bool FreqWasChanged;
+
CProgressSyncInfo()
{
if (_startEvent.Create() != S_OK)
throw 3986437;
}
+
void Init()
{
Changed = false;
@@ -70,9 +74,13 @@ public:
NumPasses = 0;
+ // Freq.SetFromAscii("MHz: ");
+ // FreqWasChanged = true;
+
Text.Empty();
TextWasChanged = true;
}
+
void Stop()
{
NWindows::NSynchronization::CCriticalSectionLock lock(CS);
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.rc b/CPP/7zip/UI/GUI/BenchmarkDialog.rc
index a31d2f25..cae9097b 100644
--- a/CPP/7zip/UI/GUI/BenchmarkDialog.rc
+++ b/CPP/7zip/UI/GUI/BenchmarkDialog.rc
@@ -2,7 +2,7 @@
#include "../../GuiCommon.rc"
#define xc 332
-#define yc 228
+#define yc 248
#undef g0xs
#undef g1x
@@ -42,10 +42,13 @@
#define g3x (m + g2xs)
#undef GROUP_Y_SIZE
+#undef GROUP_Y2_SIZE
#ifdef UNDER_CE
#define GROUP_Y_SIZE 8
+#define GROUP_Y2_SIZE 8
#else
#define GROUP_Y_SIZE 40
+#define GROUP_Y2_SIZE 32
#endif
IDD_BENCH DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX
@@ -101,11 +104,14 @@ BEGIN
RTEXT "", IDT_BENCH_DECOMPR_RPU2, xRpu, 136, sRpu, 8
RTEXT "", IDT_BENCH_DECOMPR_RATING2, xRating, 136, sRating, 8
- GROUPBOX "Total Rating", IDG_BENCH_TOTAL_RATING, xTotalRating, 163, sTotalRating, GROUP_Y_SIZE
+ GROUPBOX "Total Rating", IDG_BENCH_TOTAL_RATING, xTotalRating, 163, sTotalRating, GROUP_Y2_SIZE
- RTEXT "", IDT_BENCH_TOTAL_USAGE_VAL, xUsage, 181, sUsage, 8
- RTEXT "", IDT_BENCH_TOTAL_RPU_VAL, xRpu, 181, sRpu, 8
- RTEXT "", IDT_BENCH_TOTAL_RATING_VAL, xRating, 181, sRating, 8
+ RTEXT "", IDT_BENCH_TOTAL_USAGE_VAL, xUsage, 176, sUsage, 8
+ RTEXT "", IDT_BENCH_TOTAL_RPU_VAL, xRpu, 176, sRpu, 8
+ RTEXT "", IDT_BENCH_TOTAL_RATING_VAL, xRating, 176, sRating, 8
+
+ RTEXT "", IDT_BENCH_CPU, m, 202, xc, 8
+ RTEXT "", IDT_BENCH_VER, m, 216, xc, 8
LTEXT "Elapsed time:", IDT_BENCH_ELAPSED, m, 163, g2xs, 8
LTEXT "Size:", IDT_BENCH_SIZE, m, 176, g2xs, 8
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h
index 7dd6d031..a632d764 100644
--- a/CPP/7zip/UI/GUI/BenchmarkDialogRes.h
+++ b/CPP/7zip/UI/GUI/BenchmarkDialogRes.h
@@ -9,6 +9,9 @@
#define IDC_BENCH_NUM_THREADS 103
#define IDT_BENCH_HARDWARE_THREADS 104
+#define IDT_BENCH_VER 105
+#define IDT_BENCH_CPU 106
+
#define IDT_BENCH_COMPRESS_SPEED1 110
#define IDT_BENCH_COMPRESS_SPEED2 111
#define IDT_BENCH_COMPRESS_RATING1 112
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp
index a2d0ac2b..23b6f52f 100644
--- a/CPP/7zip/UI/GUI/CompressDialog.cpp
+++ b/CPP/7zip/UI/GUI/CompressDialog.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../../C/CpuArch.h"
+
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
@@ -76,7 +78,7 @@ using namespace NFile;
using namespace NName;
using namespace NDir;
-static const int kHistorySize = 20;
+static const unsigned kHistorySize = 20;
static LPCWSTR kExeExt = L".exe";
static LPCWSTR k7zFormat = L"7z";
@@ -170,7 +172,7 @@ struct CFormatInfo
LPCWSTR Name;
UInt32 LevelsMask;
const EMethodID *MathodIDs;
- int NumMethods;
+ unsigned NumMethods;
bool Filter;
bool Solid;
bool MultiThread;
@@ -372,7 +374,7 @@ bool CCompressDialog::OnInit()
m_Format.SetCurSel(index);
continue;
}
- if (i == 0 || ai.Name.IsEqualToNoCase(m_RegistryInfo.ArcType))
+ if (i == 0 || ai.Name.IsEqualTo_NoCase(m_RegistryInfo.ArcType))
{
m_Format.SetCurSel(index);
Info.FormatIndex = arcIndex;
@@ -455,7 +457,7 @@ void CCompressDialog::UpdatePasswordControl()
bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
{
- switch(buttonID)
+ switch (buttonID)
{
case IDB_COMPRESS_SET_ARCHIVE:
{
@@ -554,9 +556,8 @@ bool CCompressDialog::IsSFX()
static int GetExtDotPos(const UString &s)
{
- int dotPos = s.ReverseFind('.');
- int slashPos = MyMax(s.ReverseFind(WCHAR_PATH_SEPARATOR), s.ReverseFind('/'));
- if (dotPos >= 0 && dotPos > slashPos + 1)
+ int dotPos = s.ReverseFind_Dot();
+ if (dotPos > s.ReverseFind_PathSepar() + 1)
return dotPos;
return -1;
}
@@ -578,7 +579,7 @@ void CCompressDialog::OnButtonSFX()
if (dotPos >= 0)
{
UString ext = fileName.Ptr(dotPos);
- if (ext.IsEqualToNoCase(kExeExt))
+ if (ext.IsEqualTo_NoCase(kExeExt))
{
fileName.DeleteFrom(dotPos);
m_ArchivePath.SetText(fileName);
@@ -690,8 +691,7 @@ void CCompressDialog::OnOK()
return;
}
UString method = GetEncryptionMethodSpec();
- method.MakeLower_Ascii();
- if (method.Find(L"aes") == 0)
+ if (method.IsPrefixedBy_Ascii_NoCase("aes"))
{
if (Info.Password.Len() > 99)
{
@@ -820,7 +820,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
{
if (code == CBN_SELCHANGE)
{
- switch(itemID)
+ switch (itemID)
{
case IDC_COMPRESS_ARCHIVE:
{
@@ -914,7 +914,7 @@ void CCompressDialog::SetArchiveName2(bool prevWasSFX)
if (prevWasSFX)
prevExtension = kExeExt;
else
- prevExtension = UString('.') + prevArchiverInfo.GetMainExt();
+ prevExtension = UString(L'.') + prevArchiverInfo.GetMainExt();
const unsigned prevExtensionLen = prevExtension.Len();
if (fileName.Len() >= prevExtensionLen)
if (StringsAreEqualNoCase(fileName.RightPtr(prevExtensionLen), prevExtension))
@@ -962,7 +962,7 @@ int CCompressDialog::FindRegistryFormat(const UString &name)
FOR_VECTOR (i, m_RegistryInfo.Formats)
{
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i];
- if (name.IsEqualToNoCase(GetUnicodeString(fo.FormatID)))
+ if (name.IsEqualTo_NoCase(GetUnicodeString(fo.FormatID)))
return i;
}
return -1;
@@ -984,7 +984,7 @@ int CCompressDialog::GetStaticFormatIndex()
{
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
for (unsigned i = 0; i < ARRAY_SIZE(g_Formats); i++)
- if (ai.Name.IsEqualToNoCase(g_Formats[i].Name))
+ if (ai.Name.IsEqualTo_NoCase(g_Formats[i].Name))
return i;
return 0; // -1;
}
@@ -1016,8 +1016,8 @@ void CCompressDialog::SetLevel()
else
level = 9;
}
- int i;
- for (i = 0; i <= 9; i++)
+
+ for (unsigned i = 0; i <= 9; i++)
{
if ((fi.LevelsMask & (1 << i)) != 0)
{
@@ -1051,7 +1051,8 @@ void CCompressDialog::SetMethod(int keepMethodId)
}
bool isSfx = IsSFX();
bool weUseSameMethod = false;
- for (int m = 0; m < fi.NumMethods; m++)
+
+ for (unsigned m = 0; m < fi.NumMethods; m++)
{
EMethodID methodID = fi.MathodIDs[m];
if (isSfx)
@@ -1066,9 +1067,10 @@ void CCompressDialog::SetMethod(int keepMethodId)
weUseSameMethod = true;
continue;
}
- if ((defaultMethod.IsEqualToNoCase(method) || m == 0) && !weUseSameMethod)
+ if ((defaultMethod.IsEqualTo_NoCase(method) || m == 0) && !weUseSameMethod)
m_Method.SetCurSel(itemIndex);
}
+
if (!weUseSameMethod)
{
SetDictionary();
@@ -1079,19 +1081,19 @@ void CCompressDialog::SetMethod(int keepMethodId)
bool CCompressDialog::IsZipFormat()
{
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- return ai.Name.IsEqualToNoCase(L"zip");
+ return ai.Name.IsEqualTo_Ascii_NoCase("zip");
}
void CCompressDialog::SetEncryptionMethod()
{
_encryptionMethod.ResetContent();
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- if (ai.Name.IsEqualToNoCase(L"7z"))
+ if (ai.Name.IsEqualTo_Ascii_NoCase("7z"))
{
_encryptionMethod.AddString(TEXT("AES-256"));
_encryptionMethod.SetCurSel(0);
}
- else if (ai.Name.IsEqualToNoCase(L"zip"))
+ else if (ai.Name.IsEqualTo_Ascii_NoCase("zip"))
{
int index = FindRegistryFormat(ai.Name);
UString encryptionMethod;
@@ -1102,7 +1104,7 @@ void CCompressDialog::SetEncryptionMethod()
}
_encryptionMethod.AddString(TEXT("ZipCrypto"));
_encryptionMethod.AddString(TEXT("AES-256"));
- _encryptionMethod.SetCurSel(encryptionMethod.Find(L"AES") == 0 ? 1 : 0);
+ _encryptionMethod.SetCurSel(encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0);
}
}
@@ -1155,138 +1157,149 @@ void CCompressDialog::SetDictionary()
m_Dictionary.ResetContent();
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
int index = FindRegistryFormat(ai.Name);
- UInt32 defaultDictionary = (UInt32)(Int32)-1;
+ UInt32 defaultDict = (UInt32)(Int32)-1;
+
if (index >= 0)
{
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- if (fo.Method.IsEqualToNoCase(GetMethodSpec()))
- defaultDictionary = fo.Dictionary;
+ if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()))
+ defaultDict = fo.Dictionary;
}
+
int methodID = GetMethodID();
UInt32 level = GetLevel2();
if (methodID < 0)
return;
const UInt64 maxRamSize = GetMaxRamSizeForProgram();
+
switch (methodID)
{
case kLZMA:
case kLZMA2:
{
static const UInt32 kMinDicSize = (1 << 16);
- if (defaultDictionary == (UInt32)(Int32)-1)
+ if (defaultDict == (UInt32)(Int32)-1)
{
- if (level >= 9) defaultDictionary = (1 << 26);
- else if (level >= 7) defaultDictionary = (1 << 25);
- else if (level >= 5) defaultDictionary = (1 << 24);
- else if (level >= 3) defaultDictionary = (1 << 20);
- else defaultDictionary = (kMinDicSize);
+ if (level >= 9) defaultDict = (1 << 26);
+ else if (level >= 7) defaultDict = (1 << 25);
+ else if (level >= 5) defaultDict = (1 << 24);
+ else if (level >= 3) defaultDict = (1 << 20);
+ else defaultDict = (kMinDicSize);
}
- int i;
+
AddDictionarySize(kMinDicSize);
m_Dictionary.SetCurSel(0);
- for (i = 20; i <= 30; i++)
- for (int j = 0; j < 2; j++)
+
+ for (unsigned i = 20; i <= 31; i++)
+ for (unsigned j = 0; j < 2; j++)
{
if (i == 20 && j > 0)
continue;
- UInt32 dictionary = (1 << i) + (j << (i - 1));
- if (dictionary >
- #ifdef _WIN64
- (1 << 30)
+ UInt32 dict = ((UInt32)(2 + j) << (i - 1));
+ if (dict >
+ #ifdef MY_CPU_64BIT
+ (3 << 29)
#else
(1 << 26)
#endif
)
continue;
- AddDictionarySize(dictionary);
+ AddDictionarySize(dict);
UInt64 decomprSize;
- UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize);
- if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize)
+ UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize);
+ if (dict <= defaultDict && requiredComprSize <= maxRamSize)
m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
}
- // SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
+ // SetNearestSelectComboBox(m_Dictionary, defaultDict);
break;
}
+
case kPPMd:
{
- if (defaultDictionary == (UInt32)(Int32)-1)
+ if (defaultDict == (UInt32)(Int32)-1)
{
- if (level >= 9) defaultDictionary = (192 << 20);
- else if (level >= 7) defaultDictionary = ( 64 << 20);
- else if (level >= 5) defaultDictionary = ( 16 << 20);
- else defaultDictionary = ( 4 << 20);
+ if (level >= 9) defaultDict = (192 << 20);
+ else if (level >= 7) defaultDict = ( 64 << 20);
+ else if (level >= 5) defaultDict = ( 16 << 20);
+ else defaultDict = ( 4 << 20);
}
- int i;
- for (i = 20; i < 31; i++)
- for (int j = 0; j < 2; j++)
+
+ for (unsigned i = 20; i < 31; i++)
+ for (unsigned j = 0; j < 2; j++)
{
if (i == 20 && j > 0)
continue;
- UInt32 dictionary = (1 << i) + (j << (i - 1));
- if (dictionary >
- #ifdef _WIN64
+ UInt32 dict = ((UInt32)(2 + j) << (i - 1));
+ if (dict >
+ #ifdef MY_CPU_64BIT
(1 << 30)
#else
(1 << 29)
#endif
)
continue;
- AddDictionarySize(dictionary);
+ AddDictionarySize(dict);
UInt64 decomprSize;
- UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize);
- if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)
+ UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize);
+ if (dict <= defaultDict && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)
m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
}
- SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
+
+ SetNearestSelectComboBox(m_Dictionary, defaultDict);
break;
}
+
case kDeflate:
{
AddDictionarySize(32 << 10);
m_Dictionary.SetCurSel(0);
break;
}
+
case kDeflate64:
{
AddDictionarySize(64 << 10);
m_Dictionary.SetCurSel(0);
break;
}
+
case kBZip2:
{
- if (defaultDictionary == (UInt32)(Int32)-1)
+ if (defaultDict == (UInt32)(Int32)-1)
{
- if (level >= 5)
- defaultDictionary = (900 << 10);
- else if (level >= 3)
- defaultDictionary = (500 << 10);
- else
- defaultDictionary = (100 << 10);
+ if (level >= 5) defaultDict = (900 << 10);
+ else if (level >= 3) defaultDict = (500 << 10);
+ else defaultDict = (100 << 10);
}
- for (int i = 1; i <= 9; i++)
+
+ for (unsigned i = 1; i <= 9; i++)
{
- UInt32 dictionary = (i * 100) << 10;
- AddDictionarySize(dictionary);
- if (dictionary <= defaultDictionary || m_Dictionary.GetCount() == 0)
+ UInt32 dict = ((UInt32)i * 100) << 10;
+ AddDictionarySize(dict);
+ if (dict <= defaultDict || m_Dictionary.GetCount() == 0)
m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
}
+
break;
}
+
case kPPMdZip:
{
- if (defaultDictionary == (UInt32)(Int32)-1)
- defaultDictionary = (1 << (19 + (level > 8 ? 8 : level)));
- for (int i = 20; i <= 28; i++)
+ if (defaultDict == (UInt32)(Int32)-1)
+ defaultDict = (1 << (19 + (level > 8 ? 8 : level)));
+
+ for (unsigned i = 20; i <= 28; i++)
{
- UInt32 dictionary = (1 << i);
- AddDictionarySize(dictionary);
+ UInt32 dict = (1 << i);
+ AddDictionarySize(dict);
UInt64 decomprSize;
- UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize);
- if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)
+ UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize);
+ if (dict <= defaultDict && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)
m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
}
- SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
+
+ SetNearestSelectComboBox(m_Dictionary, defaultDict);
break;
}
}
@@ -1322,16 +1335,19 @@ void CCompressDialog::SetOrder()
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
int index = FindRegistryFormat(ai.Name);
UInt32 defaultOrder = (UInt32)(Int32)-1;
+
if (index >= 0)
{
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- if (fo.Method.IsEqualToNoCase(GetMethodSpec()))
+ if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()))
defaultOrder = fo.Order;
}
+
int methodID = GetMethodID();
UInt32 level = GetLevel2();
if (methodID < 0)
return;
+
switch (methodID)
{
case kLZMA:
@@ -1339,10 +1355,10 @@ void CCompressDialog::SetOrder()
{
if (defaultOrder == (UInt32)(Int32)-1)
defaultOrder = (level >= 7) ? 64 : 32;
- for (int i = 3; i <= 8; i++)
- for (int j = 0; j < 2; j++)
+ for (unsigned i = 3; i <= 8; i++)
+ for (unsigned j = 0; j < 2; j++)
{
- UInt32 order = (1 << i) + (j << (i - 1));
+ UInt32 order = ((UInt32)(2 + j) << (i - 1));
if (order <= 256)
AddOrder(order);
}
@@ -1350,66 +1366,64 @@ void CCompressDialog::SetOrder()
SetNearestSelectComboBox(m_Order, defaultOrder);
break;
}
+
case kPPMd:
{
if (defaultOrder == (UInt32)(Int32)-1)
{
- if (level >= 9)
- defaultOrder = 32;
- else if (level >= 7)
- defaultOrder = 16;
- else if (level >= 5)
- defaultOrder = 6;
- else
- defaultOrder = 4;
+ if (level >= 9) defaultOrder = 32;
+ else if (level >= 7) defaultOrder = 16;
+ else if (level >= 5) defaultOrder = 6;
+ else defaultOrder = 4;
}
- int i;
+
AddOrder(2);
AddOrder(3);
- for (i = 2; i < 8; i++)
- for (int j = 0; j < 4; j++)
+
+ for (unsigned i = 2; i < 8; i++)
+ for (unsigned j = 0; j < 4; j++)
{
- UInt32 order = (1 << i) + (j << (i - 2));
+ UInt32 order = (4 + j) << (i - 2);
if (order < 32)
AddOrder(order);
}
+
AddOrder(32);
SetNearestSelectComboBox(m_Order, defaultOrder);
break;
}
+
case kDeflate:
case kDeflate64:
{
if (defaultOrder == (UInt32)(Int32)-1)
{
- if (level >= 9)
- defaultOrder = 128;
- else if (level >= 7)
- defaultOrder = 64;
- else
- defaultOrder = 32;
+ if (level >= 9) defaultOrder = 128;
+ else if (level >= 7) defaultOrder = 64;
+ else defaultOrder = 32;
}
- int i;
- for (i = 3; i <= 8; i++)
- for (int j = 0; j < 2; j++)
+
+ for (unsigned i = 3; i <= 8; i++)
+ for (unsigned j = 0; j < 2; j++)
{
- UInt32 order = (1 << i) + (j << (i - 1));
+ UInt32 order = ((UInt32)(2 + j) << (i - 1));;
if (order <= 256)
AddOrder(order);
}
+
AddOrder(methodID == kDeflate64 ? 257 : 258);
SetNearestSelectComboBox(m_Order, defaultOrder);
break;
}
+
case kBZip2:
- {
break;
- }
+
case kPPMdZip:
{
if (defaultOrder == (UInt32)(Int32)-1)
defaultOrder = level + 3;
- for (int i = 2; i <= 16; i++)
+ for (unsigned i = 2; i <= 16; i++)
AddOrder(i);
SetNearestSelectComboBox(m_Order, defaultOrder);
break;
@@ -1442,9 +1456,9 @@ void CCompressDialog::SetSolidBlockSize()
if (level == 0)
return;
- UInt32 dictionary = GetDictionarySpec();
- if (dictionary == (UInt32)(Int32)-1)
- dictionary = 1;
+ UInt32 dict = GetDictionarySpec();
+ if (dict == (UInt32)(Int32)-1)
+ dict = 1;
UInt32 defaultBlockSize = (UInt32)(Int32)-1;
@@ -1453,7 +1467,7 @@ void CCompressDialog::SetSolidBlockSize()
if (index >= 0)
{
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- if (fo.Method.IsEqualToNoCase(GetMethodSpec()))
+ if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()))
defaultBlockSize = fo.BlockLogSize;
}
@@ -1461,9 +1475,10 @@ void CCompressDialog::SetSolidBlockSize()
m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize);
m_Solid.SetCurSel(0);
bool needSet = defaultBlockSize == (UInt32)(Int32)-1;
- for (int i = 20; i <= 36; i++)
+
+ for (unsigned i = 20; i <= 36; i++)
{
- if (needSet && dictionary >= (((UInt64)1 << (i - 7))) && i <= 32)
+ if (needSet && dict >= (((UInt64)1 << (i - 7))) && i <= 32)
defaultBlockSize = i;
TCHAR s[40];
ConvertUInt32ToString(1 << (i % 10), s);
@@ -1473,6 +1488,7 @@ void CCompressDialog::SetSolidBlockSize()
int index = (int)m_Solid.AddString(s);
m_Solid.SetItemData(index, (UInt32)i);
}
+
index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID));
m_Solid.SetItemData(index, kSolidBlockSize);
if (defaultBlockSize == (UInt32)(Int32)-1)
@@ -1497,7 +1513,7 @@ void CCompressDialog::SetNumThreads()
if (index >= 0)
{
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- if (fo.Method.IsEqualToNoCase(GetMethodSpec()) && fo.NumThreads != (UInt32)(Int32)-1)
+ if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()) && fo.NumThreads != (UInt32)(Int32)-1)
defaultValue = fo.NumThreads;
}
@@ -1521,7 +1537,7 @@ void CCompressDialog::SetNumThreads()
SetNearestSelectComboBox(m_NumThreads, defaultValue);
}
-UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory)
+UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory)
{
decompressMemory = UInt64(Int64(-1));
UInt32 level = GetLevel2();
@@ -1536,6 +1552,7 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo
if (fi.Filter && level >= 9)
size += (12 << 20) * 2 + (5 << 20);
UInt32 numThreads = GetNumThreads2();
+
if (IsZipFormat())
{
UInt32 numSubThreads = 1;
@@ -1545,13 +1562,15 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo
if (numMainThreads > 1)
size += (UInt64)numMainThreads << 25;
}
+
int methidId = GetMethodID();
+
switch (methidId)
{
case kLZMA:
case kLZMA2:
{
- UInt32 hs = dictionary - 1;
+ UInt32 hs = dict - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
@@ -1562,9 +1581,9 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo
hs >>= 1;
hs++;
UInt64 size1 = (UInt64)hs * 4;
- size1 += (UInt64)dictionary * 4;
+ size1 += (UInt64)dict * 4;
if (level >= 5)
- size1 += (UInt64)dictionary * 4;
+ size1 += (UInt64)dict * 4;
size1 += (2 << 20);
UInt32 numThreads1 = 1;
@@ -1573,27 +1592,31 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo
size1 += (2 << 20) + (4 << 20);
numThreads1 = 2;
}
+
UInt32 numBlockThreads = numThreads / numThreads1;
+
if (methidId == kLZMA || numBlockThreads == 1)
- size1 += (UInt64)dictionary * 3 / 2;
+ size1 += (UInt64)dict * 3 / 2;
else
{
- UInt64 chunkSize = (UInt64)dictionary << 2;
+ UInt64 chunkSize = (UInt64)dict << 2;
chunkSize = MyMax(chunkSize, (UInt64)(1 << 20));
chunkSize = MyMin(chunkSize, (UInt64)(1 << 28));
- chunkSize = MyMax(chunkSize, (UInt64)dictionary);
+ chunkSize = MyMax(chunkSize, (UInt64)dict);
size1 += chunkSize * 2;
}
size += size1 * numBlockThreads;
- decompressMemory = dictionary + (2 << 20);
+ decompressMemory = dict + (2 << 20);
return size;
}
+
case kPPMd:
{
- decompressMemory = dictionary + (2 << 20);
+ decompressMemory = dict + (2 << 20);
return size + decompressMemory;
}
+
case kDeflate:
case kDeflate64:
{
@@ -1606,18 +1629,21 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemo
decompressMemory = (2 << 20);
return size;
}
+
case kBZip2:
{
decompressMemory = (7 << 20);
UInt64 memForOneThread = (10 << 20);
return size + memForOneThread * numThreads;
}
+
case kPPMdZip:
{
- decompressMemory = dictionary + (2 << 20);
+ decompressMemory = dict + (2 << 20);
return size + (UInt64)decompressMemory * numThreads;
}
}
+
return (UInt64)(Int64)-1;
}
diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h
index 3463fefc..a7a3a3a7 100644
--- a/CPP/7zip/UI/GUI/CompressDialog.h
+++ b/CPP/7zip/UI/GUI/CompressDialog.h
@@ -164,7 +164,7 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
void SetSolidBlockSize();
void SetNumThreads();
- UInt64 GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory);
+ UInt64 GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory);
UInt64 GetMemoryUsage(UInt64 &decompressMemory);
void PrintMemUsage(UINT res, UInt64 value);
void SetMemoryUsage();
diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc
index 6c555a7e..d6ce5ac0 100644
--- a/CPP/7zip/UI/GUI/CompressDialog.rc
+++ b/CPP/7zip/UI/GUI/CompressDialog.rc
@@ -80,7 +80,7 @@ BEGIN
LTEXT "&Solid Block size:", IDT_COMPRESS_SOLID, m, 146, g0xs, 8
COMBOBOX IDC_COMPRESS_SOLID, g1x, 144, g1xs, 140, MY_COMBO
- LTEXT "&Number of CPU threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8
+ LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8
COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO
RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, 8
@@ -95,7 +95,7 @@ BEGIN
LTEXT "Split to &volumes, bytes:", IDT_SPLIT_TO_VOLUMES, m, 225, gSize, 8
COMBOBOX IDC_COMPRESS_VOLUME, m, 237, gSize, 73, MY_COMBO_WITH_EDIT
- LTEXT "&Parameters:", IDT_COMPRESS_PARAMETERS, m, 256, gSize, 8
+ LTEXT "Parameters:", IDT_COMPRESS_PARAMETERS, m, 256, gSize, 8
EDITTEXT IDE_COMPRESS_PARAMETERS, m, 268, gSize, 14, ES_AUTOHSCROLL
@@ -130,7 +130,7 @@ BEGIN
GROUPBOX "Encryption", IDG_COMPRESS_ENCRYPTION, g4x, yPsw, g4xs, GROUP_Y_SIZE_ENCRYPT
- LTEXT "Enter password:", IDT_PASSWORD_ENTER, g4x2, yPsw + 14, g4xs2, 8
+ LTEXT "Enter &password:", IDT_PASSWORD_ENTER, g4x2, yPsw + 14, g4xs2, 8
EDITTEXT IDE_COMPRESS_PASSWORD1, g4x2, yPsw + 26, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL
LTEXT "Reenter password:", IDT_PASSWORD_REENTER, g4x2, yPsw + 46, g4xs2, 8
EDITTEXT IDE_COMPRESS_PASSWORD2, g4x2, yPsw + 58, g4xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL
@@ -179,7 +179,7 @@ BEGIN
LTEXT "Split to &volumes, bytes:", IDT_SPLIT_TO_VOLUMES, m, 60, 32, 8
COMBOBOX IDC_COMPRESS_VOLUME, m + 32, 58, 44, 73, MY_COMBO_WITH_EDIT
- LTEXT "&Parameters:", IDT_COMPRESS_PARAMETERS, m + 80, 60, 48, 8
+ LTEXT "Parameters:", IDT_COMPRESS_PARAMETERS, m + 80, 60, 48, 8
EDITTEXT IDE_COMPRESS_PARAMETERS, m + 128, 58, 24, 13, ES_AUTOHSCROLL
COMBOBOX IDC_COMPRESS_UPDATE_MODE, m, 76, 88, 80, MY_COMBO
@@ -187,7 +187,7 @@ BEGIN
CONTROL "Compress shared files", IDX_COMPRESS_SHARED, MY_CHECKBOX, m, 94, xc, 10
- LTEXT "Enter password:", IDT_PASSWORD_ENTER, m, 112, 60, 8
+ LTEXT "Enter &password:", IDT_PASSWORD_ENTER, m, 112, 60, 8
EDITTEXT IDE_COMPRESS_PASSWORD1, m + 60, 110, 44, 13, ES_PASSWORD | ES_AUTOHSCROLL
CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m + 108, 112, 44, 10
diff --git a/CPP/7zip/UI/GUI/Extract.rc b/CPP/7zip/UI/GUI/Extract.rc
index defcfcc4..f75b2e6f 100644
--- a/CPP/7zip/UI/GUI/Extract.rc
+++ b/CPP/7zip/UI/GUI/Extract.rc
@@ -11,8 +11,14 @@ BEGIN
IDS_CANT_OPEN_ENCRYPTED_ARCHIVE "Can not open encrypted archive '{0}'. Wrong password?"
IDS_UNSUPPORTED_ARCHIVE_TYPE "Unsupported archive type"
+ IDS_CANT_OPEN_AS_TYPE "Can not open the file as {0} archive"
+ IDS_IS_OPEN_AS_TYPE "The file is open as {0} archive"
+ IDS_IS_OPEN_WITH_OFFSET "The archive is open with offset"
+
IDS_PROGRESS_EXTRACTING "Extracting"
+ IDS_PROGRESS_SKIPPING "Skipping"
+
IDS_EXTRACT_SET_FOLDER "Specify a location for extracted files."
IDS_EXTRACT_PATHS_FULL "Full pathnames"
@@ -32,7 +38,7 @@ BEGIN
IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED "Data error in encrypted file '{0}'. Wrong password?"
IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED "CRC failed in encrypted file '{0}'. Wrong password?"
- IDS_EXTRACT_MSG_WRONG_PSW "Wrong password?"
+ IDS_EXTRACT_MSG_WRONG_PSW_GUESS "Wrong password?"
// IDS_EXTRACT_MSG_ENCRYPTED "Encrypted file"
IDS_EXTRACT_MSG_UNSUPPORTED_METHOD "Unsupported compression method"
@@ -43,6 +49,7 @@ BEGIN
IDS_EXTRACT_MSG_DATA_AFTER_END "There are some data after the end of the payload data"
IDS_EXTRACT_MSG_IS_NOT_ARC "Is not archive"
IDS_EXTRACT_MSG_HEADERS_ERROR "Headers Error"
+ IDS_EXTRACT_MSG_WRONG_PSW_CLAIM "Wrong password"
IDS_OPEN_MSG_UNAVAILABLE_START "Unavailable start of archive"
IDS_OPEN_MSG_UNCONFIRMED_START "Unconfirmed start of archive"
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp
index d1ce8255..9a14c6c4 100644
--- a/CPP/7zip/UI/GUI/ExtractDialog.cpp
+++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp
@@ -143,7 +143,7 @@ bool CExtractDialog::OnInit()
GetText(s);
if (!ArcPath.IsEmpty())
{
- s += L" : ";
+ s.AddAscii(" : ");
s += ArcPath;
}
SetText(s);
@@ -289,7 +289,7 @@ void CExtractDialog::OnButtonSetPath()
void AddUniqueString(UStringVector &list, const UString &s)
{
FOR_VECTOR (i, list)
- if (s.IsEqualToNoCase(list[i]))
+ if (s.IsEqualTo_NoCase(list[i]))
return;
list.Add(s);
}
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp
index b5fbeaec..e58f6b2b 100644
--- a/CPP/7zip/UI/GUI/ExtractGUI.cpp
+++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp
@@ -40,20 +40,20 @@ static const wchar_t *kIncorrectOutDir = L"Incorrect output directory path";
static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true)
{
- wchar_t sz[32];
- s += LangString(resourceID);
+ AddLangString(s, resourceID);
if (addColon)
s += L':';
- s += L' ';
+ s.Add_Space();
+ char sz[32];
ConvertUInt64ToString(value, sz);
- s += sz;
- s += L'\n';
+ s.AddAscii(sz);
+ s.Add_LF();
}
static void AddSizePair(UString &s, UINT resourceID, UInt64 value)
{
wchar_t sz[32];
- s += LangString(resourceID);
+ AddLangString(s, resourceID);
s += L": ";
ConvertUInt64ToString(value, sz);
s += MyFormatNew(IDS_FILE_SIZE, sz);
@@ -65,7 +65,7 @@ static void AddSizePair(UString &s, UINT resourceID, UInt64 value)
s += sz;
s += L" MB)";
}
- s += L'\n';
+ s.Add_LF();
}
#endif
@@ -122,7 +122,7 @@ HRESULT CThreadExtracting::ProcessVirt()
AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize);
if (Stat.NumAltStreams != 0)
{
- s += L'\n';
+ s.Add_LF();
AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams);
AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize);
}
@@ -130,12 +130,12 @@ HRESULT CThreadExtracting::ProcessVirt()
if (HashBundle)
{
- s += L'\n';
+ s.Add_LF();
AddHashBundleRes(s, *HashBundle, UString());
}
- s += L'\n';
- s += LangString(IDS_MESSAGE_NO_ERRORS);
+ s.Add_LF();
+ AddLangString(s, IDS_MESSAGE_NO_ERRORS);
FinalMessage.OkMessage.Title = Title;
FinalMessage.OkMessage.Message = s;
@@ -237,7 +237,9 @@ HRESULT ExtractGUI(
0x02000603,
#endif
options.OutputDir);
- MyMessageBox(s2 + UString(L'\n') + s);
+ s2.Add_LF();
+ s2 += s;
+ MyMessageBox(s2);
return E_FAIL;
}
*/
diff --git a/CPP/7zip/UI/GUI/ExtractRes.h b/CPP/7zip/UI/GUI/ExtractRes.h
index 48738bbb..634ba6b5 100644
--- a/CPP/7zip/UI/GUI/ExtractRes.h
+++ b/CPP/7zip/UI/GUI/ExtractRes.h
@@ -6,8 +6,14 @@
#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 3006
#define IDS_UNSUPPORTED_ARCHIVE_TYPE 3007
+#define IDS_CANT_OPEN_AS_TYPE 3017
+#define IDS_IS_OPEN_AS_TYPE 3018
+#define IDS_IS_OPEN_WITH_OFFSET 3019
+
#define IDS_PROGRESS_EXTRACTING 3300
+#define IDS_PROGRESS_SKIPPING 3325
+
#define IDS_EXTRACT_SET_FOLDER 3402
#define IDS_EXTRACT_PATHS_FULL 3411
@@ -27,7 +33,7 @@
#define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED 3703
#define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED 3704
-#define IDS_EXTRACT_MSG_WRONG_PSW 3710
+#define IDS_EXTRACT_MSG_WRONG_PSW_GUESS 3710
// #define IDS_EXTRACT_MSG_ENCRYPTED 3711
#define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD 3721
@@ -38,6 +44,7 @@
#define IDS_EXTRACT_MSG_DATA_AFTER_END 3726
#define IDS_EXTRACT_MSG_IS_NOT_ARC 3727
#define IDS_EXTRACT_MSG_HEADERS_ERROR 3728
+#define IDS_EXTRACT_MSG_WRONG_PSW_CLAIM 3729
#define IDS_OPEN_MSG_UNAVAILABLE_START 3763
#define IDS_OPEN_MSG_UNCONFIRMED_START 3764
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp
index 592f7673..134ac021 100644
--- a/CPP/7zip/UI/GUI/GUI.cpp
+++ b/CPP/7zip/UI/GUI/GUI.cpp
@@ -126,14 +126,8 @@ static int Main2()
#endif
#endif
- CCodecs *codecs = new CCodecs;
- #ifdef EXTERNAL_CODECS
- CExternalCodecs __externalCodecs;
- __externalCodecs.GetCodecs = codecs;
- __externalCodecs.GetHashers = codecs;
- #else
- CMyComPtr<IUnknown> compressCodecsInfo = codecs;
- #endif
+ CREATE_CODECS_OBJECT
+
codecs->CaseSensitiveChange = options.CaseSensitiveChange;
codecs->CaseSensitive = options.CaseSensitive;
ThrowException_if_Error(codecs->Load());
@@ -144,8 +138,18 @@ static int Main2()
(isExtractGroupCommand
|| options.Command.IsFromUpdateGroup()))
+ {
+ #ifdef EXTERNAL_CODECS
+ if (!codecs->MainDll_ErrorPath.IsEmpty())
+ {
+ UString s = L"7-Zip cannot load module ";
+ s += fs2us(codecs->MainDll_ErrorPath);
+ throw s;
+ }
+ #endif
throw kNoFormats;
-
+ }
+
CObjectVector<COpenType> formatIndices;
if (!ParseOpenTypes(*codecs, options.ArcType, formatIndices))
{
@@ -171,12 +175,12 @@ static int Main2()
if (isExtractGroupCommand
|| options.Command.CommandType == NCommandType::kHash
|| options.Command.CommandType == NCommandType::kBenchmark)
- ThrowException_if_Error(__externalCodecs.LoadCodecs());
+ ThrowException_if_Error(__externalCodecs.Load());
#endif
if (options.Command.CommandType == NCommandType::kBenchmark)
{
- HRESULT res = Benchmark(EXTERNAL_CODECS_VARS options.Properties);
+ HRESULT res = Benchmark(EXTERNAL_CODECS_VARS_L options.Properties);
/*
if (res == S_FALSE)
{
@@ -188,6 +192,9 @@ static int Main2()
}
else if (isExtractGroupCommand)
{
+ UStringVector ArchivePathsSorted;
+ UStringVector ArchivePathsFullSorted;
+
CExtractCallbackImp *ecs = new CExtractCallbackImp;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
@@ -218,14 +225,35 @@ static int Main2()
if (!options.HashMethods.IsEmpty())
{
hb_ptr = &hb;
- ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS options.HashMethods));
+ ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods));
}
#endif
+ {
+ CDirItemsStat st;
+ HRESULT hresultMain = EnumerateDirItemsAndSort(
+ options.arcCensor,
+ NWildcard::k_RelatPath,
+ UString(), // addPathPrefix
+ ArchivePathsSorted,
+ ArchivePathsFullSorted,
+ st,
+ NULL // &scan: change it!!!!
+ );
+ if (hresultMain != S_OK)
+ {
+ /*
+ if (hresultMain != E_ABORT && messageWasDisplayed)
+ return NExitCode::kFatalError;
+ */
+ throw CSystemException(hresultMain);
+ }
+ }
+
HRESULT result = ExtractGUI(codecs,
formatIndices, excludedFormatIndices,
- options.ArchivePathsSorted,
- options.ArchivePathsFullSorted,
+ ArchivePathsSorted,
+ ArchivePathsFullSorted,
options.Censor.Pairs.Front().Head,
eo,
#ifndef _SFX
@@ -291,7 +319,7 @@ static int Main2()
else if (options.Command.CommandType == NCommandType::kHash)
{
bool messageWasDisplayed = false;
- HRESULT result = HashCalcGUI(EXTERNAL_CODECS_VARS
+ HRESULT result = HashCalcGUI(EXTERNAL_CODECS_VARS_L
options.Censor, options.HashOptions, messageWasDisplayed);
if (result != S_OK)
diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp
index 1cbdbfd4..63cdb2fd 100644
--- a/CPP/7zip/UI/GUI/GUI.dsp
+++ b/CPP/7zip/UI/GUI/GUI.dsp
@@ -45,7 +45,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /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"
@@ -72,7 +72,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
-# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /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"
@@ -99,7 +99,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /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"
@@ -127,7 +127,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
-# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /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"
@@ -513,6 +513,14 @@ SOURCE=..\FileManager\ProgramLocation.h
# End Source File
# Begin Source File
+SOURCE=..\FileManager\PropertyName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\FileManager\PropertyName.h
+# End Source File
+# Begin Source File
+
SOURCE=..\FileManager\RegistryUtils.cpp
# End Source File
# Begin Source File
@@ -577,6 +585,14 @@ SOURCE=.\UpdateCallbackGUI.h
# End Source File
# Begin Source File
+SOURCE=.\UpdateCallbackGUI2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\UpdateCallbackGUI2.h
+# End Source File
+# Begin Source File
+
SOURCE=.\UpdateGUI.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/UI/GUI/HashGUI.cpp b/CPP/7zip/UI/GUI/HashGUI.cpp
index 903e41fc..3eb7d7d4 100644
--- a/CPP/7zip/UI/GUI/HashGUI.cpp
+++ b/CPP/7zip/UI/GUI/HashGUI.cpp
@@ -22,7 +22,6 @@ using namespace NWindows;
class CHashCallbackGUI: public CProgressThreadVirt, public IHashCallbackUI
{
UInt64 NumFiles;
- UStringVector FailedFiles;
bool _curIsFolder;
UString FirstFileName;
@@ -45,33 +44,28 @@ public:
}
};
-static void NewLine(UString &s)
-{
- s += L'\n';
-}
-
static void AddValuePair(UString &s, UINT resourceID, UInt64 value)
{
- s += LangString(resourceID);
- s += L": ";
- wchar_t sz[32];
+ AddLangString(s, resourceID);
+ s.AddAscii(": ");
+ char sz[32];
ConvertUInt64ToString(value, sz);
- s += sz;
- NewLine(s);
+ s.AddAscii(sz);
+ s.Add_LF();
}
static void AddSizeValuePair(UString &s, UINT resourceID, UInt64 value)
{
- s += LangString(resourceID);
- s += L": ";
+ AddLangString(s, resourceID);
+ s.AddAscii(": ");
wchar_t sz[32];
ConvertUInt64ToString(value, sz);
s += MyFormatNew(IDS_FILE_SIZE, sz);
ConvertUInt64ToString(value >> 20, sz);
- s += L" (";
+ s.AddAscii(" (");
s += sz;
- s += L" MB)";
- NewLine(s);
+ s.AddAscii(" MB)");
+ s.Add_LF();
}
HRESULT CHashCallbackGUI::StartScanning()
@@ -81,23 +75,20 @@ HRESULT CHashCallbackGUI::StartScanning()
return CheckBreak();
}
-HRESULT CHashCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)
+HRESULT CHashCallbackGUI::ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir)
{
- return ProgressDialog.Sync.ScanProgress(numFiles, totalSize, path, isDir);
+ return ProgressDialog.Sync.ScanProgress(st.NumFiles, st.GetTotalBytes(), path, isDir);
}
-HRESULT CHashCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError)
+HRESULT CHashCallbackGUI::ScanError(const FString &path, DWORD systemError)
{
- FailedFiles.Add(name);
- AddErrorMessage(systemError, name);
+ AddErrorMessage(systemError, fs2us(path));
return CheckBreak();
}
-HRESULT CHashCallbackGUI::FinishScanning()
+HRESULT CHashCallbackGUI::FinishScanning(const CDirItemsStat &st)
{
- CProgressSync &sync = ProgressDialog.Sync;
- sync.Set_FilePath(L"");
- return CheckBreak();
+ return ScanProgress(st, FString(), false);
}
HRESULT CHashCallbackGUI::CheckBreak()
@@ -139,12 +130,11 @@ HRESULT CHashCallbackGUI::GetStream(const wchar_t *name, bool isFolder)
return CheckBreak();
}
-HRESULT CHashCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError)
+HRESULT CHashCallbackGUI::OpenFileError(const FString &path, DWORD systemError)
{
- FailedFiles.Add(name);
// if (systemError == ERROR_SHARING_VIOLATION)
{
- AddErrorMessage(systemError, name);
+ AddErrorMessage(systemError, fs2us(path));
return S_FALSE;
}
// return systemError;
@@ -159,20 +149,22 @@ HRESULT CHashCallbackGUI::SetOperationResult(UInt64 /* fileSize */, const CHashB
return CheckBreak();
}
-static void AddHashString(UString &s, const CHasherState &h, int digestIndex, const wchar_t *title)
+static void AddHashString(UString &s, const CHasherState &h, unsigned digestIndex, const wchar_t *title)
{
s += title;
- s += L' ';
+ s.Add_Space();
char temp[k_HashCalc_DigestSize_Max * 2 + 4];
AddHashHexToString(temp, h.Digests[digestIndex], h.DigestSize);
- s.AddAsciiStr(temp);
- NewLine(s);
+ s.AddAscii(temp);
+ s.Add_LF();
}
-static void AddHashResString(UString &s, const CHasherState &h, int digestIndex, UInt32 resID)
+static void AddHashResString(UString &s, const CHasherState &h, unsigned digestIndex, UInt32 resID)
{
UString s2 = LangString(resID);
- s2.Replace(L"CRC", h.Name);
+ UString name;
+ name.SetFromAscii(h.Name);
+ s2.Replace(L"CRC", name);
AddHashString(s, h, digestIndex, s2);
}
@@ -181,14 +173,14 @@ void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFil
if (hb.NumErrors != 0)
{
AddValuePair(s, IDS_PROP_NUM_ERRORS, hb.NumErrors);
- NewLine(s);
+ s.Add_LF();
}
if (hb.NumFiles == 1 && hb.NumDirs == 0 && !firstFileName.IsEmpty())
{
- s += LangString(IDS_PROP_NAME);
- s += L": ";
+ AddLangString(s, IDS_PROP_NAME);
+ s.AddAscii(": ");
s += firstFileName;
- NewLine(s);
+ s.Add_LF();
}
else
{
@@ -200,23 +192,23 @@ void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFil
if (hb.NumAltStreams != 0)
{
- NewLine(s);
+ s.Add_LF();
AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, hb.NumAltStreams);
AddSizeValuePair(s, IDS_PROP_ALT_STREAMS_SIZE, hb.AltStreamsSize);
}
FOR_VECTOR (i, hb.Hashers)
{
- NewLine(s);
+ s.Add_LF();
const CHasherState &h = hb.Hashers[i];
if (hb.NumFiles == 1 && hb.NumDirs == 0)
{
- s += h.Name;
+ s.AddAscii(h.Name);
AddHashString(s, h, k_HashCalc_Index_DataSum, L":");
}
else
{
- AddHashResString(s, h, k_HashCalc_Index_DataSum, IDS_CHECKSUM_CRC_DATA);
+ AddHashResString(s, h, k_HashCalc_Index_DataSum, IDS_CHECKSUM_CRC_DATA);
AddHashResString(s, h, k_HashCalc_Index_NamesSum, IDS_CHECKSUM_CRC_DATA_NAMES);
}
if (hb.NumAltStreams != 0)
@@ -245,7 +237,7 @@ HRESULT CHashCallbackGUI::ProcessVirt()
{
NumFiles = 0;
- UString errorInfo;
+ AString errorInfo;
HRESULT res = HashCalc(EXTERNAL_CODECS_LOC_VARS
*censor, *options, errorInfo, this);
@@ -270,7 +262,8 @@ HRESULT HashCalcGUI(
const UString title = LangString(IDS_CHECKSUM_CALCULATING);
t.ProgressDialog.MainTitle = L"7-Zip"; // LangString(IDS_APP_TITLE);
- t.ProgressDialog.MainAddTitle = title + L' ';
+ t.ProgressDialog.MainAddTitle = title;
+ t.ProgressDialog.MainAddTitle.Add_Space();
RINOK(t.Create(title));
messageWasDisplayed = t.ThreadFinishedOK && t.ProgressDialog.MessagesDisplayed;
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
index 36af147b..240f4880 100644
--- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
+++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
@@ -7,7 +7,7 @@
#include "../../../Windows/PropVariant.h"
-#include "../FileManager/PasswordDialog.h"
+#include "../FileManager/FormatUtils.h"
#include "../FileManager/LangUtils.h"
#include "../FileManager/resourceGUI.h"
@@ -18,29 +18,26 @@
using namespace NWindows;
-CUpdateCallbackGUI::~CUpdateCallbackGUI() {}
+// CUpdateCallbackGUI::~CUpdateCallbackGUI() {}
void CUpdateCallbackGUI::Init()
{
+ CUpdateCallbackGUI2::Init();
FailedFiles.Clear();
- NumFiles = 0;
}
-HRESULT CUpdateCallbackGUI::OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType)
+void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result);
+
+HRESULT CUpdateCallbackGUI::OpenResult(
+ const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)
{
- if (result != S_OK)
+ UString s;
+ OpenResult_GUI(s, codecs, arcLink, name, result);
+ if (!s.IsEmpty())
{
- UString s;
- if (errorArcType)
- {
- s += L"Can not open the file as [";
- s += errorArcType;
- s += L"] archive";
- }
- else
- s += L"The file is not supported archive";
- ProgressDialog->Sync.AddError_Message_Name(s, name);
+ ProgressDialog->Sync.AddError_Message(s);
}
+
return S_OK;
}
@@ -51,16 +48,18 @@ HRESULT CUpdateCallbackGUI::StartScanning()
return S_OK;
}
-HRESULT CUpdateCallbackGUI::CanNotFindError(const wchar_t *name, DWORD systemError)
+HRESULT CUpdateCallbackGUI::ScanError(const FString &path, DWORD systemError)
{
- FailedFiles.Add(name);
- ProgressDialog->Sync.AddError_Code_Name(systemError, name);
+ FailedFiles.Add(path);
+ ProgressDialog->Sync.AddError_Code_Name(systemError, fs2us(path));
return S_OK;
}
-HRESULT CUpdateCallbackGUI::FinishScanning()
+HRESULT CUpdateCallbackGUI::FinishScanning(const CDirItemsStat &st)
{
CProgressSync &sync = ProgressDialog->Sync;
+ RINOK(ProgressDialog->Sync.ScanProgress(st.NumFiles + st.NumAltStreams,
+ st.GetTotalBytes(), FString(), true));
sync.Set_Status(L"");
return S_OK;
}
@@ -73,7 +72,7 @@ HRESULT CUpdateCallbackGUI::StartArchive(const wchar_t *name, bool /* updating *
return S_OK;
}
-HRESULT CUpdateCallbackGUI::FinishArchive()
+HRESULT CUpdateCallbackGUI::FinishArchive(const CFinishArchiveStat & /* st */)
{
CProgressSync &sync = ProgressDialog->Sync;
sync.Set_Status(L"");
@@ -85,19 +84,22 @@ HRESULT CUpdateCallbackGUI::CheckBreak()
return ProgressDialog->Sync.CheckStop();
}
-HRESULT CUpdateCallbackGUI::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)
+HRESULT CUpdateCallbackGUI::ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir)
{
- return ProgressDialog->Sync.ScanProgress(numFiles, totalSize, path, isDir);
+ return ProgressDialog->Sync.ScanProgress(st.NumFiles + st.NumAltStreams,
+ st.GetTotalBytes(), path, isDir);
}
-HRESULT CUpdateCallbackGUI::Finilize()
+/*
+HRESULT CUpdateCallbackGUI::Finalize()
{
return S_OK;
}
+*/
-HRESULT CUpdateCallbackGUI::SetNumFiles(UInt64 numFiles)
+HRESULT CUpdateCallbackGUI::SetNumItems(UInt64 numItems)
{
- ProgressDialog->Sync.Set_NumFilesTotal(numFiles);
+ ProgressDialog->Sync.Set_NumFilesTotal(numItems);
return S_OK;
}
@@ -118,18 +120,17 @@ HRESULT CUpdateCallbackGUI::SetRatioInfo(const UInt64 *inSize, const UInt64 *out
return CheckBreak();
}
-HRESULT CUpdateCallbackGUI::GetStream(const wchar_t *name, bool /* isAnti */)
+HRESULT CUpdateCallbackGUI::GetStream(const wchar_t *name, bool isDir, bool /* isAnti */, UInt32 mode)
{
- ProgressDialog->Sync.Set_FilePath(name);
- return S_OK;
+ return SetOperation_Base(mode, name, isDir);
}
-HRESULT CUpdateCallbackGUI::OpenFileError(const wchar_t *name, DWORD systemError)
+HRESULT CUpdateCallbackGUI::OpenFileError(const FString &path, DWORD systemError)
{
- FailedFiles.Add(name);
+ FailedFiles.Add(path);
// if (systemError == ERROR_SHARING_VIOLATION)
{
- ProgressDialog->Sync.AddError_Code_Name(systemError, name);
+ ProgressDialog->Sync.AddError_Code_Name(systemError, fs2us(path));
return S_FALSE;
}
// return systemError;
@@ -142,22 +143,37 @@ HRESULT CUpdateCallbackGUI::SetOperationResult(Int32 /* operationResult */)
return S_OK;
}
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);
+
+HRESULT CUpdateCallbackGUI::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
+{
+ if (opRes != NArchive::NExtract::NOperationResult::kOK)
+ {
+ UString s;
+ SetExtractErrorMessage(opRes, isEncrypted, name, s);
+ ProgressDialog->Sync.AddError_Message(s);
+ }
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir)
+{
+ return SetOperation_Base(op, name, isDir);
+}
+
HRESULT CUpdateCallbackGUI::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
*password = NULL;
+ if (passwordIsDefined)
+ *passwordIsDefined = BoolToInt(PasswordIsDefined);
if (!PasswordIsDefined)
{
- if (passwordIsDefined == 0 || AskPassword)
+ if (AskPassword)
{
- CPasswordDialog dialog;
- ProgressDialog->WaitCreating();
- if (dialog.Create(*ProgressDialog) != IDOK)
- return E_ABORT;
- Password = dialog.Password;
- PasswordIsDefined = true;
+ RINOK(ShowAskPasswordDialog())
}
}
- if (passwordIsDefined != 0)
+ if (passwordIsDefined)
*passwordIsDefined = BoolToInt(PasswordIsDefined);
return StringToBstr(Password, password);
}
@@ -201,6 +217,7 @@ HRESULT CUpdateCallbackGUI::Open_CryptoGetTextPassword(BSTR *password)
return CryptoGetTextPassword2(NULL, password);
}
+/*
HRESULT CUpdateCallbackGUI::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
{
passwordIsDefined = PasswordIsDefined;
@@ -213,17 +230,51 @@ bool CUpdateCallbackGUI::Open_WasPasswordAsked()
return PasswordWasAsked;
}
-void CUpdateCallbackGUI::Open_ClearPasswordWasAskedFlag()
+void CUpdateCallbackGUI::Open_Clear_PasswordWasAsked_Flag()
{
PasswordWasAsked = false;
}
+*/
-/*
-HRESULT CUpdateCallbackGUI::ShowDeleteFile(const wchar_t *name)
+HRESULT CUpdateCallbackGUI::ShowDeleteFile(const wchar_t *name, bool isDir)
{
- ProgressDialog->Sync.SetCurrentFileName(name);
+ return SetOperation_Base(NUpdateNotifyOp::kDelete, name, isDir);
+}
+
+HRESULT CUpdateCallbackGUI::FinishDeletingAfterArchiving()
+{
+ // ClosePercents2();
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::DeletingAfterArchiving(const FString &path, bool isDir)
+{
+ return ProgressDialog->Sync.Set_Status2(_lang_Removing, fs2us(path), isDir);
+}
+
+HRESULT CUpdateCallbackGUI::StartOpenArchive(const wchar_t * /* name */)
+{
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::ReadingFileError(const FString &path, DWORD systemError)
+{
+ FailedFiles.Add(path);
+ ProgressDialog->Sync.AddError_Code_Name(systemError, fs2us(path));
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::WriteSfx(const wchar_t * /* name */, UInt64 /* size */)
+{
+ CProgressSync &sync = ProgressDialog->Sync;
+ sync.Set_Status(L"WriteSfx");
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackGUI::Open_Finished()
+{
+ // ClosePercents();
return S_OK;
}
-*/
#endif
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h
index 21b6f432..2e0c111b 100644
--- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.h
+++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.h
@@ -5,34 +5,30 @@
#include "../Common/Update.h"
#include "../Common/ArchiveOpenCallback.h"
-#include "../FileManager/ProgressDialog2.h"
+
+#include "UpdateCallbackGUI2.h"
class CUpdateCallbackGUI:
public IOpenCallbackUI,
- public IUpdateCallbackUI2
+ public IUpdateCallbackUI2,
+ public CUpdateCallbackGUI2
{
public:
- bool PasswordIsDefined;
- UString Password;
+ // CUpdateCallbackGUI();
+ // ~CUpdateCallbackGUI();
+
bool AskPassword;
- bool PasswordWasAsked;
- UInt64 NumFiles;
+
+ void Init();
CUpdateCallbackGUI():
- PasswordIsDefined(false),
- PasswordWasAsked(false),
AskPassword(false)
{}
-
- ~CUpdateCallbackGUI();
- void Init();
INTERFACE_IUpdateCallbackUI2(;)
INTERFACE_IOpenCallbackUI(;)
- UStringVector FailedFiles;
-
- CProgressDialog *ProgressDialog;
+ FStringVector FailedFiles;
};
#endif
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp
new file mode 100644
index 00000000..4eeead7d
--- /dev/null
+++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.cpp
@@ -0,0 +1,59 @@
+// UpdateCallbackGUI2.cpp
+
+#include "StdAfx.h"
+
+#include "../FileManager/LangUtils.h"
+#include "../FileManager/PasswordDialog.h"
+
+#include "resource2.h"
+#include "resource3.h"
+#include "ExtractRes.h"
+
+#include "UpdateCallbackGUI.h"
+
+using namespace NWindows;
+
+static const UINT k_UpdNotifyLangs[] =
+{
+ IDS_PROGRESS_ADD,
+ IDS_PROGRESS_UPDATE,
+ IDS_PROGRESS_ANALYZE,
+ IDS_PROGRESS_REPLICATE,
+ IDS_PROGRESS_REPACK,
+ IDS_PROGRESS_SKIPPING,
+ IDS_PROGRESS_DELETE,
+ IDS_PROGRESS_HEADER
+};
+
+void CUpdateCallbackGUI2::Init()
+{
+ NumFiles = 0;
+
+ _lang_Removing = LangString(IDS_PROGRESS_REMOVE);
+ _lang_Ops.Clear();
+ for (unsigned i = 0; i < ARRAY_SIZE(k_UpdNotifyLangs); i++)
+ _lang_Ops.Add(LangString(k_UpdNotifyLangs[i]));
+}
+
+HRESULT CUpdateCallbackGUI2::SetOperation_Base(UInt32 notifyOp, const wchar_t *name, bool isDir)
+{
+ const UString *s = NULL;
+ if (notifyOp < _lang_Ops.Size())
+ s = &(_lang_Ops[(unsigned)notifyOp]);
+ else
+ s = &_emptyString;
+
+ return ProgressDialog->Sync.Set_Status2(*s, name, isDir);
+}
+
+
+HRESULT CUpdateCallbackGUI2::ShowAskPasswordDialog()
+{
+ CPasswordDialog dialog;
+ ProgressDialog->WaitCreating();
+ if (dialog.Create(*ProgressDialog) != IDOK)
+ return E_ABORT;
+ Password = dialog.Password;
+ PasswordIsDefined = true;
+ return S_OK;
+}
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h
new file mode 100644
index 00000000..2b30ad21
--- /dev/null
+++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI2.h
@@ -0,0 +1,35 @@
+// UpdateCallbackGUI2.h
+
+#ifndef __UPDATE_CALLBACK_GUI2_H
+#define __UPDATE_CALLBACK_GUI2_H
+
+#include "../FileManager/ProgressDialog2.h"
+
+class CUpdateCallbackGUI2
+{
+ UStringVector _lang_Ops;
+ UString _emptyString;
+public:
+ UString Password;
+ bool PasswordIsDefined;
+ bool PasswordWasAsked;
+ UInt64 NumFiles;
+
+ UString _lang_Removing;
+
+ CUpdateCallbackGUI2():
+ PasswordIsDefined(false),
+ PasswordWasAsked(false),
+ NumFiles(0)
+ {}
+
+ // ~CUpdateCallbackGUI2();
+ void Init();
+
+ CProgressDialog *ProgressDialog;
+
+ HRESULT SetOperation_Base(UInt32 notifyOp, const wchar_t *name, bool isDir);
+ HRESULT ShowAskPasswordDialog();
+};
+
+#endif
diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp
index a7af4e94..64501306 100644
--- a/CPP/7zip/UI/GUI/UpdateGUI.cpp
+++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp
@@ -6,7 +6,7 @@
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
-// #include "../../../Windows/Error.h"
+#include "../../../Windows/DLL.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/Thread.h"
@@ -54,9 +54,8 @@ HRESULT CThreadUpdating::ProcessVirt()
HRESULT res = UpdateArchive(codecs, *formatIndices, *cmdArcPath,
*WildcardCensor, *Options,
ei, UpdateCallbackGUI, UpdateCallbackGUI, needSetPath);
- FinalMessage.ErrorMessage.Message = ei.Message;
- SetErrorPath1(ei.FileName);
- SetErrorPath2(ei.FileName2);
+ FinalMessage.ErrorMessage.Message.SetFromAscii(ei.Message);
+ ErrorPaths = ei.FileNames;
if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT)
return ei.SystemError;
return res;
@@ -260,7 +259,7 @@ static HRESULT ShowDialog(
FOR_VECTOR (i, item.PathParts)
{
if (i > 0)
- name += WCHAR_PATH_SEPARATOR;
+ name.Add_PathSepar();
name += item.PathParts[i];
}
if (fileInfo.Find(us2fs(name)))
@@ -306,8 +305,8 @@ static HRESULT ShowDialog(
if (!oneFile && ai.Flags_KeepName())
continue;
if ((int)i != di.FormatIndex)
- if (ai.Name.IsEqualToNoCase(L"swfc"))
- if (!oneFile || name.Len() < 4 || !StringsAreEqualNoCase(name.RightPtr(4), L".swf"))
+ if (ai.Name.IsEqualTo_Ascii_NoCase("swfc"))
+ if (!oneFile || name.Len() < 4 || !StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".swf"))
continue;
dialog.ArcIndices.Add(i);
}
@@ -387,7 +386,7 @@ static HRESULT ShowDialog(
options.MethodMode.Properties.Clear();
- bool is7z = archiverInfo.Name.IsEqualToNoCase(L"7z");
+ bool is7z = archiverInfo.Name.IsEqualTo_Ascii_NoCase("7z");
bool methodOverride = IsThereMethodOverride(is7z, di.Options);
SetOutProperties(
diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile
index 60cfcd4b..bcafa0e5 100644
--- a/CPP/7zip/UI/GUI/makefile
+++ b/CPP/7zip/UI/GUI/makefile
@@ -18,6 +18,7 @@ GUI_OBJS = \
$O\GUI.obj \
$O\HashGUI.obj \
$O\UpdateCallbackGUI.obj \
+ $O\UpdateCallbackGUI2.obj \
$O\UpdateGUI.obj \
COMMON_OBJS = \
@@ -107,6 +108,7 @@ FM_OBJS = \
$O\LangUtils.obj \
$O\OpenCallback.obj \
$O\ProgramLocation.obj \
+ $O\PropertyName.obj \
$O\RegistryUtils.obj \
$O\SplitUtils.obj \
$O\StringUtils.obj \
diff --git a/CPP/7zip/UI/GUI/resource.rc b/CPP/7zip/UI/GUI/resource.rc
index 0f7c6235..13a09c64 100644
--- a/CPP/7zip/UI/GUI/resource.rc
+++ b/CPP/7zip/UI/GUI/resource.rc
@@ -2,6 +2,8 @@
// #include <winnt.h>
#include "resource2.rc"
+#include "resource3.rc"
+
#include "../FileManager/resourceGui.rc"
MY_VERSION_INFO(MY_VFT_APP, "7-Zip GUI", "7zg", "7zg.exe")
diff --git a/CPP/7zip/UI/GUI/resource3.h b/CPP/7zip/UI/GUI/resource3.h
new file mode 100644
index 00000000..1758d525
--- /dev/null
+++ b/CPP/7zip/UI/GUI/resource3.h
@@ -0,0 +1,10 @@
+#define IDS_PROGRESS_REMOVE 3305
+
+#define IDS_PROGRESS_ADD 3320
+#define IDS_PROGRESS_UPDATE 3321
+#define IDS_PROGRESS_ANALYZE 3322
+#define IDS_PROGRESS_REPLICATE 3323
+#define IDS_PROGRESS_REPACK 3324
+
+#define IDS_PROGRESS_DELETE 3326
+#define IDS_PROGRESS_HEADER 3327
diff --git a/CPP/7zip/UI/GUI/resource3.rc b/CPP/7zip/UI/GUI/resource3.rc
new file mode 100644
index 00000000..cfc8bc35
--- /dev/null
+++ b/CPP/7zip/UI/GUI/resource3.rc
@@ -0,0 +1,15 @@
+#include "resource3.h"
+
+STRINGTABLE
+BEGIN
+ IDS_PROGRESS_REMOVE "Removing"
+
+ IDS_PROGRESS_ADD "Adding"
+ IDS_PROGRESS_UPDATE "Updating"
+ IDS_PROGRESS_ANALYZE "Analyzing"
+ IDS_PROGRESS_REPLICATE "Replicating"
+ IDS_PROGRESS_REPACK "Repacking"
+
+ IDS_PROGRESS_DELETE "Deleting"
+ IDS_PROGRESS_HEADER "Header creating"
+END
diff --git a/CPP/Build.mak b/CPP/Build.mak
index df600eb8..ef0ed0c4 100644
--- a/CPP/Build.mak
+++ b/CPP/Build.mak
@@ -42,7 +42,7 @@ COMPL_ASM = $(MY_ML) $** $O/$(*B).obj
COMPL_ASM = $(MY_ML) -c -Fo$O/ $**
!ENDIF
-CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR-
+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR- -GF
!IFDEF MY_STATIC_LINK
!IFNDEF MY_SINGLE_THREAD
diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
index 1bf41736..1c7f2654 100644
--- a/CPP/Common/CommandLineParser.cpp
+++ b/CPP/Common/CommandLineParser.cpp
@@ -11,7 +11,7 @@ static bool IsString1PrefixedByString2_NoCase(const wchar_t *u, const char *a)
char c = *a;
if (c == 0)
return true;
- if (MyCharLower_Ascii(c) != MyCharLower_Ascii(*u))
+ if ((unsigned char)MyCharLower_Ascii(c) != MyCharLower_Ascii(*u))
return false;
a++;
u++;
@@ -135,24 +135,28 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
switch (form.Type)
{
case NSwitchType::kMinus:
- if (rem != 0)
+ if (rem == 1)
{
sw.WithMinus = (s[pos] == '-');
if (sw.WithMinus)
- pos++;
+ return true;
+ ErrorMessage = "Incorrect switch postfix:";
+ return false;
}
break;
case NSwitchType::kChar:
- if (rem != 0)
+ if (rem == 1)
{
wchar_t c = s[pos];
if (c <= 0x7F)
{
sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
if (sw.PostCharIndex >= 0)
- pos++;
+ return true;
}
+ ErrorMessage = "Incorrect switch postfix:";
+ return false;
}
break;
@@ -160,6 +164,7 @@ bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
sw.PostStrings.Add((const wchar_t *)s + pos);
return true;
}
+
if (pos != s.Len())
{
ErrorMessage = "Too long switch:";
diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp
index 6f4de495..2c343b31 100644
--- a/CPP/Common/CrcReg.cpp
+++ b/CPP/Common/CrcReg.cpp
@@ -7,22 +7,17 @@
#include "../Common/MyCom.h"
-#include "../7zip/ICoder.h"
#include "../7zip/Common/RegisterCodec.h"
EXTERN_C_BEGIN
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
-extern CRC_FUNC g_CrcUpdate;
-
-#ifdef MY_CPU_X86_OR_AMD64
- UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
-#endif
+UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table);
-#ifndef MY_CPU_BE
- UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
-#endif
+extern CRC_FUNC g_CrcUpdate;
+extern CRC_FUNC g_CrcUpdateT8;
+extern CRC_FUNC g_CrcUpdateT4;
EXTERN_C_END
@@ -33,62 +28,42 @@ class CCrcHasher:
{
UInt32 _crc;
CRC_FUNC _updateFunc;
+ Byte mtDummy[1 << 7];
+
bool SetFunctions(UInt32 tSize);
public:
CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); }
MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
-
- STDMETHOD_(void, Init)();
- STDMETHOD_(void, Update)(const void *data, UInt32 size);
- STDMETHOD_(void, Final)(Byte *digest);
- STDMETHOD_(UInt32, GetDigestSize)();
+ INTERFACE_IHasher(;)
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
};
-STDMETHODIMP_(void) CCrcHasher::Init()
-{
- _crc = CRC_INIT_VAL;
-}
-
-STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size)
-{
- _crc = _updateFunc(_crc, data, size, g_CrcTable);
-}
-
-STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest)
-{
- UInt32 val = CRC_GET_DIGEST(_crc);
- SetUi32(digest, val);
-}
-
-STDMETHODIMP_(UInt32) CCrcHasher::GetDigestSize()
-{
- return 4;
-}
-
bool CCrcHasher::SetFunctions(UInt32 tSize)
{
_updateFunc = g_CrcUpdate;
- if (tSize == 4)
+
+ if (tSize == 1)
+ _updateFunc = CrcUpdateT1;
+ else if (tSize == 4)
{
- #ifndef MY_CPU_BE
- _updateFunc = CrcUpdateT4;
- #endif
+ if (g_CrcUpdateT4)
+ _updateFunc = g_CrcUpdateT4;
+ else
+ return false;
}
else if (tSize == 8)
{
- #ifdef MY_CPU_X86_OR_AMD64
- _updateFunc = CrcUpdateT8;
- #else
+ if (g_CrcUpdateT8)
+ _updateFunc = g_CrcUpdateT8;
+ else
return false;
- #endif
}
+
return true;
}
-STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs,
- const PROPVARIANT *coderProps, UInt32 numProps)
+STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
{
for (UInt32 i = 0; i < numProps; i++)
{
@@ -104,8 +79,20 @@ STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs,
return S_OK;
}
-static IHasher *CreateHasher() { return new CCrcHasher(); }
+STDMETHODIMP_(void) CCrcHasher::Init() throw()
+{
+ _crc = CRC_INIT_VAL;
+}
+
+STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size) throw()
+{
+ _crc = _updateFunc(_crc, data, size, g_CrcTable);
+}
-static CHasherInfo g_HasherInfo = { CreateHasher, 0x1, L"CRC32", 4 };
+STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest) throw()
+{
+ UInt32 val = CRC_GET_DIGEST(_crc);
+ SetUi32(digest, val);
+}
-REGISTER_HASHER(Crc32)
+REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4)
diff --git a/CPP/Common/DynLimBuf.h b/CPP/Common/DynLimBuf.h
index 035fc272..962f2e61 100644
--- a/CPP/Common/DynLimBuf.h
+++ b/CPP/Common/DynLimBuf.h
@@ -18,6 +18,10 @@ class CDynLimBuf
bool _error;
CDynLimBuf(const CDynLimBuf &s);
+
+ // ---------- forbidden functions ----------
+ CDynLimBuf &operator+=(wchar_t c);
+
public:
CDynLimBuf(size_t limit) throw();
~CDynLimBuf() { MyFree(_chars); }
@@ -29,7 +33,7 @@ public:
// const char *Ptr() const { return _chars; }
CDynLimBuf &operator+=(char c) throw();
- CDynLimBuf &operator+=(const char *s) throw();
+ CDynLimBuf &operator+=(const char *s) throw();
};
diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h
index cd23ad73..44e3df7f 100644
--- a/CPP/Common/DynamicBuffer.h
+++ b/CPP/Common/DynamicBuffer.h
@@ -26,7 +26,8 @@ template <class T> class CDynamicBuffer
}
T *newBuffer = new T[newCap];
- memcpy(newBuffer, _items, _pos * sizeof(T));
+ if (_pos != 0)
+ memcpy(newBuffer, _items, _pos * sizeof(T));
delete []_items;
_items = newBuffer;
_size = newCap;
@@ -34,8 +35,8 @@ template <class T> class CDynamicBuffer
public:
CDynamicBuffer(): _items(0), _size(0), _pos(0) {}
- // operator T *() { return _items; };
- operator const T *() const { return _items; };
+ // operator T *() { return _items; }
+ operator const T *() const { return _items; }
~CDynamicBuffer() { delete []_items; }
T *GetCurPtrAndGrow(size_t addSize)
@@ -48,6 +49,11 @@ public:
return res;
}
+ void AddData(const T *data, size_t size)
+ {
+ memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T));
+ }
+
const size_t GetPos() const { return _pos; }
// void Empty() { _pos = 0; }
diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp
index 64e561a3..8c525cf7 100644
--- a/CPP/Common/Lang.cpp
+++ b/CPP/Common/Lang.cpp
@@ -120,15 +120,17 @@ bool CLang::Open(CFSTR fileName, const wchar_t *id)
return false;
if (length > (1 << 20))
return false;
+
AString s;
unsigned len = (unsigned)length;
- char *p = s.GetBuffer(len);
+ char *p = s.GetBuf(len);
UInt32 processed;
if (!file.Read(p, len, processed))
return false;
file.Close();
if (len != processed)
return false;
+
char *p2 = p;
for (unsigned i = 0; i < len; i++)
{
@@ -138,13 +140,16 @@ bool CLang::Open(CFSTR fileName, const wchar_t *id)
if (c != 0x0D)
*p2++ = c;
}
- s.ReleaseBuffer((unsigned)(p2 - p));
+ *p2 = 0;
+ s.ReleaseBuf_SetLen((unsigned)(p2 - p));
+
if (OpenFromString(s))
{
- const wchar_t *s = Get(0);
- if (s && wcscmp(s, id) == 0)
+ const wchar_t *name = Get(0);
+ if (name && wcscmp(name, id) == 0)
return true;
}
+
Clear();
return false;
}
diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h
index 2ca2a850..22e42574 100644
--- a/CPP/Common/Lang.h
+++ b/CPP/Common/Lang.h
@@ -14,7 +14,7 @@ class CLang
bool OpenFromString(const AString &s);
public:
CLang(): _text(0) {}
- ~CLang() { Clear(); };
+ ~CLang() { Clear(); }
bool Open(CFSTR fileName, const wchar_t *id);
void Clear() throw();
const wchar_t *Get(UInt32 id) const throw();
diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp
index 313532ef..3bf4ec29 100644
--- a/CPP/Common/ListFileUtils.cpp
+++ b/CPP/Common/ListFileUtils.cpp
@@ -48,7 +48,7 @@ bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage
return false;
file.Close();
unsigned num = (unsigned)fileSize / 2;
- wchar_t *p = u.GetBuffer(num);
+ wchar_t *p = u.GetBuf(num);
if (codePage == MY__CP_UTF16)
for (unsigned i = 0; i < num; i++)
{
@@ -65,20 +65,20 @@ bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage
return false;
p[i] = c;
}
- u.ReleaseBuffer(num);
+ p[num] = 0;
+ u.ReleaseBuf_SetLen(num);
}
else
{
AString s;
- char *p = s.GetBuffer((unsigned)fileSize);
+ char *p = s.GetBuf((unsigned)fileSize);
UInt32 processed;
if (!file.Read(p, (UInt32)fileSize, processed))
return false;
if (processed != fileSize)
return false;
file.Close();
- p[processed] = 0;
- s.ReleaseBuffer();
+ s.ReleaseBuf_CalcLen((unsigned)processed);
if (s.Len() != processed)
return false;
diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h
index 27c188c7..58caa2ff 100644
--- a/CPP/Common/MyBuffer.h
+++ b/CPP/Common/MyBuffer.h
@@ -10,15 +10,6 @@ template <class T> class CBuffer
T *_items;
size_t _size;
- void CopyToEmpty(const CBuffer &buffer)
- {
- if (buffer._size > 0)
- {
- _items = new T[buffer._size];
- memcpy(_items, buffer._items, buffer._size * sizeof(T));
- _size = buffer._size;
- }
- }
public:
void Free()
{
@@ -32,11 +23,21 @@ public:
CBuffer(): _items(0), _size(0) {};
CBuffer(size_t size): _items(0), _size(0) { _items = new T[size]; _size = size; }
- CBuffer(const CBuffer &buffer): _items(0), _size(0) { CopyToEmpty(buffer); }
+ CBuffer(const CBuffer &buffer): _items(0), _size(0)
+ {
+ size_t size = buffer._size;
+ if (size != 0)
+ {
+ _items = new T[size];
+ memcpy(_items, buffer._items, size * sizeof(T));
+ _size = size;
+ }
+ }
+
~CBuffer() { delete []_items; }
- operator T *() { return _items; };
- operator const T *() const { return _items; };
+ operator T *() { return _items; }
+ operator const T *() const { return _items; }
size_t Size() const { return _size; }
void Alloc(size_t size)
@@ -65,7 +66,8 @@ public:
void CopyFrom(const T *data, size_t size)
{
Alloc(size);
- memcpy(_items, data, size * sizeof(T));
+ if (size != 0)
+ memcpy(_items, data, size * sizeof(T));
}
void ChangeSize_KeepData(size_t newSize, size_t keepSize)
@@ -73,10 +75,10 @@ public:
if (newSize == _size)
return;
T *newBuffer = NULL;
- if (newSize > 0)
+ if (newSize != 0)
{
newBuffer = new T[newSize];
- if (_size > 0)
+ if (_size != 0)
memcpy(newBuffer, _items, MyMin(MyMin(_size, keepSize), newSize) * sizeof(T));
}
delete []_items;
@@ -86,8 +88,8 @@ public:
CBuffer& operator=(const CBuffer &buffer)
{
- Free();
- CopyToEmpty(buffer);
+ if (&buffer != this)
+ CopyFrom(buffer, buffer._size);
return *this;
}
};
@@ -98,6 +100,8 @@ bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)
size_t size1 = b1.Size();
if (size1 != b2.Size())
return false;
+ if (size1 == 0)
+ return true;
return memcmp(b1, b2, size1 * sizeof(T)) == 0;
}
@@ -107,6 +111,8 @@ bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
size_t size1 = b1.Size();
if (size1 == b2.Size())
return false;
+ if (size1 == 0)
+ return false;
return memcmp(b1, b2, size1 * sizeof(T)) != 0;
}
@@ -134,8 +140,8 @@ public:
CObjArray(): _items(0) {};
~CObjArray() { delete []_items; }
- operator T *() { return _items; };
- operator const T *() const { return _items; };
+ operator T *() { return _items; }
+ operator const T *() const { return _items; }
void Alloc(size_t newSize)
{
@@ -172,7 +178,7 @@ public:
CObjArray2(const CObjArray2 &buffer): _items(0), _size(0)
{
size_t newSize = buffer._size;
- if (newSize > 0)
+ if (newSize != 0)
{
T *newBuffer = new T[newSize];;
_items = newBuffer;
@@ -196,8 +202,8 @@ public:
~CObjArray2() { delete []_items; }
- operator T *() { return _items; };
- operator const T *() const { return _items; };
+ operator T *() { return _items; }
+ operator const T *() const { return _items; }
unsigned Size() const { return (unsigned)_size; }
bool IsEmpty() const { return _size == 0; }
@@ -208,7 +214,7 @@ public:
if (size == _size)
return;
T *newBuffer = NULL;
- if (size > 0)
+ if (size != 0)
newBuffer = new T[size];
delete []_items;
_items = newBuffer;
@@ -220,7 +226,7 @@ public:
{
Free();
size_t newSize = buffer._size;
- if (newSize > 0)
+ if (newSize != 0)
{
T *newBuffer = new T[newSize];;
_items = newBuffer;
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
index 9e2576e3..7c725c91 100644
--- a/CPP/Common/MyCom.h
+++ b/CPP/Common/MyCom.h
@@ -76,19 +76,28 @@ public:
inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
{
*bstr = ::SysAllocString(src);
- return (*bstr != NULL) ? S_OK : E_OUTOFMEMORY;
+ return (*bstr) ? S_OK : E_OUTOFMEMORY;
}
class CMyComBSTR
{
BSTR m_str;
+
public:
-
CMyComBSTR(): m_str(NULL) {}
+ ~CMyComBSTR() { ::SysFreeString(m_str); }
+ BSTR* operator&() { return &m_str; }
+ operator LPCOLESTR() const { return m_str; }
+ // operator bool() const { return m_str != NULL; }
+ // bool operator!() const { return m_str == NULL; }
+private:
+ // operator BSTR() const { return m_str; }
+
CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
// CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
// CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); }
CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
+
/*
CMyComBSTR(REFGUID src)
{
@@ -98,7 +107,7 @@ public:
CoTaskMemFree(szGuid);
}
*/
- ~CMyComBSTR() { ::SysFreeString(m_str); }
+
CMyComBSTR& operator=(const CMyComBSTR& src)
{
if (m_str != src.m_str)
@@ -109,22 +118,29 @@ public:
}
return *this;
}
+
CMyComBSTR& operator=(LPCOLESTR src)
{
::SysFreeString(m_str);
m_str = ::SysAllocString(src);
return *this;
}
- // unsigned Len() const { return ::SysStringLen(m_str); }
- operator BSTR() const { return m_str; }
- BSTR* operator&() { return &m_str; }
+
+ unsigned Len() const { return ::SysStringLen(m_str); }
+
BSTR MyCopy() const
{
- int byteLen = ::SysStringByteLen(m_str);
+ // We don't support Byte BSTRs here
+ return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
+ /*
+ UINT byteLen = ::SysStringByteLen(m_str);
BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
- memcpy(res, m_str, byteLen);
+ if (res && byteLen != 0 && m_str)
+ memcpy(res, m_str, byteLen);
return res;
+ */
}
+
/*
void Attach(BSTR src) { m_str = src; }
BSTR Detach()
@@ -134,12 +150,12 @@ public:
return s;
}
*/
+
void Empty()
{
::SysFreeString(m_str);
m_str = NULL;
}
- bool operator!() const { return (m_str == NULL); }
};
//////////////////////////////////////////////////////////
@@ -149,6 +165,8 @@ class CMyUnknownImp
public:
ULONG __m_RefCount;
CMyUnknownImp(): __m_RefCount(0) {}
+
+ // virtual ~CMyUnknownImp() {};
};
#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
@@ -164,7 +182,7 @@ public:
MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
MY_QUERYINTERFACE_ENTRY(i)
-#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; AddRef(); return S_OK; }
+#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; ++__m_RefCount; /* AddRef(); */ return S_OK; }
#define MY_ADDREF_RELEASE \
STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \
@@ -239,4 +257,6 @@ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \
MY_QUERYINTERFACE_ENTRY(i7) \
)
+const HRESULT k_My_HRESULT_WritingWasCut = 0x20000010;
+
#endif
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
index a92f8428..f35ed71e 100644
--- a/CPP/Common/MyString.cpp
+++ b/CPP/Common/MyString.cpp
@@ -65,6 +65,17 @@ void MyStringUpper_Ascii(wchar_t *s)
}
*/
+void MyStringLower_Ascii(char *s) throw()
+{
+ for (;;)
+ {
+ char c = *s;
+ if (c == 0)
+ return;
+ *s++ = MyCharLower_Ascii(c);
+ }
+}
+
void MyStringLower_Ascii(wchar_t *s) throw()
{
for (;;)
@@ -272,6 +283,17 @@ bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()
}
}
+bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()
+{
+ for (;;)
+ {
+ wchar_t c2 = *s2++; if (c2 == 0) return true;
+ wchar_t c1 = *s1++;
+ if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2))
+ return false;
+ }
+}
+
// NTFS order: uses upper case
int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()
{
@@ -290,7 +312,8 @@ int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()
}
}
-int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw()
+/*
+int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)
{
for (; num != 0; num--)
{
@@ -307,7 +330,7 @@ int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)
}
return 0;
}
-
+*/
// ---------- AString ----------
@@ -317,15 +340,27 @@ void AString::InsertSpace(unsigned &index, unsigned size)
MoveItems(index + size, index);
}
+#define k_Alloc_Len_Limit 0x40000000
+
void AString::ReAlloc(unsigned newLimit)
{
- if (newLimit < _len || newLimit >= 0x20000000) throw 20130220;
+ if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220;
// MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1);
char *newBuf = MY_STRING_NEW(char, newLimit + 1);
memcpy(newBuf, _chars, (size_t)(_len + 1)); \
MY_STRING_DELETE(_chars);
_chars = newBuf;
+ _limit = newLimit;
+}
+void AString::ReAlloc2(unsigned newLimit)
+{
+ if (newLimit >= k_Alloc_Len_Limit) throw 20130220;
+ // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0);
+ char *newBuf = MY_STRING_NEW(char, newLimit + 1);
+ newBuf[0] = 0;
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
_limit = newLimit;
}
@@ -477,6 +512,63 @@ AString &AString::operator=(const AString &s)
return *this;
}
+void AString::SetFromWStr_if_Ascii(const wchar_t *s)
+{
+ unsigned len = 0;
+ {
+ for (;; len++)
+ {
+ wchar_t c = s[len];
+ if (c == 0)
+ break;
+ if (c >= 0x80)
+ return;
+ }
+ }
+ if (len > _limit)
+ {
+ char *newBuf = MY_STRING_NEW(char, len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ char *dest = _chars;
+ unsigned i;
+ for (i = 0; i < len; i++)
+ dest[i] = (char)s[i];
+ dest[i] = 0;
+}
+
+/*
+void AString::SetFromBstr_if_Ascii(BSTR s)
+{
+ unsigned len = ::SysStringLen(s);
+ {
+ for (unsigned i = 0; i < len; i++)
+ if (s[i] <= 0 || s[i] >= 0x80)
+ return;
+ }
+ if (len > _limit)
+ {
+ char *newBuf = MY_STRING_NEW(char, len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ char *dest = _chars;
+ unsigned i;
+ for (i = 0; i < len; i++)
+ dest[i] = (char)s[i];
+ dest[i] = 0;
+}
+*/
+
+void AString::Add_Space() { operator+=(' '); }
+void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
+void AString::Add_LF() { operator+=('\n'); }
+
AString &AString::operator+=(const char *s)
{
unsigned len = MyStringLen(s);
@@ -503,25 +595,50 @@ void AString::SetFrom(const char *s, unsigned len) // no check
_chars = newBuf;
_limit = len;
}
- memcpy(_chars, s, len);
+ if (len != 0)
+ memcpy(_chars, s, len);
_chars[len] = 0;
_len = len;
}
-int AString::Find(const AString &s, unsigned startIndex) const throw()
+void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check
+{
+ unsigned i;
+ for (i = 0; i < len; i++)
+ if (s[i] == 0)
+ break;
+ SetFrom(s, i);
+}
+
+int AString::Find(const char *s, unsigned startIndex) const throw()
{
- if (s.IsEmpty())
+ const char *fs = strstr(_chars + startIndex, s);
+ if (!fs)
+ return -1;
+ return (int)(fs - _chars);
+
+ /*
+ if (s[0] == 0)
return startIndex;
- for (; startIndex < _len; startIndex++)
+ unsigned len = MyStringLen(s);
+ const char *p = _chars + startIndex;
+ for (;; p++)
{
- unsigned j;
- for (j = 0; j < s._len && startIndex + j < _len; j++)
- if (_chars[startIndex + j] != s._chars[j])
+ const char c = *p;
+ if (c != s[0])
+ {
+ if (c == 0)
+ return -1;
+ continue;
+ }
+ unsigned i;
+ for (i = 1; i < len; i++)
+ if (p[i] != s[i])
break;
- if (j == s._len)
- return (int)startIndex;
+ if (i == len)
+ return (int)(p - _chars);
}
- return -1;
+ */
}
int AString::ReverseFind(char c) const throw()
@@ -539,6 +656,22 @@ int AString::ReverseFind(char c) const throw()
}
}
+int AString::ReverseFind_PathSepar() const throw()
+{
+ if (_len == 0)
+ return -1;
+ const char *p = _chars + _len - 1;
+ for (;;)
+ {
+ char c = *p;
+ if (IS_PATH_SEPAR(c))
+ return (int)(p - _chars);
+ if (p == _chars)
+ return -1;
+ p--;
+ }
+}
+
void AString::TrimLeft() throw()
{
const char *p = _chars;
@@ -559,15 +692,14 @@ void AString::TrimLeft() throw()
void AString::TrimRight() throw()
{
const char *p = _chars;
- int i;
- for (i = _len - 1; i >= 0; i--)
+ unsigned i;
+ for (i = _len; i != 0; i--)
{
- char c = p[i];
+ char c = p[i - 1];
if (c != ' ' && c != '\n' && c != '\t')
break;
}
- i++;
- if ((unsigned)i != _len)
+ if (i != _len)
{
_chars[i] = 0;
_len = i;
@@ -616,19 +748,28 @@ void AString::Insert(unsigned index, const AString &s)
void AString::RemoveChar(char ch) throw()
{
- int pos = Find(ch);
- if (pos < 0)
- return;
- const char *src = _chars;
- char *dest = _chars + pos;
- pos++;
- unsigned len = _len;
- for (; (unsigned)pos < len; pos++)
+ char *src = _chars;
+
+ for (;;)
+ {
+ char c = *src++;
+ if (c == 0)
+ return;
+ if (c == ch)
+ break;
+ }
+
+ char *dest = src - 1;
+
+ for (;;)
{
- char c = src[(unsigned)pos];
+ char c = *src++;
+ if (c == 0)
+ break;
if (c != ch)
*dest++ = c;
}
+
*dest = 0;
_len = (unsigned)(dest - _chars);
}
@@ -645,7 +786,7 @@ void AString::Replace(char oldChar, char newChar) throw()
pos = Find(oldChar, pos);
if (pos < 0)
break;
- _chars[pos] = newChar;
+ _chars[(unsigned)pos] = newChar;
pos++;
// number++;
}
@@ -753,13 +894,23 @@ void UString::InsertSpace(unsigned index, unsigned size)
void UString::ReAlloc(unsigned newLimit)
{
- if (newLimit < _len || newLimit >= 0x20000000) throw 20130221;
+ if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221;
// MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1);
wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1);
wmemcpy(newBuf, _chars, _len + 1);
MY_STRING_DELETE(_chars);
_chars = newBuf;
+ _limit = newLimit;
+}
+void UString::ReAlloc2(unsigned newLimit)
+{
+ if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
+ // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
+ wchar_t *newBuf = MY_STRING_NEW(wchar_t, newLimit + 1);
+ newBuf[0] = 0;
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
_limit = newLimit;
}
@@ -854,14 +1005,15 @@ UString::UString(wchar_t c)
UString::UString(const wchar_t *s)
{
- SetStartLen(MyStringLen(s));
- MyStringCopy(_chars, s);
+ unsigned len = MyStringLen(s);
+ SetStartLen(len);
+ wmemcpy(_chars, s, len + 1);
}
UString::UString(const UString &s)
{
SetStartLen(s._len);
- MyStringCopy(_chars, s._chars);
+ wmemcpy(_chars, s._chars, s._len + 1);
}
UString &UString::operator=(wchar_t c)
@@ -890,7 +1042,7 @@ UString &UString::operator=(const wchar_t *s)
_limit = len;
}
_len = len;
- MyStringCopy(_chars, s);
+ wmemcpy(_chars, s, len + 1);
return *this;
}
@@ -907,15 +1059,44 @@ UString &UString::operator=(const UString &s)
_limit = len;
}
_len = len;
- MyStringCopy(_chars, s._chars);
+ wmemcpy(_chars, s._chars, len + 1);
return *this;
}
+void UString::SetFromBstr(BSTR s)
+{
+ unsigned len = ::SysStringLen(s);
+ if (len > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ // if (s)
+ wmemcpy(_chars, s, len + 1);
+}
+
+void UString::Add_Space() { operator+=(L' '); }
+void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
+
+void UString::Add_LF()
+{
+ if (_limit == _len)
+ Grow_1();
+ unsigned len = _len;
+ wchar_t *chars = _chars;
+ chars[len++] = L'\n';
+ chars[len] = 0;
+ _len = len;
+}
+
UString &UString::operator+=(const wchar_t *s)
{
unsigned len = MyStringLen(s);
Grow(len);
- MyStringCopy(_chars + _len, s);
+ wmemcpy(_chars + _len, s, len + 1);
_len += len;
return *this;
}
@@ -923,7 +1104,7 @@ UString &UString::operator+=(const wchar_t *s)
UString &UString::operator+=(const UString &s)
{
Grow(s._len);
- MyStringCopy(_chars + _len, s._chars);
+ wmemcpy(_chars + _len, s._chars, s._len + 1);
_len += s._len;
return *this;
}
@@ -937,7 +1118,8 @@ void UString::SetFrom(const wchar_t *s, unsigned len) // no check
_chars = newBuf;
_limit = len;
}
- wmemcpy(_chars, s, len);
+ if (len != 0)
+ wmemcpy(_chars, s, len);
_chars[len] = 0;
_len = len;
}
@@ -954,38 +1136,53 @@ void UString::SetFromAscii(const char *s)
}
wchar_t *chars = _chars;
for (unsigned i = 0; i < len; i++)
- chars[i] = s[i];
+ chars[i] = (unsigned char)s[i];
chars[len] = 0;
_len = len;
}
-void UString::AddAsciiStr(const char *s)
+void UString::AddAscii(const char *s)
{
unsigned len = MyStringLen(s);
Grow(len);
wchar_t *chars = _chars + _len;
for (unsigned i = 0; i < len; i++)
- chars[i] = s[i];
+ chars[i] = (unsigned char)s[i];
chars[len] = 0;
_len += len;
}
-int UString::Find(const UString &s, unsigned startIndex) const throw()
+int UString::Find(const wchar_t *s, unsigned startIndex) const throw()
{
- if (s.IsEmpty())
+ const wchar_t *fs = wcsstr(_chars + startIndex, s);
+ if (!fs)
+ return -1;
+ return (int)(fs - _chars);
+
+ /*
+ if (s[0] == 0)
return startIndex;
- for (; startIndex < _len; startIndex++)
+ unsigned len = MyStringLen(s);
+ const wchar_t *p = _chars + startIndex;
+ for (;; p++)
{
- unsigned j;
- for (j = 0; j < s._len && startIndex + j < _len; j++)
- if (_chars[startIndex + j] != s._chars[j])
+ const wchar_t c = *p;
+ if (c != s[0])
+ {
+ if (c == 0)
+ return -1;
+ continue;
+ }
+ unsigned i;
+ for (i = 1; i < len; i++)
+ if (p[i] != s[i])
break;
- if (j == s._len)
- return (int)startIndex;
+ if (i == len)
+ return (int)(p - _chars);
}
- return -1;
+ */
}
int UString::ReverseFind(wchar_t c) const throw()
@@ -1003,6 +1200,22 @@ int UString::ReverseFind(wchar_t c) const throw()
}
}
+int UString::ReverseFind_PathSepar() const throw()
+{
+ if (_len == 0)
+ return -1;
+ const wchar_t *p = _chars + _len - 1;
+ for (;;)
+ {
+ wchar_t c = *p;
+ if (IS_PATH_SEPAR(c))
+ return (int)(p - _chars);
+ if (p == _chars)
+ return -1;
+ p--;
+ }
+}
+
void UString::TrimLeft() throw()
{
const wchar_t *p = _chars;
@@ -1023,15 +1236,14 @@ void UString::TrimLeft() throw()
void UString::TrimRight() throw()
{
const wchar_t *p = _chars;
- int i;
- for (i = _len - 1; i >= 0; i--)
+ unsigned i;
+ for (i = _len; i != 0; i--)
{
- wchar_t c = p[i];
+ wchar_t c = p[i - 1];
if (c != ' ' && c != '\n' && c != '\t')
break;
}
- i++;
- if ((unsigned)i != _len)
+ if (i != _len)
{
_chars[i] = 0;
_len = i;
@@ -1080,19 +1292,28 @@ void UString::Insert(unsigned index, const UString &s)
void UString::RemoveChar(wchar_t ch) throw()
{
- int pos = Find(ch);
- if (pos < 0)
- return;
- const wchar_t *src = _chars;
- wchar_t *dest = _chars + pos;
- pos++;
- unsigned len = _len;
- for (; (unsigned)pos < len; pos++)
+ wchar_t *src = _chars;
+
+ for (;;)
{
- wchar_t c = src[(unsigned)pos];
+ wchar_t c = *src++;
+ if (c == 0)
+ return;
+ if (c == ch)
+ break;
+ }
+
+ wchar_t *dest = src - 1;
+
+ for (;;)
+ {
+ wchar_t c = *src++;
+ if (c == 0)
+ break;
if (c != ch)
*dest++ = c;
}
+
*dest = 0;
_len = (unsigned)(dest - _chars);
}
@@ -1109,7 +1330,7 @@ void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
pos = Find(oldChar, pos);
if (pos < 0)
break;
- _chars[pos] = newChar;
+ _chars[(unsigned)pos] = newChar;
pos++;
// number++;
}
@@ -1166,6 +1387,135 @@ void UString::DeleteFrontal(unsigned num) throw()
}
+// ---------- UString2 ----------
+
+void UString2::ReAlloc2(unsigned newLimit)
+{
+ if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
+ // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
+ _chars = MY_STRING_NEW(wchar_t, newLimit + 1);
+}
+
+void UString2::SetStartLen(unsigned len)
+{
+ _chars = 0;
+ _chars = MY_STRING_NEW(wchar_t, len + 1);
+ _len = len;
+}
+
+
+/*
+UString2::UString2(wchar_t c)
+{
+ SetStartLen(1);
+ _chars[0] = c;
+ _chars[1] = 0;
+}
+*/
+
+UString2::UString2(const wchar_t *s)
+{
+ unsigned len = MyStringLen(s);
+ SetStartLen(len);
+ wmemcpy(_chars, s, len + 1);
+}
+
+UString2::UString2(const UString2 &s): _chars(NULL), _len(0)
+{
+ if (s._chars)
+ {
+ SetStartLen(s._len);
+ wmemcpy(_chars, s._chars, s._len + 1);
+ }
+}
+
+/*
+UString2 &UString2::operator=(wchar_t c)
+{
+ if (1 > _len)
+ {
+ wchar_t *newBuf = MY_STRING_NEW(wchar_t, 1 + 1);
+ if (_chars)
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ }
+ _len = 1;
+ _chars[0] = c;
+ _chars[1] = 0;
+ return *this;
+}
+*/
+
+UString2 &UString2::operator=(const wchar_t *s)
+{
+ unsigned len = MyStringLen(s);
+ if (len > _len)
+ {
+ wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ if (_chars)
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ }
+ _len = len;
+ MyStringCopy(_chars, s);
+ return *this;
+}
+
+void UString2::SetFromAscii(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ if (len > _len)
+ {
+ wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ if (_chars)
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ }
+ wchar_t *chars = _chars;
+ for (unsigned i = 0; i < len; i++)
+ chars[i] = (unsigned char)s[i];
+ chars[len] = 0;
+ _len = len;
+}
+
+UString2 &UString2::operator=(const UString2 &s)
+{
+ if (&s == this)
+ return *this;
+ unsigned len = s._len;
+ if (len > _len)
+ {
+ wchar_t *newBuf = MY_STRING_NEW(wchar_t, len + 1);
+ if (_chars)
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ }
+ _len = len;
+ MyStringCopy(_chars, s._chars);
+ return *this;
+}
+
+bool operator==(const UString2 &s1, const UString2 &s2)
+{
+ return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);
+}
+
+bool operator==(const UString2 &s1, const wchar_t *s2)
+{
+ if (s1.IsEmpty())
+ return (*s2 == 0);
+ return wcscmp(s1.GetRawPtr(), s2) == 0;
+}
+
+bool operator==(const wchar_t *s1, const UString2 &s2)
+{
+ if (s2.IsEmpty())
+ return (*s1 == 0);
+ return wcscmp(s1, s2.GetRawPtr()) == 0;
+}
+
+
+
// ----------------------------------------
/*
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
index a2ed5382..a0e88df5 100644
--- a/CPP/Common/MyString.h
+++ b/CPP/Common/MyString.h
@@ -13,6 +13,15 @@
#include "MyTypes.h"
#include "MyVector.h"
+#ifdef _WIN32
+#define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/')
+#else
+#define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR)
+#endif
+
+inline bool IsPathSepar(char c) { return IS_PATH_SEPAR(c); }
+inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); }
+
inline unsigned MyStringLen(const char *s)
{
unsigned i;
@@ -50,6 +59,21 @@ inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
while ((*dest++ = *src++) != 0);
}
+/*
+inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src)
+{
+ for (;;)
+ {
+ wchar_t c = *src;
+ *dest = c;
+ if (c == 0)
+ return dest;
+ src++;
+ dest++;
+ }
+}
+*/
+
int FindCharPosInString(const char *s, char c) throw();
int FindCharPosInString(const wchar_t *s, wchar_t c) throw();
@@ -81,7 +105,7 @@ inline wchar_t MyCharUpper_Ascii(wchar_t c)
inline char MyCharLower_Ascii(char c)
{
if (c >= 'A' && c <= 'Z')
- return (char)(c + 0x20);
+ return (char)((unsigned char)c + 0x20);
return c;
}
@@ -134,6 +158,7 @@ inline wchar_t MyCharLower(wchar_t c) throw()
// char *MyStringLower(char *s) throw();
// void MyStringUpper_Ascii(wchar_t *s) throw();
+void MyStringLower_Ascii(char *s) throw();
void MyStringLower_Ascii(wchar_t *s) throw();
// wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW;
// wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW;
@@ -142,9 +167,10 @@ bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
+bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();
int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();
-int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();
+// int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();
// ---------- ASCII ----------
// char values in ASCII strings must be less then 128
@@ -170,6 +196,7 @@ class AString
void InsertSpace(unsigned &index, unsigned size);
void ReAlloc(unsigned newLimit);
+ void ReAlloc2(unsigned newLimit);
void SetStartLen(unsigned len);
void Grow_1();
void Grow(unsigned n);
@@ -186,6 +213,17 @@ class AString
friend AString operator+(const AString &s1, const char *s2);
friend AString operator+(const char *s1, const AString &s2);
+ // ---------- forbidden functions ----------
+ AString &operator+=(wchar_t c);
+ AString &operator=(wchar_t c);
+ AString(wchar_t c);
+ void Find(wchar_t c) const;
+ void Find(wchar_t c, unsigned startIndex) const;
+ void ReverseFind(wchar_t c) const;
+ void InsertAtFront(wchar_t c);
+ void RemoveChar(wchar_t ch);
+ void Replace(wchar_t oldChar, wchar_t newChar);
+
public:
AString();
AString(char c);
@@ -205,20 +243,39 @@ public:
void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
- // The minimum size of the character buffer in characters.
- // This value does not include space for a null terminator.
- char *GetBuffer(unsigned minBufLen)
+ /* GetBuf(minLen): provides the buffer that can store
+ at least (minLen) characters and additional null terminator.
+ 9.35: GetBuf doesn't preserve old characters and terminator */
+ char *GetBuf(unsigned minLen)
{
- if (minBufLen > _limit)
- ReAlloc(minBufLen);
+ if (minLen > _limit)
+ ReAlloc2(minLen);
return _chars;
}
- void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
- void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
+ char *GetBuf_SetEnd(unsigned minLen)
+ {
+ if (minLen > _limit)
+ ReAlloc2(minLen);
+ char *chars = _chars;
+ chars[minLen] = 0;
+ _len = minLen;
+ return chars;
+ }
+
+ void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
+ void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
+ void ReleaseBuf_CalcLen(unsigned maxLen)
+ {
+ char *chars = _chars;
+ chars[maxLen] = 0;
+ _len = MyStringLen(chars);
+ }
AString &operator=(char c);
AString &operator=(const char *s);
AString &operator=(const AString &s);
+ void SetFromWStr_if_Ascii(const wchar_t *s);
+ // void SetFromBstr_if_Ascii(BSTR s);
AString &operator+=(char c)
{
@@ -231,18 +288,30 @@ public:
_len = len;
return *this;
}
+
+ void Add_Space();
+ void Add_Space_if_NotEmpty();
+ void Add_LF();
+ void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }
AString &operator+=(const char *s);
AString &operator+=(const AString &s);
+ void AddAscii(const char *s) { operator+=(s); }
void SetFrom(const char *s, unsigned len); // no check
+ void SetFrom_CalcLen(const char *s, unsigned len);
+ // void SetFromAscii(const char *s) { operator+=(s); }
+
// AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
AString Left(unsigned count) const { return AString(count, *this); }
// void MakeUpper() { MyStringUpper(_chars); }
// void MakeLower() { MyStringLower(_chars); }
+ void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
+ bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; }
+ bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
// int Compare(const char *s) const { return MyStringCompare(_chars, s); }
// int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }
// int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }
@@ -250,16 +319,29 @@ public:
bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
+ bool IsAscii() const
+ {
+ unsigned len = Len();
+ const char *s = _chars;
+ for (unsigned i = 0; i < len; i++)
+ if ((unsigned char)s[i] >= 0x80)
+ return false;
+ return true;
+ }
int Find(char c) const { return FindCharPosInString(_chars, c); }
int Find(char c, unsigned startIndex) const
{
int pos = FindCharPosInString(_chars + startIndex, c);
return pos < 0 ? -1 : (int)startIndex + pos;
}
+
int ReverseFind(char c) const throw();
- int Find(const AString &s) const { return Find(s, 0); }
- int Find(const AString &s, unsigned startIndex) const throw();
+ int ReverseFind_Dot() const throw() { return ReverseFind('.'); }
+ int ReverseFind_PathSepar() const throw();
+ int Find(const char *s) const { return Find(s, 0); }
+ int Find(const char *s, unsigned startIndex) const throw();
+
void TrimLeft() throw();
void TrimRight() throw();
void Trim()
@@ -274,9 +356,10 @@ public:
void Insert(unsigned index, const AString &s);
void RemoveChar(char ch) throw();
+
void Replace(char oldChar, char newChar) throw();
void Replace(const AString &oldString, const AString &newString);
-
+
void Delete(unsigned index) throw();
void Delete(unsigned index, unsigned count) throw();
void DeleteFrontal(unsigned num) throw();
@@ -312,6 +395,19 @@ inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() !
inline bool operator!=(const AString &s1, const char *s2) { return strcmp(s1, s2) != 0; }
inline bool operator!=(const char *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
+// ---------- forbidden functions ----------
+
+void operator==(char c1, const AString &s2);
+void operator==(const AString &s1, char c2);
+
+void operator+(char c, const AString &s); // this function can be OK, but we don't use it
+
+void operator+(const AString &s, int c);
+void operator+(const AString &s, unsigned c);
+void operator+(int c, const AString &s);
+void operator+(unsigned c, const AString &s);
+void operator-(const AString &s, int c);
+void operator-(const AString &s, unsigned c);
class UString
@@ -328,6 +424,7 @@ class UString
void InsertSpace(unsigned index, unsigned size);
void ReAlloc(unsigned newLimit);
+ void ReAlloc2(unsigned newLimit);
void SetStartLen(unsigned len);
void Grow_1();
void Grow(unsigned n);
@@ -344,6 +441,27 @@ class UString
friend UString operator+(const UString &s1, const wchar_t *s2);
friend UString operator+(const wchar_t *s1, const UString &s2);
+ // ---------- forbidden functions ----------
+
+ UString &operator+=(char c);
+ UString &operator+=(unsigned char c);
+ UString &operator=(char c);
+ UString &operator=(unsigned char c);
+ UString(char c);
+ UString(unsigned char c);
+ void Find(char c) const;
+ void Find(unsigned char c) const;
+ void Find(char c, unsigned startIndex) const;
+ void Find(unsigned char c, unsigned startIndex) const;
+ void ReverseFind(char c) const;
+ void ReverseFind(unsigned char c) const;
+ void InsertAtFront(char c);
+ void InsertAtFront(unsigned char c);
+ void RemoveChar(char ch);
+ void RemoveChar(unsigned char ch);
+ void Replace(char oldChar, char newChar);
+ void Replace(unsigned char oldChar, unsigned char newChar);
+
public:
UString();
UString(wchar_t c);
@@ -363,20 +481,35 @@ public:
void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
- // The minimum size of the character buffer in characters.
- // This value does not include space for a null terminator.
- wchar_t *GetBuffer(unsigned minBufLen)
+ wchar_t *GetBuf(unsigned minLen)
{
- if (minBufLen > _limit)
- ReAlloc(minBufLen);
+ if (minLen > _limit)
+ ReAlloc2(minLen);
return _chars;
}
- void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
- void ReleaseBuffer(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
+ wchar_t *GetBuf_SetEnd(unsigned minLen)
+ {
+ if (minLen > _limit)
+ ReAlloc2(minLen);
+ wchar_t *chars = _chars;
+ chars[minLen] = 0;
+ _len = minLen;
+ return chars;
+ }
+
+ void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
+ void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
+ void ReleaseBuf_CalcLen(unsigned maxLen)
+ {
+ wchar_t *chars = _chars;
+ chars[maxLen] = 0;
+ _len = MyStringLen(chars);
+ }
UString &operator=(wchar_t c);
UString &operator=(const wchar_t *s);
UString &operator=(const UString &s);
+ void SetFromBstr(BSTR s);
UString &operator+=(wchar_t c)
{
@@ -390,13 +523,18 @@ public:
return *this;
}
+ void Add_Space();
+ void Add_Space_if_NotEmpty();
+ void Add_LF();
+ void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); }
+
UString &operator+=(const wchar_t *s);
UString &operator+=(const UString &s);
void SetFrom(const wchar_t *s, unsigned len); // no check
void SetFromAscii(const char *s);
- void AddAsciiStr(const char *s);
+ void AddAscii(const char *s);
UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
UString Left(unsigned count) const { return UString(count, *this); }
@@ -407,23 +545,38 @@ public:
void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
- bool IsEqualToNoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
+ bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
+ bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
// int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }
// int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }
// int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
- bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); };
+ bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }
+ bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); }
bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
+ bool IsAscii() const
+ {
+ unsigned len = Len();
+ const wchar_t *s = _chars;
+ for (unsigned i = 0; i < len; i++)
+ if (s[i] >= 0x80)
+ return false;
+ return true;
+ }
int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
int Find(wchar_t c, unsigned startIndex) const
{
int pos = FindCharPosInString(_chars + startIndex, c);
return pos < 0 ? -1 : (int)startIndex + pos;
}
- int Find(const UString &s) const { return Find(s, 0); }
- int Find(const UString &s, unsigned startIndex) const throw();
+
int ReverseFind(wchar_t c) const throw();
+ int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); }
+ int ReverseFind_PathSepar() const throw();
+
+ int Find(const wchar_t *s) const { return Find(s, 0); }
+ int Find(const wchar_t *s, unsigned startIndex) const throw();
void TrimLeft() throw();
void TrimRight() throw();
@@ -439,9 +592,10 @@ public:
void Insert(unsigned index, const UString &s);
void RemoveChar(wchar_t ch) throw();
+
void Replace(wchar_t oldChar, wchar_t newChar) throw();
void Replace(const UString &oldString, const UString &newString);
-
+
void Delete(unsigned index) throw();
void Delete(unsigned index, unsigned count) throw();
void DeleteFrontal(unsigned num) throw();
@@ -468,6 +622,110 @@ inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1,
inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
+// ---------- forbidden functions ----------
+
+void operator==(wchar_t c1, const UString &s2);
+void operator==(const UString &s1, wchar_t c2);
+
+void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it
+
+void operator+(const UString &s, char c);
+void operator+(const UString &s, unsigned char c);
+void operator+(char c, const UString &s);
+void operator+(unsigned char c, const UString &s);
+void operator-(const UString &s1, wchar_t c);
+
+#ifdef _WIN32
+// can we forbid these functions, if wchar_t is 32-bit ?
+void operator+(const UString &s, int c);
+void operator+(const UString &s, unsigned c);
+void operator+(int c, const UString &s);
+void operator+(unsigned c, const UString &s);
+void operator-(const UString &s1, int c);
+void operator-(const UString &s1, unsigned c);
+#endif
+
+
+
+
+
+
+
+class UString2
+{
+ wchar_t *_chars;
+ unsigned _len;
+
+ void ReAlloc2(unsigned newLimit);
+ void SetStartLen(unsigned len);
+
+ // ---------- forbidden functions ----------
+
+ UString2 &operator=(char c);
+ UString2 &operator=(unsigned char c);
+ UString2 &operator=(wchar_t c);
+ UString2(char c);
+ UString2(unsigned char c);
+
+public:
+ UString2(): _chars(NULL), _len(0) {}
+ // UString2(wchar_t c);
+ UString2(const wchar_t *s);
+ UString2(const UString2 &s);
+ ~UString2() { if (_chars) MY_STRING_DELETE(_chars); }
+
+ unsigned Len() const { return _len; }
+ bool IsEmpty() const { return _len == 0; }
+ // void Empty() { _len = 0; _chars[0] = 0; }
+
+ // operator const wchar_t *() const { return _chars; }
+ const wchar_t *GetRawPtr() const { return _chars; }
+
+ wchar_t *GetBuf(unsigned minLen)
+ {
+ if (!_chars || minLen > _len)
+ ReAlloc2(minLen);
+ return _chars;
+ }
+ void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
+
+ UString2 &operator=(const wchar_t *s);
+ UString2 &operator=(const UString2 &s);
+ void SetFromAscii(const char *s);
+};
+
+bool operator==(const UString2 &s1, const UString2 &s2);
+bool operator==(const UString2 &s1, const wchar_t *s2);
+bool operator==(const wchar_t *s1, const UString2 &s2);
+
+inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); }
+inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); }
+inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); }
+
+
+// ---------- forbidden functions ----------
+
+void operator==(wchar_t c1, const UString2 &s2);
+void operator==(const UString2 &s1, wchar_t c2);
+bool operator<(const UString2 &s1, const UString2 &s2);
+bool operator>(const UString2 &s1, const UString2 &s2);
+
+void operator+(const UString2 &s1, const UString2 &s2);
+void operator+(const UString2 &s1, const wchar_t *s2);
+void operator+(const wchar_t *s1, const UString2 &s2);
+void operator+(wchar_t c, const UString2 &s);
+void operator+(const UString2 &s, wchar_t c);
+void operator+(const UString2 &s, char c);
+void operator+(const UString2 &s, unsigned char c);
+void operator+(char c, const UString2 &s);
+void operator+(unsigned char c, const UString2 &s);
+void operator-(const UString2 &s1, wchar_t c);
+
+
+
+
+
+
typedef CObjectVector<AString> AStringVector;
typedef CObjectVector<UString> UStringVector;
diff --git a/CPP/Common/MyTypes.h b/CPP/Common/MyTypes.h
index 4f52a01d..75806f37 100644
--- a/CPP/Common/MyTypes.h
+++ b/CPP/Common/MyTypes.h
@@ -27,4 +27,9 @@ struct CBoolPair
}
};
+#define CLASS_NO_COPY(cls) \
+ private: \
+ cls(const cls &); \
+ cls &operator=(const cls &);
+
#endif
diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h
index 0d060a93..28b26d68 100644
--- a/CPP/Common/MyVector.h
+++ b/CPP/Common/MyVector.h
@@ -12,7 +12,7 @@ class CRecordVector
void MoveItems(unsigned destIndex, unsigned srcIndex)
{
- memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * (size_t)sizeof(T));
+ memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T));
}
void ReserveOnePosition()
@@ -21,7 +21,8 @@ class CRecordVector
{
unsigned newCapacity = _capacity + (_capacity >> 2) + 1;
T *p = new T[newCapacity];
- memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));
+ if (_size != 0)
+ memcpy(p, _items, (size_t)_size * sizeof(T));
delete []_items;
_items = p;
_capacity = newCapacity;
@@ -40,7 +41,7 @@ public:
_items = new T[size];
_size = size;
_capacity = size;
- memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T));
+ memcpy(_items, v._items, (size_t)size * sizeof(T));
}
}
@@ -61,7 +62,8 @@ public:
if (newCapacity > _capacity)
{
T *p = new T[newCapacity];
- memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));
+ if (_size != 0)
+ memcpy(p, _items, (size_t)_size * sizeof(T));
delete []_items;
_items = p;
_capacity = newCapacity;
@@ -92,7 +94,8 @@ public:
if (newSize > _capacity)
{
T *p = new T[newSize];
- memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));
+ if (_size != 0)
+ memcpy(p, _items, (size_t)_size * sizeof(T));
delete []_items;
_items = p;
_capacity = newSize;
@@ -108,7 +111,7 @@ public:
if (_size != 0)
{
p = new T[_size];
- memcpy(p, _items, (size_t)_size * (size_t)sizeof(T));
+ memcpy(p, _items, (size_t)_size * sizeof(T));
}
delete []_items;
_items = p;
@@ -163,6 +166,8 @@ public:
CRecordVector& operator=(const CRecordVector &v)
{
+ if (&v == this)
+ return *this;
unsigned size = v.Size();
if (size > _capacity)
{
@@ -174,7 +179,8 @@ public:
_capacity = size;
}
_size = size;
- memcpy(_items, v._items, (size_t)size * (size_t)sizeof(T));
+ if (size != 0)
+ memcpy(_items, v._items, (size_t)size * sizeof(T));
return *this;
}
@@ -182,7 +188,8 @@ public:
{
unsigned size = v.Size();
Reserve(_size + size);
- memcpy(_items + _size, v._items, (size_t)size * (size_t)sizeof(T));
+ if (size != 0)
+ memcpy(_items + _size, v._items, (size_t)size * sizeof(T));
_size += size;
return *this;
}
@@ -212,7 +219,7 @@ public:
if (index != 0)
{
T temp = _items[index];
- memmove(_items + 1, _items, (size_t)index * (size_t)sizeof(T));
+ memmove(_items + 1, _items, (size_t)index * sizeof(T));
_items[0] = temp;
}
}
@@ -421,6 +428,8 @@ public:
}
CObjectVector& operator=(const CObjectVector &v)
{
+ if (&v == this)
+ return *this;
Clear();
unsigned size = v.Size();
_v.Reserve(size);
diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp
index 410f24e9..e5e8be99 100644
--- a/CPP/Common/NewHandler.cpp
+++ b/CPP/Common/NewHandler.cpp
@@ -31,7 +31,8 @@ void my_delete(void *p) throw()
void * my_Realloc(void *p, size_t newSize, size_t oldSize)
{
void *newBuf = my_new(newSize);
- memcpy(newBuf, p, oldSize);
+ if (oldSize != 0)
+ memcpy(newBuf, p, oldSize);
my_delete(p);
return newBuf;
}
diff --git a/CPP/Common/Sha1Reg.cpp b/CPP/Common/Sha1Reg.cpp
new file mode 100644
index 00000000..eedb7e29
--- /dev/null
+++ b/CPP/Common/Sha1Reg.cpp
@@ -0,0 +1,40 @@
+// Sha1Reg.cpp
+
+#include "StdAfx.h"
+
+#include "../../C/Sha1.h"
+
+#include "../Common/MyCom.h"
+
+#include "../7zip/Common/RegisterCodec.h"
+
+class CSha1Hasher:
+ public IHasher,
+ public CMyUnknownImp
+{
+ CSha1 _sha;
+ Byte mtDummy[1 << 7];
+
+public:
+ CSha1Hasher() { Sha1_Init(&_sha); }
+
+ MY_UNKNOWN_IMP
+ INTERFACE_IHasher(;)
+};
+
+STDMETHODIMP_(void) CSha1Hasher::Init() throw()
+{
+ Sha1_Init(&_sha);
+}
+
+STDMETHODIMP_(void) CSha1Hasher::Update(const void *data, UInt32 size) throw()
+{
+ Sha1_Update(&_sha, (const Byte *)data, size);
+}
+
+STDMETHODIMP_(void) CSha1Hasher::Final(Byte *digest) throw()
+{
+ Sha1_Final(&_sha, digest);
+}
+
+REGISTER_HASHER(CSha1Hasher, 0x201, "SHA1", SHA1_DIGEST_SIZE)
diff --git a/CPP/Common/Sha256Reg.cpp b/CPP/Common/Sha256Reg.cpp
index 6adb3cdc..6c822cc7 100644
--- a/CPP/Common/Sha256Reg.cpp
+++ b/CPP/Common/Sha256Reg.cpp
@@ -6,7 +6,6 @@
#include "../Common/MyCom.h"
-#include "../7zip/ICoder.h"
#include "../7zip/Common/RegisterCodec.h"
class CSha256Hasher:
@@ -14,39 +13,28 @@ class CSha256Hasher:
public CMyUnknownImp
{
CSha256 _sha;
+ Byte mtDummy[1 << 7];
+
public:
- CSha256Hasher() { Init(); };
+ CSha256Hasher() { Sha256_Init(&_sha); }
MY_UNKNOWN_IMP
-
- STDMETHOD_(void, Init)();
- STDMETHOD_(void, Update)(const void *data, UInt32 size);
- STDMETHOD_(void, Final)(Byte *digest);
- STDMETHOD_(UInt32, GetDigestSize)();
+ INTERFACE_IHasher(;)
};
-STDMETHODIMP_(void) CSha256Hasher::Init()
+STDMETHODIMP_(void) CSha256Hasher::Init() throw()
{
Sha256_Init(&_sha);
}
-STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size)
+STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size) throw()
{
Sha256_Update(&_sha, (const Byte *)data, size);
}
-STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest)
+STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest) throw()
{
Sha256_Final(&_sha, digest);
}
-STDMETHODIMP_(UInt32) CSha256Hasher::GetDigestSize()
-{
- return SHA256_DIGEST_SIZE;
-}
-
-static IHasher *CreateHasher() { return new CSha256Hasher; }
-
-static CHasherInfo g_HasherInfo = { CreateHasher, 0xA, L"SHA256", SHA256_DIGEST_SIZE };
-
-REGISTER_HASHER(Sha256)
+REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE)
diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h
index 5cd40e40..1837bfb0 100644
--- a/CPP/Common/StdOutStream.h
+++ b/CPP/Common/StdOutStream.h
@@ -39,7 +39,7 @@ public:
CStdOutStream & operator<<(char c) throw()
{
- fputc(c, _stream);
+ fputc((unsigned char)c, _stream);
return *this;
}
diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp
index 0443a06c..b55ac171 100644
--- a/CPP/Common/StringConvert.cpp
+++ b/CPP/Common/StringConvert.cpp
@@ -8,158 +8,306 @@
#include <stdlib.h>
#endif
+static const char k_DefultChar = '_';
+
#ifdef _WIN32
-UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)
-{
- UString resultString;
- if (!srcString.IsEmpty())
- {
- int numChars = MultiByteToWideChar(codePage, 0, srcString,
- srcString.Len(), resultString.GetBuffer(srcString.Len()),
- srcString.Len() + 1);
- if (numChars == 0)
- throw 282228;
- resultString.ReleaseBuffer(numChars);
- }
- return resultString;
-}
-void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage)
+/*
+MultiByteToWideChar(CodePage, DWORD dwFlags,
+ LPCSTR lpMultiByteStr, int cbMultiByte,
+ LPWSTR lpWideCharStr, int cchWideChar)
+
+ if (cbMultiByte == 0)
+ return: 0. ERR: ERROR_INVALID_PARAMETER
+
+ if (cchWideChar == 0)
+ return: the required buffer size in characters.
+
+ if (supplied buffer size was not large enough)
+ return: 0. ERR: ERROR_INSUFFICIENT_BUFFER
+ The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex)
+
+ If there are illegal characters:
+ if MB_ERR_INVALID_CHARS is set in dwFlags:
+ - the function stops conversion on illegal character.
+ - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION.
+
+ if MB_ERR_INVALID_CHARS is NOT set in dwFlags:
+ before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0.
+ in Vista+: illegal character is not dropped (MSDN). Undocumented: illegal
+ character is converted to U+FFFD, which is REPLACEMENT CHARACTER.
+*/
+
+
+void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
{
dest.Empty();
- if (!srcString.IsEmpty())
+ if (src.IsEmpty())
+ return;
{
- wchar_t *destBuf = dest.GetBuffer(srcString.Len());
- const char *sp = (const char *)srcString;
+ /*
+ wchar_t *d = dest.GetBuf(src.Len());
+ const char *s = (const char *)src;
unsigned i;
+
for (i = 0;;)
{
- char c = sp[i];
- if ((Byte)c >= 0x80 || c == 0)
+ Byte c = (Byte)s[i];
+ if (c >= 0x80 || c == 0)
break;
- destBuf[i++] = (wchar_t)c;
+ d[i++] = (wchar_t)c;
}
- if (i != srcString.Len())
+ if (i != src.Len())
{
- unsigned numChars = MultiByteToWideChar(codePage, 0, sp + i,
- srcString.Len() - i, destBuf + i,
- srcString.Len() + 1 - i);
- if (numChars == 0)
+ unsigned len = MultiByteToWideChar(codePage, 0, s + i,
+ src.Len() - i, d + i,
+ src.Len() + 1 - i);
+ if (len == 0)
throw 282228;
- i += numChars;
+ i += len;
+ }
+
+ d[i] = 0;
+ dest.ReleaseBuf_SetLen(i);
+ */
+ unsigned len = MultiByteToWideChar(codePage, 0, src, src.Len(), NULL, 0);
+ if (len == 0)
+ {
+ if (GetLastError() != 0)
+ throw 282228;
+ }
+ else
+ {
+ len = MultiByteToWideChar(codePage, 0, src, src.Len(), dest.GetBuf(len), len);
+ if (len == 0)
+ throw 282228;
+ dest.ReleaseBuf_SetEnd(len);
}
- dest.ReleaseBuffer(i);
}
}
-void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
+/*
+ int WideCharToMultiByte(
+ UINT CodePage, DWORD dwFlags,
+ LPCWSTR lpWideCharStr, int cchWideChar,
+ LPSTR lpMultiByteStr, int cbMultiByte,
+ LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
+
+if (lpDefaultChar == NULL),
+ - it uses system default value.
+
+if (CodePage == CP_UTF7 || CodePage == CP_UTF8)
+ if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL)
+ return: 0. ERR: ERROR_INVALID_PARAMETER.
+
+The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL)
+
+*/
+
+static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
{
dest.Empty();
defaultCharWasUsed = false;
- if (!s.IsEmpty())
+ if (src.IsEmpty())
+ return;
{
- unsigned numRequiredBytes = s.Len() * 2;
- char *destBuf = dest.GetBuffer(numRequiredBytes);
+ /*
+ unsigned numRequiredBytes = src.Len() * 2;
+ char *d = dest.GetBuf(numRequiredBytes);
+ const wchar_t *s = (const wchar_t *)src;
unsigned i;
- const wchar_t *sp = (const wchar_t *)s;
+
for (i = 0;;)
{
- wchar_t c = sp[i];
+ wchar_t c = s[i];
if (c >= 0x80 || c == 0)
break;
- destBuf[i++] = (char)c;
+ d[i++] = (char)c;
}
- defaultCharWasUsed = false;
- if (i != s.Len())
+
+ if (i != src.Len())
{
- BOOL defUsed;
- unsigned numChars = WideCharToMultiByte(codePage, 0, sp + i, s.Len() - i,
- destBuf + i, numRequiredBytes + 1 - i,
- &defaultChar, &defUsed);
+ BOOL defUsed = FALSE;
+ defaultChar = defaultChar;
+
+ bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);
+ unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i,
+ d + i, numRequiredBytes + 1 - i,
+ (isUtf ? NULL : &defaultChar),
+ (isUtf ? NULL : &defUsed));
defaultCharWasUsed = (defUsed != FALSE);
- if (numChars == 0)
+ if (len == 0)
throw 282229;
- i += numChars;
+ i += len;
}
- dest.ReleaseBuffer(i);
- }
-}
-void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage)
-{
- bool defaultCharWasUsed;
- UnicodeStringToMultiByte2(dest, srcString, codePage, '_', defaultCharWasUsed);
-}
+ d[i] = 0;
+ dest.ReleaseBuf_SetLen(i);
+ */
-AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
-{
- AString dest;
- defaultCharWasUsed = false;
- if (!s.IsEmpty())
- {
- unsigned numRequiredBytes = s.Len() * 2;
- BOOL defUsed;
- int numChars = WideCharToMultiByte(codePage, 0, s, s.Len(),
- dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1,
- &defaultChar, &defUsed);
- defaultCharWasUsed = (defUsed != FALSE);
- if (numChars == 0)
- throw 282229;
- dest.ReleaseBuffer(numChars);
- }
- return dest;
-}
+ /*
+ if (codePage != CP_UTF7)
+ {
+ const wchar_t *s = (const wchar_t *)src;
+ unsigned i;
+ for (i = 0;; i++)
+ {
+ wchar_t c = s[i];
+ if (c >= 0x80 || c == 0)
+ break;
+ }
+
+ if (s[i] == 0)
+ {
+ char *d = dest.GetBuf(src.Len());
+ for (i = 0;;)
+ {
+ wchar_t c = s[i];
+ if (c == 0)
+ break;
+ d[i++] = (char)c;
+ }
+ d[i] = 0;
+ dest.ReleaseBuf_SetLen(i);
+ return;
+ }
+ }
+ */
-AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)
-{
- bool defaultCharWasUsed;
- return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed);
+ unsigned len = WideCharToMultiByte(codePage, 0, src, src.Len(), NULL, 0, NULL, NULL);
+ if (len == 0)
+ {
+ if (GetLastError() != 0)
+ throw 282228;
+ }
+ else
+ {
+ BOOL defUsed = FALSE;
+ bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);
+ defaultChar = defaultChar;
+ len = WideCharToMultiByte(codePage, 0, src, src.Len(),
+ dest.GetBuf(len), len,
+ (isUtf ? NULL : &defaultChar),
+ (isUtf ? NULL : &defUsed)
+ );
+ if (!isUtf)
+ defaultCharWasUsed = (defUsed != FALSE);
+ if (len == 0)
+ throw 282228;
+ dest.ReleaseBuf_SetEnd(len);
+ }
+ }
}
+/*
#ifndef UNDER_CE
-AString SystemStringToOemString(const CSysString &srcString)
+AString SystemStringToOemString(const CSysString &src)
{
- AString result;
- CharToOem(srcString, result.GetBuffer(srcString.Len() * 2));
- result.ReleaseBuffer();
- return result;
+ AString dest;
+ const unsigned len = src.Len() * 2;
+ CharToOem(src, dest.GetBuf(len));
+ dest.ReleaseBuf_CalcLen(len);
+ return dest;
}
#endif
+*/
#else
-UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)
+void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT /* codePage */)
{
- UString resultString;
- for (unsigned i = 0; i < srcString.Len(); i++)
- resultString += (wchar_t)srcString[i];
- /*
- if (!srcString.IsEmpty())
+ dest.Empty();
+ if (src.IsEmpty())
+ return;
+
+ size_t limit = ((size_t)src.Len() + 1) * 2;
+ wchar_t *d = dest.GetBuf((unsigned)limit);
+ size_t len = mbstowcs(d, src, limit);
+ if (len != (size_t)-1)
{
- int numChars = mbstowcs(resultString.GetBuffer(srcString.Len()), srcString, srcString.Len() + 1);
- if (numChars < 0) throw "Your environment does not support UNICODE";
- resultString.ReleaseBuffer(numChars);
+ dest.ReleaseBuf_SetEnd((unsigned)len);
+ return;
+ }
+
+ {
+ unsigned i;
+ const char *s = (const char *)src;
+ for (i = 0;;)
+ {
+ Byte c = (Byte)s[i];
+ if (c == 0)
+ break;
+ d[i++] = (wchar_t)c;
+ }
+ d[i] = 0;
+ dest.ReleaseBuf_SetLen(i);
}
- */
- return resultString;
}
-AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)
+static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT /* codePage */, char defaultChar, bool &defaultCharWasUsed)
{
- AString resultString;
- for (unsigned i = 0; i < srcString.Len(); i++)
- resultString += (char)srcString[i];
- /*
- if (!srcString.IsEmpty())
+ dest.Empty();
+ defaultCharWasUsed = false;
+ if (src.IsEmpty())
+ return;
+
+ size_t limit = ((size_t)src.Len() + 1) * 6;
+ char *d = dest.GetBuf((unsigned)limit);
+ size_t len = wcstombs(d, src, limit);
+ if (len != (size_t)-1)
{
- int numRequiredBytes = srcString.Len() * 6 + 1;
- int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes);
- if (numChars < 0) throw "Your environment does not support UNICODE";
- resultString.ReleaseBuffer(numChars);
+ dest.ReleaseBuf_SetEnd((unsigned)len);
+ return;
+ }
+
+ {
+ const wchar_t *s = (const wchar_t *)src;
+ unsigned i;
+ for (i = 0;;)
+ {
+ wchar_t c = s[i];
+ if (c == 0)
+ break;
+ if (c >= 0x100)
+ {
+ c = defaultChar;
+ defaultCharWasUsed = true;
+ }
+ d[i++] = (char)c;
+ }
+ d[i] = 0;
+ dest.ReleaseBuf_SetLen(i);
}
- */
- return resultString;
}
#endif
+
+
+UString MultiByteToUnicodeString(const AString &src, UINT codePage)
+{
+ UString dest;
+ MultiByteToUnicodeString2(dest, src, codePage);
+ return dest;
+}
+
+void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage)
+{
+ bool defaultCharWasUsed;
+ UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);
+}
+
+AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
+{
+ AString dest;
+ UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed);
+ return dest;
+}
+
+AString UnicodeStringToMultiByte(const UString &src, UINT codePage)
+{
+ AString dest;
+ bool defaultCharWasUsed;
+ UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);
+ return dest;
+}
diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h
index 8eea72ef..92401245 100644
--- a/CPP/Common/StringConvert.h
+++ b/CPP/Common/StringConvert.h
@@ -10,7 +10,7 @@ UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_AC
// optimized versions that work faster for ASCII strings
void MultiByteToUnicodeString2(UString &dest, const AString &srcString, UINT codePage = CP_ACP);
-void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
+// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
void UnicodeStringToMultiByte2(AString &dest, const UString &srcString, UINT codePage);
AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp
index 2023fcc2..dfa5cc3b 100644
--- a/CPP/Common/StringToInt.cpp
+++ b/CPP/Common/StringToInt.cpp
@@ -8,12 +8,12 @@ static const UInt32 k_UInt32_max = 0xFFFFFFFF;
static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF);
// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1;
-#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType) \
+#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \
uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \
if (end) *end = s; \
uintType res = 0; \
for (;; s++) { \
- charType c = *s; \
+ charTypeUnsigned c = (charTypeUnsigned)*s; \
if (c < '0' || c > '9') { if (end) *end = s; return res; } \
if (res > (k_ ## uintType ## _max) / 10) return 0; \
res *= 10; \
@@ -21,10 +21,10 @@ static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF);
if (res > (k_ ## uintType ## _max) - v) return 0; \
res += v; }}
-CONVERT_STRING_TO_UINT_FUNC(UInt32, char)
-CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t)
-CONVERT_STRING_TO_UINT_FUNC(UInt64, char)
-CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t)
+CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte)
+CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t)
+CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte)
+CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t)
Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()
{
@@ -58,7 +58,7 @@ UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw()
UInt32 res = 0;
for (;; s++)
{
- char c = *s;
+ unsigned c = (unsigned char)*s;
if (c < '0' || c > '7')
{
if (end)
@@ -79,7 +79,7 @@ UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw()
UInt64 res = 0;
for (;; s++)
{
- char c = *s;
+ unsigned c = (unsigned char)*s;
if (c < '0' || c > '7')
{
if (end)
@@ -100,7 +100,7 @@ UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw()
UInt32 res = 0;
for (;; s++)
{
- char c = *s;
+ unsigned c = (Byte)*s;
unsigned v;
if (c >= '0' && c <= '9') v = (c - '0');
else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
@@ -125,7 +125,7 @@ UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw()
UInt64 res = 0;
for (;; s++)
{
- char c = *s;
+ unsigned c = (Byte)*s;
unsigned v;
if (c >= '0' && c <= '9') v = (c - '0');
else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp
index 8cb1e9be..b772164a 100644
--- a/CPP/Common/UTFConvert.cpp
+++ b/CPP/Common/UTFConvert.cpp
@@ -5,56 +5,91 @@
#include "MyTypes.h"
#include "UTFConvert.h"
-static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+#ifdef _WIN32
+#define _WCHART_IS_16BIT 1
+#endif
-bool CheckUTF8(const char *src) throw()
+/*
+ _UTF8_START(n) - is a base value for start byte (head), if there are (n) additional bytes after start byte
+
+ n : _UTF8_START(n) : Bits of code point
+
+ 0 : 0x80 : : unused
+ 1 : 0xC0 : 11 :
+ 2 : 0xE0 : 16 : Basic Multilingual Plane
+ 3 : 0xF0 : 21 : Unicode space
+ 3 : 0xF8 : 26 :
+ 5 : 0xFC : 31 : UCS-4
+ 6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value
+ 7 : 0xFF :
+*/
+
+#define _UTF8_START(n) (0x100 - (1 << (7 - (n))))
+
+#define _UTF8_HEAD_PARSE2(n) if (c < _UTF8_START((n) + 1)) { numBytes = (n); c -= _UTF8_START(n); }
+
+#define _UTF8_HEAD_PARSE \
+ _UTF8_HEAD_PARSE2(1) \
+ else _UTF8_HEAD_PARSE2(2) \
+ else _UTF8_HEAD_PARSE2(3) \
+ else _UTF8_HEAD_PARSE2(4) \
+ else _UTF8_HEAD_PARSE2(5) \
+
+ // else _UTF8_HEAD_PARSE2(6)
+
+bool CheckUTF8(const char *src, bool allowReduced) throw()
{
for (;;)
{
- Byte c;
- unsigned numAdds;
- c = *src++;
+ Byte c = *src++;
if (c == 0)
return true;
if (c < 0x80)
continue;
- if (c < 0xC0)
+ if (c < 0xC0) // (c < 0xC0 + 2) // if we support only optimal encoding chars
return false;
- for (numAdds = 1; numAdds < 5; numAdds++)
- if (c < kUtf8Limits[numAdds])
- break;
- UInt32 value = (c - kUtf8Limits[numAdds - 1]);
+
+ unsigned numBytes;
+ _UTF8_HEAD_PARSE
+ else
+ return false;
+
+ UInt32 val = c;
do
{
Byte c2 = *src++;
if (c2 < 0x80 || c2 >= 0xC0)
- return false;
- value <<= 6;
- value |= (c2 - 0x80);
+ return allowReduced && c2 == 0;
+ val <<= 6;
+ val |= (c2 - 0x80);
}
- while (--numAdds);
+ while (--numBytes);
- if (value >= 0x110000)
+ if (val >= 0x110000)
return false;
}
}
-static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) throw()
+#define _ERROR_UTF8 \
+ { if (dest) dest[destPos] = (wchar_t)0xFFFD; destPos++; ok = false; continue; }
+
+static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim) throw()
{
- size_t destPos = 0, srcPos = 0;
+ size_t destPos = 0;
+ bool ok = true;
+
for (;;)
{
Byte c;
- unsigned numAdds;
- if (srcPos == srcLen)
+ if (src == srcLim)
{
*destLen = destPos;
- return True;
+ return ok;
}
- c = (Byte)src[srcPos++];
+ c = *src++;
if (c < 0x80)
{
@@ -64,113 +99,190 @@ static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_
continue;
}
if (c < 0xC0)
- break;
- for (numAdds = 1; numAdds < 5; numAdds++)
- if (c < kUtf8Limits[numAdds])
- break;
- UInt32 value = (c - kUtf8Limits[numAdds - 1]);
+ _ERROR_UTF8
+
+ unsigned numBytes;
+ _UTF8_HEAD_PARSE
+ else
+ _ERROR_UTF8
+
+ UInt32 val = c;
do
{
Byte c2;
- if (srcPos == srcLen)
+ if (src == srcLim)
break;
- c2 = (Byte)src[srcPos++];
+ c2 = *src;
if (c2 < 0x80 || c2 >= 0xC0)
break;
- value <<= 6;
- value |= (c2 - 0x80);
+ src++;
+ val <<= 6;
+ val |= (c2 - 0x80);
}
- while (--numAdds);
-
- if (value < 0x10000)
+ while (--numBytes);
+
+ if (numBytes != 0)
+ _ERROR_UTF8
+
+ if (val < 0x10000)
{
if (dest)
- dest[destPos] = (wchar_t)value;
+ dest[destPos] = (wchar_t)val;
destPos++;
}
else
{
- value -= 0x10000;
- if (value >= 0x100000)
- break;
+ val -= 0x10000;
+ if (val >= 0x100000)
+ _ERROR_UTF8
if (dest)
{
- dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10));
- dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF));
+ dest[destPos + 0] = (wchar_t)(0xD800 + (val >> 10));
+ dest[destPos + 1] = (wchar_t)(0xDC00 + (val & 0x3FF));
}
destPos += 2;
}
}
- *destLen = destPos;
- return False;
}
-static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen)
+#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))
+
+#define _UTF8_HEAD(n, val) ((char)(_UTF8_START(n) + (val >> (6 * (n)))))
+#define _UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F)))
+
+static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim)
{
- size_t destPos = 0, srcPos = 0;
+ size_t size = srcLim - src;
for (;;)
{
- unsigned numAdds;
- UInt32 value;
- if (srcPos == srcLen)
+ if (src == srcLim)
+ return size;
+
+ UInt32 val = *src++;
+
+ if (val < 0x80)
+ continue;
+
+ if (val < _UTF8_RANGE(1))
{
- *destLen = destPos;
- return True;
+ size++;
+ continue;
}
- value = src[srcPos++];
- if (value < 0x80)
+
+ if (val >= 0xD800 && val < 0xDC00 && src != srcLim)
{
- if (dest)
- dest[destPos] = (char)value;
- destPos++;
+ UInt32 c2 = *src;
+ if (c2 >= 0xDC00 && c2 < 0xE000)
+ {
+ src++;
+ size += 2;
+ continue;
+ }
+ }
+
+ #ifdef _WCHART_IS_16BIT
+
+ size += 2;
+
+ #else
+
+ if (val < _UTF8_RANGE(2)) size += 2;
+ else if (val < _UTF8_RANGE(3)) size += 3;
+ else if (val < _UTF8_RANGE(4)) size += 4;
+ else if (val < _UTF8_RANGE(5)) size += 5;
+ else size += 6;
+
+ #endif
+ }
+}
+
+static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim)
+{
+ for (;;)
+ {
+ if (src == srcLim)
+ return dest;
+
+ UInt32 val = *src++;
+
+ if (val < 0x80)
+ {
+ *dest++ = (char)val;
continue;
}
- if (value >= 0xD800 && value < 0xE000)
+
+ if (val < _UTF8_RANGE(1))
{
- UInt32 c2;
- if (value >= 0xDC00 || srcPos == srcLen)
- break;
- c2 = src[srcPos++];
- if (c2 < 0xDC00 || c2 >= 0xE000)
- break;
- value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
+ dest[0] = _UTF8_HEAD(1, val);
+ dest[1] = _UTF8_CHAR(0, val);
+ dest += 2;
+ continue;
}
- for (numAdds = 1; numAdds < 5; numAdds++)
- if (value < (((UInt32)1) << (numAdds * 5 + 6)))
- break;
- if (dest)
- dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
- destPos++;
+
+ if (val >= 0xD800 && val < 0xDC00 && src != srcLim)
+ {
+ UInt32 c2 = *src;
+ if (c2 >= 0xDC00 && c2 < 0xE000)
+ {
+ src++;
+ val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
+ dest[0] = _UTF8_HEAD(3, val);
+ dest[1] = _UTF8_CHAR(2, val);
+ dest[2] = _UTF8_CHAR(1, val);
+ dest[3] = _UTF8_CHAR(0, val);
+ dest += 4;
+ continue;
+ }
+ }
+
+ #ifndef _WCHART_IS_16BIT
+ if (val < _UTF8_RANGE(2))
+ #endif
+ {
+ dest[0] = _UTF8_HEAD(2, val);
+ dest[1] = _UTF8_CHAR(1, val);
+ dest[2] = _UTF8_CHAR(0, val);
+ dest += 3;
+ continue;
+ }
+
+ #ifndef _WCHART_IS_16BIT
+
+ UInt32 b;
+ unsigned numBits;
+ if (val < _UTF8_RANGE(3)) { numBits = 6 * 3; b = _UTF8_HEAD(3, val); }
+ else if (val < _UTF8_RANGE(4)) { numBits = 6 * 4; b = _UTF8_HEAD(4, val); }
+ else if (val < _UTF8_RANGE(5)) { numBits = 6 * 5; b = _UTF8_HEAD(5, val); }
+ else { numBits = 6 * 6; b = _UTF8_START(6); }
+
+ *dest++ = (Byte)b;
+
do
{
- numAdds--;
- if (dest)
- dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
- destPos++;
+ numBits -= 6;
+ *dest++ = (char)(0x80 + ((val >> numBits) & 0x3F));
}
- while (numAdds != 0);
+ while (numBits != 0);
+
+ #endif
}
- *destLen = destPos;
- return False;
}
bool ConvertUTF8ToUnicode(const AString &src, UString &dest)
{
dest.Empty();
size_t destLen = 0;
- Utf8_To_Utf16(NULL, &destLen, src, src.Len());
- Bool res = Utf8_To_Utf16(dest.GetBuffer((unsigned)destLen), &destLen, src, src.Len());
- dest.ReleaseBuffer((unsigned)destLen);
- return res ? true : false;
+ Utf8_To_Utf16(NULL, &destLen, src, src.Ptr(src.Len()));
+ bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src.Ptr(src.Len()));
+ dest.ReleaseBuf_SetEnd((unsigned)destLen);
+ return res;
}
-bool ConvertUnicodeToUTF8(const UString &src, AString &dest)
+void ConvertUnicodeToUTF8(const UString &src, AString &dest)
{
dest.Empty();
- size_t destLen = 0;
- Utf16_To_Utf8(NULL, &destLen, src, src.Len());
- Bool res = Utf16_To_Utf8(dest.GetBuffer((unsigned)destLen), &destLen, src, src.Len());
- dest.ReleaseBuffer((unsigned)destLen);
- return res ? true : false;
+ size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()));
+ Utf16_To_Utf8(dest.GetBuf((unsigned)destLen), src, src.Ptr(src.Len()));
+ dest.ReleaseBuf_SetEnd((unsigned)destLen);
}
diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h
index 16b02fe4..827f3dcf 100644
--- a/CPP/Common/UTFConvert.h
+++ b/CPP/Common/UTFConvert.h
@@ -5,8 +5,8 @@
#include "MyString.h"
-bool CheckUTF8(const char *src) throw();
+bool CheckUTF8(const char *src, bool allowReduced = false) throw();
bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString);
-bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString);
+void ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString);
#endif
diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp
index 9614f63d..a83f9f10 100644
--- a/CPP/Common/Wildcard.cpp
+++ b/CPP/Common/Wildcard.cpp
@@ -15,22 +15,8 @@ bool g_CaseSensitive =
bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)
{
if (g_CaseSensitive)
- {
- for (;;)
- {
- wchar_t c2 = *s2++; if (c2 == 0) return true;
- wchar_t c1 = *s1++;
- if (MyCharUpper(c1) !=
- MyCharUpper(c2))
- return false;
- }
- }
-
- for (;;)
- {
- wchar_t c2 = *s2++; if (c2 == 0) return true;
- wchar_t c1 = *s1++; if (c1 != c2) return false;
- }
+ return IsString1PrefixedByString2(s1, s2);
+ return IsString1PrefixedByString2_NoCase(s1, s2);
}
int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW
@@ -97,7 +83,7 @@ void SplitPathToParts(const UString &path, UStringVector &pathParts)
UString name;
unsigned prev = 0;
for (unsigned i = 0; i < len; i++)
- if (IsCharDirLimiter(path[i]))
+ if (IsPathSepar(path[i]))
{
name.SetFrom(path.Ptr(prev), i - prev);
pathParts.Add(name);
@@ -112,7 +98,7 @@ void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name)
const wchar_t *start = path;
const wchar_t *p = start + path.Len();
for (; p != start; p--)
- if (IsCharDirLimiter(*(p - 1)))
+ if (IsPathSepar(*(p - 1)))
break;
dirPrefix.SetFrom(path, (unsigned)(p - start));
name = p;
@@ -124,10 +110,10 @@ void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &na
const wchar_t *p = start + path.Len();
if (p != start)
{
- if (IsCharDirLimiter(*(p - 1)))
+ if (IsPathSepar(*(p - 1)))
p--;
for (; p != start; p--)
- if (IsCharDirLimiter(*(p - 1)))
+ if (IsPathSepar(*(p - 1)))
break;
}
dirPrefix.SetFrom(path, (unsigned)(p - start));
@@ -139,7 +125,7 @@ UString ExtractDirPrefixFromPath(const UString &path)
const wchar_t *start = path;
const wchar_t *p = start + path.Len();
for (; p != start; p--)
- if (IsCharDirLimiter(*(p - 1)))
+ if (IsPathSepar(*(p - 1)))
break;
return path.Left((unsigned)(p - start));
}
@@ -149,7 +135,7 @@ UString ExtractFileNameFromPath(const UString &path)
const wchar_t *start = path;
const wchar_t *p = start + path.Len();
for (; p != start; p--)
- if (IsCharDirLimiter(*(p - 1)))
+ if (IsPathSepar(*(p - 1)))
break;
return p;
}
@@ -177,15 +163,6 @@ bool DoesNameContainWildcard(const UString &path)
namespace NWildcard {
-
-#ifdef _WIN32
-bool IsDriveColonName(const wchar_t *s)
-{
- wchar_t c = s[0];
- return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
-}
-#endif
-
/*
M = MaskParts.Size();
@@ -212,6 +189,19 @@ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const
{
if (!isFile && !ForDir)
return false;
+
+ /*
+ if (PathParts.IsEmpty())
+ {
+ // PathParts.IsEmpty() means all items (universal wildcard)
+ if (!isFile)
+ return true;
+ if (pathParts.Size() <= 1)
+ return ForFile;
+ return (ForDir || Recursive && ForFile);
+ }
+ */
+
int delta = (int)pathParts.Size() - (int)PathParts.Size();
if (delta < 0)
return false;
@@ -286,7 +276,7 @@ void CCensorNode::AddItemSimple(bool include, CItem &item)
ExcludeItems.Add(item);
}
-void CCensorNode::AddItem(bool include, CItem &item)
+void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex)
{
if (item.PathParts.Size() <= 1)
{
@@ -300,9 +290,10 @@ void CCensorNode::AddItem(bool include, CItem &item)
}
const UString &front = item.PathParts.Front();
- // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name
- // if (item.Wildcard)
- if (DoesNameContainWildcard(front))
+ // WIN32 doesn't support wildcards in file names
+ if (item.WildcardMatching
+ && ignoreWildcardIndex != 0
+ && DoesNameContainWildcard(front))
{
AddItemSimple(include, item);
return;
@@ -311,7 +302,7 @@ void CCensorNode::AddItem(bool include, CItem &item)
if (index < 0)
index = SubNodes.Add(CCensorNode(front, this));
item.PathParts.Delete(0);
- SubNodes[index].AddItem(include, item);
+ SubNodes[index].AddItem(include, item, ignoreWildcardIndex - 1);
}
void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching)
@@ -377,6 +368,7 @@ bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, boo
return finded;
}
+/*
bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const
{
UStringVector pathParts;
@@ -406,6 +398,7 @@ bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile)
return include;
return false;
}
+*/
bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const
{
@@ -433,7 +426,7 @@ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bo
bool forFile = true;
bool forFolder = true;
UString path2 = path;
- if (IsCharDirLimiter(path.Back()))
+ if (IsPathSepar(path.Back()))
{
path2.DeleteBack();
forFile = false;
@@ -462,12 +455,90 @@ int CCensor::FindPrefix(const UString &prefix) const
return -1;
}
+#ifdef _WIN32
+
+bool IsDriveColonName(const wchar_t *s)
+{
+ wchar_t c = s[0];
+ return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
+}
+
+unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts)
+{
+ if (pathParts.IsEmpty())
+ return 0;
+
+ unsigned testIndex = 0;
+ if (pathParts[0].IsEmpty())
+ {
+ if (pathParts.Size() < 4
+ || !pathParts[1].IsEmpty()
+ || pathParts[2] != L"?")
+ return 0;
+ testIndex = 3;
+ }
+ if (NWildcard::IsDriveColonName(pathParts[testIndex]))
+ return testIndex + 1;
+ return 0;
+}
+
+#endif
+
+static unsigned GetNumPrefixParts(const UStringVector pathParts)
+{
+ if (pathParts.IsEmpty())
+ return 0;
+
+ #ifdef _WIN32
+
+ if (IsDriveColonName(pathParts[0]))
+ return 1;
+ if (!pathParts[0].IsEmpty())
+ return 0;
+
+ if (pathParts.Size() == 1)
+ return 1;
+ if (!pathParts[1].IsEmpty())
+ return 1;
+ if (pathParts.Size() == 2)
+ return 2;
+ if (pathParts[2] == L".")
+ return 3;
+
+ unsigned networkParts = 2;
+ if (pathParts[2] == L"?")
+ {
+ if (pathParts.Size() == 3)
+ return 3;
+ if (IsDriveColonName(pathParts[3]))
+ return 4;
+ if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC"))
+ return 3;
+ networkParts = 4;
+ }
+
+ networkParts +=
+ // 2; // server/share
+ 1; // server
+ if (pathParts.Size() <= networkParts)
+ return pathParts.Size();
+ return networkParts;
+
+ #else
+
+ return pathParts[0].IsEmpty() ? 1 : 0;
+
+ #endif
+}
+
void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching)
{
- UStringVector pathParts;
if (path.IsEmpty())
throw "Empty file path";
+
+ UStringVector pathParts;
SplitPathToParts(path, pathParts);
+
bool forFile = true;
if (pathParts.Back().IsEmpty())
{
@@ -477,74 +548,55 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat
UString prefix;
+ int ignoreWildcardIndex = -1;
+
+ // #ifdef _WIN32
+ // we ignore "?" wildcard in "\\?\" prefix.
+ if (pathParts.Size() >= 3
+ && pathParts[0].IsEmpty()
+ && pathParts[1].IsEmpty()
+ && pathParts[2] == L"?")
+ ignoreWildcardIndex = 2;
+ // #endif
+
if (pathMode != k_AbsPath)
{
- const UString &front = pathParts.Front();
- bool isAbs = false;
-
- if (front.IsEmpty())
- isAbs = true;
- else
+ ignoreWildcardIndex = -1;
+
+ const unsigned numPrefixParts = GetNumPrefixParts(pathParts);
+ unsigned numSkipParts = numPrefixParts;
+
+ if (pathMode != k_FullPath)
{
- #ifdef _WIN32
-
- if (IsDriveColonName(front))
- isAbs = true;
- else
-
- #endif
-
- FOR_VECTOR (i, pathParts)
- {
- const UString &part = pathParts[i];
- if (part == L".." || part == L".")
- {
- isAbs = true;
- break;
- }
- }
+ if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts)
+ numSkipParts = pathParts.Size() - 1;
}
-
- unsigned numAbsParts = 0;
- if (isAbs)
- if (pathParts.Size() > 1)
- numAbsParts = pathParts.Size() - 1;
- else
- numAbsParts = 1;
-
- #ifdef _WIN32
-
- // \\?\ case
- if (numAbsParts >= 3)
{
- if (pathParts[0].IsEmpty() &&
- pathParts[1].IsEmpty() &&
- pathParts[2] == L"?")
+ int dotsIndex = -1;
+ for (unsigned i = numPrefixParts; i < pathParts.Size(); i++)
{
- prefix =
- WSTRING_PATH_SEPARATOR
- WSTRING_PATH_SEPARATOR L"?"
- WSTRING_PATH_SEPARATOR;
- numAbsParts -= 3;
- pathParts.DeleteFrontal(3);
+ const UString &part = pathParts[i];
+ if (part == L".." || part == L".")
+ dotsIndex = i;
}
+
+ if (dotsIndex >= 0)
+ if (dotsIndex == (int)pathParts.Size() - 1)
+ numSkipParts = pathParts.Size();
+ else
+ numSkipParts = pathParts.Size() - 1;
}
-
- #endif
-
- if (numAbsParts > 1 && pathMode == k_FullPath)
- numAbsParts = 1;
-
- // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name
- // if (wildcardMatching)
- for (unsigned i = 0; i < numAbsParts; i++)
+
+ for (unsigned i = 0; i < numSkipParts; i++)
{
{
const UString &front = pathParts.Front();
- if (DoesNameContainWildcard(front))
- break;
+ // WIN32 doesn't support wildcards in file names
+ if (wildcardMatching)
+ if (i >= numPrefixParts && DoesNameContainWildcard(front))
+ break;
prefix += front;
- prefix += WCHAR_PATH_SEPARATOR;
+ prefix.Add_PathSepar();
}
pathParts.Delete(0);
}
@@ -554,15 +606,29 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat
if (index < 0)
index = Pairs.Add(CPair(prefix));
+ if (pathMode != k_AbsPath)
+ {
+ if (pathParts.IsEmpty() || pathParts.Size() == 1 && pathParts[0].IsEmpty())
+ {
+ // we create universal item, if we skip all parts as prefix (like \ or L:\ )
+ pathParts.Clear();
+ pathParts.Add(L"*");
+ forFile = true;
+ wildcardMatching = true;
+ recursive = false;
+ }
+ }
+
CItem item;
item.PathParts = pathParts;
item.ForDir = true;
item.ForFile = forFile;
item.Recursive = recursive;
item.WildcardMatching = wildcardMatching;
- Pairs[index].Head.AddItem(include, item);
+ Pairs[index].Head.AddItem(include, item, ignoreWildcardIndex);
}
+/*
bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const
{
bool finded = false;
@@ -578,6 +644,7 @@ bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) cons
}
return finded;
}
+*/
void CCensor::ExtendExclude()
{
diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h
index b9971202..512687d1 100644
--- a/CPP/Common/Wildcard.h
+++ b/CPP/Common/Wildcard.h
@@ -12,15 +12,6 @@ int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW;
bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2);
-inline bool IsCharDirLimiter(wchar_t c)
-{
- return c == WCHAR_PATH_SEPARATOR
- #ifdef _WIN32
- || c == L'/'
- #endif
- ;
-}
-
void SplitPathToParts(const UString &path, UStringVector &pathParts);
void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name);
void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path)
@@ -36,9 +27,9 @@ namespace NWildcard {
#ifdef _WIN32
// returns true, if name is like "a:", "c:", ...
bool IsDriveColonName(const wchar_t *s);
+unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts);
#endif
-
struct CItem
{
UStringVector PathParts;
@@ -66,12 +57,13 @@ class CCensorNode
bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;
void AddItemSimple(bool include, CItem &item);
- bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;
public:
+ bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;
+
CCensorNode(): Parent(0) { };
CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { };
- UString Name; // wildcard is not allowed here
+ UString Name; // WIN32 doesn't support wildcards in file names
CObjectVector<CCensorNode> SubNodes;
CObjectVector<CItem> IncludeItems;
CObjectVector<CItem> ExcludeItems;
@@ -80,15 +72,15 @@ public:
int FindSubNode(const UString &path) const;
- void AddItem(bool include, CItem &item);
+ void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1);
void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching);
void AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching);
bool NeedCheckSubDirs() const;
bool AreThereIncludeItems() const;
- bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const;
- bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
+ // bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const;
+ // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const;
// bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;
@@ -136,7 +128,7 @@ public:
{ return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }
void AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching);
- bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
+ // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
void ExtendExclude();
void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode);
diff --git a/CPP/Common/XzCrc64Reg.cpp b/CPP/Common/XzCrc64Reg.cpp
index 58413797..d1a51338 100644
--- a/CPP/Common/XzCrc64Reg.cpp
+++ b/CPP/Common/XzCrc64Reg.cpp
@@ -7,7 +7,6 @@
#include "../Common/MyCom.h"
-#include "../7zip/ICoder.h"
#include "../7zip/Common/RegisterCodec.h"
class CXzCrc64Hasher:
@@ -15,40 +14,29 @@ class CXzCrc64Hasher:
public CMyUnknownImp
{
UInt64 _crc;
+ Byte mtDummy[1 << 7];
+
public:
CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {}
MY_UNKNOWN_IMP
-
- STDMETHOD_(void, Init)();
- STDMETHOD_(void, Update)(const void *data, UInt32 size);
- STDMETHOD_(void, Final)(Byte *digest);
- STDMETHOD_(UInt32, GetDigestSize)();
+ INTERFACE_IHasher(;)
};
-STDMETHODIMP_(void) CXzCrc64Hasher::Init()
+STDMETHODIMP_(void) CXzCrc64Hasher::Init() throw()
{
_crc = CRC64_INIT_VAL;
}
-STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size)
+STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size) throw()
{
_crc = Crc64Update(_crc, data, size);
}
-STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest)
+STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest) throw()
{
UInt64 val = CRC64_GET_DIGEST(_crc);
SetUi64(digest, val);
}
-STDMETHODIMP_(UInt32) CXzCrc64Hasher::GetDigestSize()
-{
- return 8;
-}
-
-static IHasher *CreateHasher() { return new CXzCrc64Hasher; }
-
-static CHasherInfo g_HasherInfo = { CreateHasher, 0x4, L"CRC64", 8 };
-
-REGISTER_HASHER(Crc64)
+REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8)
diff --git a/CPP/Windows/COM.cpp b/CPP/Windows/COM.cpp
index 061ec34e..d0cb3211 100644
--- a/CPP/Windows/COM.cpp
+++ b/CPP/Windows/COM.cpp
@@ -14,11 +14,11 @@ namespace NCOM {
UString GUIDToStringW(REFGUID guid)
{
- UString string;
- const int kStringSize = 48;
- StringFromGUID2(guid, string.GetBuffer(kStringSize), kStringSize);
- string.ReleaseBuffer();
- return string;
+ UString s;
+ const unsigned kSize = 48;
+ StringFromGUID2(guid, s.GetBuf(kSize), kSize);
+ s.ReleaseBuf_CalcLen(kSize);
+ return s;
}
AString GUIDToStringA(REFGUID guid)
diff --git a/CPP/Windows/COM.h b/CPP/Windows/COM.h
index eedcfa9d..cee7f702 100644
--- a/CPP/Windows/COM.h
+++ b/CPP/Windows/COM.h
@@ -22,7 +22,7 @@ public:
CoInitialize(NULL);
#endif
};
- ~CComInitializer() { CoUninitialize(); };
+ ~CComInitializer() { CoUninitialize(); }
};
class CStgMedium
@@ -45,6 +45,7 @@ public:
#endif
+/*
//////////////////////////////////
// GUID <--> String Conversions
UString GUIDToStringW(REFGUID guid);
@@ -62,6 +63,7 @@ HRESULT StringToGUIDA(const char *string, GUID &classID);
#else
#define StringToGUID StringToGUIDA
#endif
+*/
}}
diff --git a/CPP/Windows/Console.h b/CPP/Windows/Console.h
index f2e8c293..43e02fa6 100644
--- a/CPP/Windows/Console.h
+++ b/CPP/Windows/Console.h
@@ -13,7 +13,7 @@ class CBase
protected:
HANDLE m_Object;
public:
- void Attach(HANDLE handle) { m_Object = handle; };
+ void Attach(HANDLE handle) { m_Object = handle; }
bool GetMode(DWORD &mode)
{ return BOOLToBool(::GetConsoleMode(m_Object, &mode)); }
bool SetMode(DWORD mode)
diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp
index 9b458fe4..3c08309b 100644
--- a/CPP/Windows/Control/ComboBox.cpp
+++ b/CPP/Windows/Control/ComboBox.cpp
@@ -18,11 +18,15 @@ namespace NControl {
LRESULT CComboBox::GetLBText(int index, CSysString &s)
{
s.Empty();
- LRESULT len = GetLBTextLen(index);
+ LRESULT len = GetLBTextLen(index); // length, excluding the terminating null character
if (len == CB_ERR)
return len;
- len = GetLBText(index, s.GetBuffer((int)len + 1));
- s.ReleaseBuffer();
+ LRESULT len2 = GetLBText(index, s.GetBuf((unsigned)len));
+ if (len2 == CB_ERR)
+ return len;
+ if (len > len2)
+ len = len2;
+ s.ReleaseBuf_CalcLen((unsigned)len);
return len;
}
@@ -42,8 +46,12 @@ LRESULT CComboBox::GetLBText(int index, UString &s)
LRESULT len = SendMessageW(CB_GETLBTEXTLEN, index, 0);
if (len == CB_ERR)
return len;
- len = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuffer((int)len + 1));
- s.ReleaseBuffer();
+ LRESULT len2 = SendMessageW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len));
+ if (len2 == CB_ERR)
+ return len;
+ if (len > len2)
+ len = len2;
+ s.ReleaseBuf_CalcLen(len);
return len;
}
AString sa;
diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h
index b450266b..59b9f419 100644
--- a/CPP/Windows/Control/Dialog.h
+++ b/CPP/Windows/Control/Dialog.h
@@ -95,9 +95,9 @@ public:
/*
#ifdef UNDER_CE
- virtual void OnHelp(void *) { OnHelp(); };
+ virtual void OnHelp(void *) { OnHelp(); }
#else
- virtual void OnHelp(LPHELPINFO) { OnHelp(); };
+ virtual void OnHelp(LPHELPINFO) { OnHelp(); }
#endif
*/
virtual void OnHelp() {};
diff --git a/CPP/Windows/Control/Window2.h b/CPP/Windows/Control/Window2.h
index d744b3e6..7ac580cb 100644
--- a/CPP/Windows/Control/Window2.h
+++ b/CPP/Windows/Control/Window2.h
@@ -35,7 +35,7 @@ public:
virtual void OnDestroy() { PostQuitMessage(0); }
virtual void OnClose() { Destroy(); }
/*
- virtual LRESULT OnHelp(LPHELPINFO helpInfo) { OnHelp(); };
+ virtual LRESULT OnHelp(LPHELPINFO helpInfo) { OnHelp(); }
virtual LRESULT OnHelp() {};
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
virtual void OnOK() {};
diff --git a/CPP/Windows/DLL.cpp b/CPP/Windows/DLL.cpp
index cf3dd1ce..a71a8017 100644
--- a/CPP/Windows/DLL.cpp
+++ b/CPP/Windows/DLL.cpp
@@ -95,7 +95,7 @@ FString GetModuleDirPrefix()
FString s;
if (MyGetModuleFileName(s))
{
- int pos = s.ReverseFind(FCHAR_PATH_SEPARATOR);
+ int pos = s.ReverseFind_PathSepar();
if (pos >= 0)
{
s.DeleteFrom(pos + 1);
diff --git a/CPP/Windows/DLL.h b/CPP/Windows/DLL.h
index f7e5b81b..984a1d33 100644
--- a/CPP/Windows/DLL.h
+++ b/CPP/Windows/DLL.h
@@ -13,17 +13,23 @@ namespace NDLL {
#else
#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName)
#endif
-
+
+/* Win32: Don't call CLibrary::Free() and FreeLibrary() from another
+ FreeLibrary() code: detaching code in DLL entry-point or in
+ destructors of global objects in DLL module. */
+
class CLibrary
{
HMODULE _module;
+
+ // CLASS_NO_COPY(CLibrary);
public:
CLibrary(): _module(NULL) {};
~CLibrary() { Free(); }
operator HMODULE() const { return _module; }
HMODULE* operator&() { return &_module; }
- bool IsLoaded() const { return (_module != NULL); };
+ bool IsLoaded() const { return (_module != NULL); }
void Attach(HMODULE m)
{
diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp
index 7c82537d..c9de4a6c 100644
--- a/CPP/Windows/ErrorMsg.cpp
+++ b/CPP/Windows/ErrorMsg.cpp
@@ -42,20 +42,25 @@ static bool MyFormatMessage(DWORD errorCode, UString &message)
UString MyFormatMessage(DWORD errorCode)
{
- UString message;
- if (!MyFormatMessage(errorCode, message))
+ UString m;
+ if (!MyFormatMessage(errorCode, m) || m.IsEmpty())
{
- wchar_t s[16];
+ char s[16];
for (int i = 0; i < 8; i++)
{
unsigned t = errorCode & 0xF;
errorCode >>= 4;
- s[7 - i] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
- s[8] = '\0';
- message = (UString)L"Error #" + s;
+ s[8] = 0;
+ m.AddAscii("Error #");
+ m.AddAscii(s);
}
- return message;
+ else if (m.Len() >= 2
+ && m[m.Len() - 1] == 0x0A
+ && m[m.Len() - 2] == 0x0D)
+ m.DeleteFrom(m.Len() - 2);
+ return m;
}
}}
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
index e6751f85..da71b710 100644
--- a/CPP/Windows/FileDir.cpp
+++ b/CPP/Windows/FileDir.cpp
@@ -86,9 +86,9 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const
#ifdef WIN_LONG_PATH
if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
- hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
}
#endif
@@ -119,9 +119,9 @@ bool SetFileAttrib(CFSTR path, DWORD attrib)
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH)
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
- return BOOLToBool(::SetFileAttributesW(longPath, attrib));
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ return BOOLToBool(::SetFileAttributesW(superPath, attrib));
}
#endif
}
@@ -145,9 +145,9 @@ bool RemoveDir(CFSTR path)
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH)
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
- return BOOLToBool(::RemoveDirectoryW(longPath));
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ return BOOLToBool(::RemoveDirectoryW(superPath));
}
#endif
}
@@ -226,6 +226,29 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
#endif
+/*
+WinXP-64 CreateDir():
+ "" - ERROR_PATH_NOT_FOUND
+ \ - ERROR_ACCESS_DENIED
+ C:\ - ERROR_ACCESS_DENIED, if there is such drive,
+
+ D:\folder - ERROR_PATH_NOT_FOUND, if there is no such drive,
+ C:\nonExistent\folder - ERROR_PATH_NOT_FOUND
+
+ C:\existFolder - ERROR_ALREADY_EXISTS
+ C:\existFolder\ - ERROR_ALREADY_EXISTS
+
+ C:\folder - OK
+ C:\folder\ - OK
+
+ \\Server\nonExistent - ERROR_BAD_NETPATH
+ \\Server\Share_Readonly - ERROR_ACCESS_DENIED
+ \\Server\Share - ERROR_ALREADY_EXISTS
+
+ \\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED
+ \\Server\Share_FAT_drive - ERROR_ALREADY_EXISTS
+*/
+
bool CreateDir(CFSTR path)
{
#ifndef _UNICODE
@@ -243,56 +266,127 @@ bool CreateDir(CFSTR path)
#ifdef WIN_LONG_PATH
if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
- return BOOLToBool(::CreateDirectoryW(longPath, NULL));
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ return BOOLToBool(::CreateDirectoryW(superPath, NULL));
}
#endif
}
return false;
}
-bool CreateComplexDir(CFSTR _aPathName)
+/*
+ CreateDir2 returns true, if directory can contain files after the call (two cases):
+ 1) the directory already exists
+ 2) the directory was created
+ path must be WITHOUT trailing path separator.
+
+ We need CreateDir2, since fileInfo.Find() for reserved names like "com8"
+ returns FILE instead of DIRECTORY. And we need to use SuperPath */
+
+static bool CreateDir2(CFSTR path)
{
- FString pathName = _aPathName;
- int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);
- if (pos > 0 && (unsigned)pos == pathName.Len() - 1)
+ #ifndef _UNICODE
+ if (!g_IsNT)
{
- if (pathName.Len() == 3 && pathName[1] == L':')
- return true; // Disk folder;
- pathName.Delete(pos);
+ if (::CreateDirectory(fs2fas(path), NULL))
+ return true;
+ }
+ else
+ #endif
+ {
+ IF_USE_MAIN_PATH
+ if (::CreateDirectoryW(fs2us(path), NULL))
+ return true;
+ #ifdef WIN_LONG_PATH
+ if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
+ {
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ {
+ if (::CreateDirectoryW(superPath, NULL))
+ return true;
+ if (::GetLastError() != ERROR_ALREADY_EXISTS)
+ return false;
+ NFind::CFileInfo fi;
+ if (!fi.Find(us2fs(superPath)))
+ return false;
+ return fi.IsDir();
+ }
+ }
+ #endif
}
- const FString pathName2 = pathName;
- pos = pathName.Len();
+ if (::GetLastError() != ERROR_ALREADY_EXISTS)
+ return false;
+ NFind::CFileInfo fi;
+ if (!fi.Find(path))
+ return false;
+ return fi.IsDir();
+}
+
+bool CreateComplexDir(CFSTR _path)
+{
+ #ifdef _WIN32
+
+ {
+ DWORD attrib = NFind::GetFileAttrib(_path);
+ if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
+ return true;
+ }
+
+ #ifndef UNDER_CE
+
+ if (IsDriveRootPath_SuperAllowed(_path))
+ return false;
+
+ unsigned prefixSize = GetRootPrefixSize(_path);
+
+ #endif
+
+ #endif
+
+ FString path = _path;
+
+ int pos = path.ReverseFind_PathSepar();
+ if (pos >= 0 && (unsigned)pos == path.Len() - 1)
+ {
+ if (path.Len() == 1)
+ return true;
+ path.DeleteBack();
+ }
+
+ const FString path2 = path;
+ pos = path.Len();
for (;;)
{
- if (CreateDir(pathName))
+ if (CreateDir2(path))
break;
if (::GetLastError() == ERROR_ALREADY_EXISTS)
- {
- NFind::CFileInfo fileInfo;
- if (!fileInfo.Find(pathName)) // For network folders
- return true;
- if (!fileInfo.IsDir())
- return false;
- break;
- }
- pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);
+ return false;
+ pos = path.ReverseFind_PathSepar();
if (pos < 0 || pos == 0)
return false;
- if (pathName[pos - 1] == L':')
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (pos == 1 && IS_PATH_SEPAR(path[0]))
+ return false;
+ if (prefixSize >= (unsigned)pos + 1)
return false;
- pathName.DeleteFrom(pos);
+ #endif
+
+ path.DeleteFrom(pos);
}
- while (pos < (int)pathName2.Len())
+ while (pos < (int)path2.Len())
{
- pos = pathName2.Find(FCHAR_PATH_SEPARATOR, pos + 1);
- if (pos < 0)
- pos = pathName2.Len();
- pathName.SetFrom(pathName2, pos);
- if (!CreateDir(pathName))
+ int pos2 = NName::FindSepar(path2.Ptr(pos + 1));
+ if (pos2 < 0)
+ pos = path2.Len();
+ else
+ pos += 1 + pos2;
+ path.SetFrom(path2, pos);
+ if (!CreateDir(path))
return false;
}
@@ -301,8 +395,19 @@ bool CreateComplexDir(CFSTR _aPathName)
bool DeleteFileAlways(CFSTR path)
{
- if (!SetFileAttrib(path, 0))
- return false;
+ /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete.
+ SetFileAttrib("name:stream", ) changes attributes of main file. */
+ {
+ DWORD attrib = NFind::GetFileAttrib(path);
+ if (attrib != INVALID_FILE_ATTRIBUTES
+ && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0
+ && (attrib & FILE_ATTRIBUTE_READONLY) != 0)
+ {
+ if (!SetFileAttrib(path, attrib & ~FILE_ATTRIBUTE_READONLY))
+ return false;
+ }
+ }
+
#ifndef _UNICODE
if (!g_IsNT)
{
@@ -312,15 +417,17 @@ bool DeleteFileAlways(CFSTR path)
else
#endif
{
+ /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")).
+ Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */
IF_USE_MAIN_PATH
if (::DeleteFileW(fs2us(path)))
return true;
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH)
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
- return BOOLToBool(::DeleteFileW(longPath));
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ return BOOLToBool(::DeleteFileW(superPath));
}
#endif
}
@@ -346,7 +453,7 @@ bool RemoveDirWithSubItems(const FString &path)
if (needRemoveSubItems)
{
FString s = path;
- s += FCHAR_PATH_SEPARATOR;
+ s.Add_PathSepar();
unsigned prefixSize = s.Len();
s += FCHAR_ANY_MASK;
NFind::CEnumerator enumerator(s);
@@ -430,7 +537,7 @@ bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName
bool res = MyGetFullPathName(path, resDirPrefix);
if (!res)
resDirPrefix = path;
- int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR);
+ int pos = resDirPrefix.ReverseFind_PathSepar();
resFileName = resDirPrefix.Ptr(pos + 1);
resDirPrefix.DeleteFrom(pos + 1);
return res;
@@ -480,7 +587,7 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
{
unsigned t = value & 0xF;
value >>= 4;
- s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ s[k] = (FChar)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
}
s[k] = '\0';
if (outFile)
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
index 02d3e5a5..b13d1cca 100644
--- a/CPP/Windows/FileDir.h
+++ b/CPP/Windows/FileDir.h
@@ -24,7 +24,14 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName);
bool RemoveDir(CFSTR path);
bool CreateDir(CFSTR path);
+
+/* CreateComplexDir returns true, if directory can contain files after the call (two cases):
+ 1) the directory already exists (network shares and drive paths are supported)
+ 2) the directory was created
+ path can be WITH or WITHOUT trailing path separator. */
+
bool CreateComplexDir(CFSTR path);
+
bool DeleteFileAlways(CFSTR name);
bool RemoveDirWithSubItems(const FString &path);
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
index c47c6ac9..fdf77831 100644
--- a/CPP/Windows/FileFind.cpp
+++ b/CPP/Windows/FileFind.cpp
@@ -2,13 +2,14 @@
#include "StdAfx.h"
-#include "FileFind.h"
-#include "FileIO.h"
-#include "FileName.h"
#ifndef _UNICODE
#include "../Common/StringConvert.h"
#endif
+#include "FileFind.h"
+#include "FileIO.h"
+#include "FileName.h"
+
#ifndef _UNICODE
extern bool g_IsNT;
#endif
@@ -58,9 +59,9 @@ bool CFileInfo::IsDots() const throw()
{
if (!IsDir() || Name.IsEmpty())
return false;
- if (Name[0] != FTEXT('.'))
+ if (Name[0] != '.')
return false;
- return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == FTEXT('.'));
+ return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');
}
#define WIN_FD_TO_MY_FI(fi, fd) \
@@ -114,6 +115,32 @@ bool CFindFileBase::Close() throw()
return true;
}
+/*
+WinXP-64 FindFirstFile():
+ "" - ERROR_PATH_NOT_FOUND
+ folder\ - ERROR_FILE_NOT_FOUND
+ \ - ERROR_FILE_NOT_FOUND
+ c:\ - ERROR_FILE_NOT_FOUND
+ c: - ERROR_FILE_NOT_FOUND, if current dir is ROOT ( c:\ )
+ c: - OK, if current dir is NOT ROOT ( c:\folder )
+ folder - OK
+
+ \\ - ERROR_INVALID_NAME
+ \\Server - ERROR_INVALID_NAME
+ \\Server\ - ERROR_INVALID_NAME
+
+ \\Server\Share - ERROR_BAD_NETPATH
+ \\Server\Share\ - ERROR_FILE_NOT_FOUND
+
+ \\?\UNC\Server\Share - ERROR_INVALID_NAME
+ \\?\UNC\Server\Share\ - ERROR_FILE_NOT_FOUND
+
+ \\Server\Share_RootDrive - ERROR_INVALID_NAME
+ \\Server\Share_RootDrive\ - ERROR_INVALID_NAME
+
+ c:\* - ERROR_FILE_NOT_FOUND, if thare are no item in that folder
+*/
+
bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)
{
if (!Close())
@@ -137,9 +164,9 @@ bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)
#ifdef WIN_LONG_PATH
if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
- _handle = ::FindFirstFileW(longPath, &fd);
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ _handle = ::FindFirstFileW(superPath, &fd);
}
#endif
if (_handle == INVALID_HANDLE_VALUE)
@@ -189,17 +216,27 @@ struct CFindStreamLoader
bool CStreamInfo::IsMainStream() const throw()
{
- return Name == L"::$DATA";
+ return StringsAreEqualNoCase_Ascii(Name, "::$DATA");
};
UString CStreamInfo::GetReducedName() const
{
+ // remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA"
UString s = Name;
- if (s.Len() >= 6)
- if (wcscmp(s.RightPtr(6), L":$DATA") == 0)
- s.DeleteFrom(s.Len() - 6);
+ if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA"))
+ s.DeleteFrom(s.Len() - 6);
+ return s;
+}
+
+/*
+UString CStreamInfo::GetReducedName2() const
+{
+ UString s = GetReducedName();
+ if (!s.IsEmpty() && s[0] == ':')
+ s.Delete(0);
return s;
}
+*/
static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si)
{
@@ -207,6 +244,23 @@ static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STR
si.Name = sd.cStreamName;
}
+/*
+ WinXP-64 FindFirstStream():
+ "" - ERROR_PATH_NOT_FOUND
+ folder\ - OK
+ folder - OK
+ \ - OK
+ c:\ - OK
+ c: - OK, if current dir is ROOT ( c:\ )
+ c: - OK, if current dir is NOT ROOT ( c:\folder )
+ \\Server\Share - OK
+ \\Server\Share\ - OK
+
+ \\ - ERROR_INVALID_NAME
+ \\Server - ERROR_INVALID_NAME
+ \\Server\ - ERROR_INVALID_NAME
+*/
+
bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
{
if (!Close())
@@ -218,6 +272,7 @@ bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
}
{
MY_WIN32_FIND_STREAM_DATA sd;
+ SetLastError(0);
IF_USE_MAIN_PATH
_handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0);
if (_handle == INVALID_HANDLE_VALUE)
@@ -228,9 +283,9 @@ bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH)
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
- _handle = g_FindFirstStreamW(longPath, My_FindStreamInfoStandard, &sd, 0);
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ _handle = g_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0);
}
#endif
}
@@ -278,7 +333,7 @@ bool CStreamEnumerator::Next(CStreamInfo &si, bool &found)
#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;
-void CFileInfoBase::Clear() throw()
+void CFileInfoBase::ClearBase() throw()
{
Size = 0;
MY_CLEAR_FILETIME(CTime);
@@ -289,43 +344,83 @@ void CFileInfoBase::Clear() throw()
IsDevice = false;
}
-#if defined(_WIN32) && !defined(UNDER_CE)
+/*
+WinXP-64 GetFileAttributes():
+ If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code
-static int FindAltStreamColon(CFSTR path)
+ \ - OK
+ C:\ - OK, if there is such drive,
+ D:\ - ERROR_PATH_NOT_FOUND, if there is no such drive,
+
+ C:\folder - OK
+ C:\folder\ - OK
+ C:\folderBad - ERROR_FILE_NOT_FOUND
+
+ \\Server\BadShare - ERROR_BAD_NETPATH
+ \\Server\Share - WORKS OK, but MSDN says:
+ GetFileAttributes for a network share, the function fails, and GetLastError
+ returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.
+*/
+
+DWORD GetFileAttrib(CFSTR path)
{
- for (int i = 0;; i++)
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ return ::GetFileAttributes(fs2fas(path));
+ else
+ #endif
{
- FChar c = path[i];
- if (c == 0)
- return -1;
- if (c == ':')
+ IF_USE_MAIN_PATH
{
- if (path[i + 1] == '\\')
- if (i == 1 || (i > 1 && path[i - 2] == '\\'))
- {
- wchar_t c0 = path[i - 1];
- if (c0 >= 'a' && c0 <= 'z' ||
- c0 >= 'A' && c0 <= 'Z')
- continue;
- }
- return i;
+ DWORD dw = ::GetFileAttributesW(fs2us(path));
+ if (dw != INVALID_FILE_ATTRIBUTES)
+ return dw;
+ }
+ #ifdef WIN_LONG_PATH
+ if (USE_SUPER_PATH)
+ {
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ return ::GetFileAttributesW(superPath);
}
+ #endif
+ return INVALID_FILE_ATTRIBUTES;
}
}
-#endif
+/* if path is "c:" or "c::" then CFileInfo::Find() returns name of current folder for that disk
+ so instead of absolute path we have relative path in Name. That is not good in some calls */
+
+/* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */
+
+/* CFileInfo::Find()
+We alow the following paths (as FindFirstFile):
+ C:\folder
+ c: - if current dir is NOT ROOT ( c:\folder )
+
+also we support paths that are not supported by FindFirstFile:
+ \
+ \\.\c:
+ c:\ - Name will be without tail slash ( c: )
+ \\?\c:\ - Name will be without tail slash ( c: )
+ \\Server\Share
+ \\?\UNC\Server\Share
+
+ c:\folder:stream - Name = folder:stream
+ c:\:stream - Name = :stream
+ c::stream - Name = c::stream
+*/
bool CFileInfo::Find(CFSTR path)
{
#ifdef SUPPORT_DEVICE_FILE
if (IsDevicePath(path))
{
- Clear();
+ ClearBase();
Name = path + 4;
-
IsDevice = true;
- if (/* path[0] == '\\' && path[1] == '\\' && path[2] == '.' && path[3] == '\\' && */
- path[5] == ':' && path[6] == 0)
+
+ if (NName::IsDrivePath2(path + 4) && path[6] == 0)
{
FChar drive[4] = { path[4], ':', '\\', 0 };
UInt64 clusterSize, totalSize, freeSize;
@@ -350,16 +445,37 @@ bool CFileInfo::Find(CFSTR path)
#if defined(_WIN32) && !defined(UNDER_CE)
int colonPos = FindAltStreamColon(path);
- if (colonPos >= 0)
+ if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0)
{
UString streamName = fs2us(path + (unsigned)colonPos);
FString filePath = path;
filePath.DeleteFrom(colonPos);
- streamName += L":$DATA"; // change it!!!!
- if (Find(filePath))
+ /* we allow both cases:
+ name:stream
+ name:stream:$DATA
+ */
+ const unsigned kPostfixSize = 6;
+ if (streamName.Len() <= kPostfixSize
+ || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA"))
+ streamName += L":$DATA";
+
+ bool isOk = true;
+
+ if (IsDrivePath2(filePath) &&
+ (colonPos == 2 || colonPos == 3 && filePath[2] == '\\'))
{
- // if (IsDir())
- Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;
+ // FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT)
+ ClearBase();
+ Name.Empty();
+ if (colonPos == 2)
+ Name = filePath;
+ }
+ else
+ isOk = Find(filePath);
+
+ if (isOk)
+ {
+ Attrib &= ~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
Size = 0;
CStreamEnumerator enumerator(filePath);
for (;;)
@@ -373,10 +489,12 @@ bool CFileInfo::Find(CFSTR path)
::SetLastError(ERROR_FILE_NOT_FOUND);
return false;
}
- if (si.Name.IsEqualToNoCase(streamName))
+ if (si.Name.IsEqualTo_NoCase(streamName))
{
+ // we delete postfix, if alt stream name is not "::$DATA"
+ if (si.Name.Len() > kPostfixSize + 1)
+ si.Name.DeleteFrom(si.Name.Len() - kPostfixSize);
Name += us2fs(si.Name);
- Name.DeleteFrom(Name.Len() - 6);
Size = si.Size;
IsAltStream = true;
return true;
@@ -390,7 +508,8 @@ bool CFileInfo::Find(CFSTR path)
CFindFile finder;
if (finder.FindFirst(path, *this))
return true;
- #ifdef _WIN32
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
{
DWORD lastError = GetLastError();
if (lastError == ERROR_BAD_NETPATH ||
@@ -398,33 +517,68 @@ bool CFileInfo::Find(CFSTR path)
lastError == ERROR_INVALID_NAME // for "\\SERVER\shared" paths that are translated to "\\?\UNC\SERVER\shared"
)
{
- unsigned len = MyStringLen(path);
- if (len > 2 && path[0] == '\\' && path[1] == '\\')
+ unsigned rootSize = 0;
+ if (IsSuperPath(path))
+ rootSize = kSuperPathPrefixSize;
+ if (IS_PATH_SEPAR(path[0]) && path[1] == 0)
{
- int startPos = 2;
- if (len > kSuperUncPathPrefixSize && IsSuperUncPath(path))
- startPos = kSuperUncPathPrefixSize;
- int pos = FindCharPosInString(path + startPos, FTEXT('\\'));
- if (pos >= 0)
+ DWORD attrib = GetFileAttrib(path);
+ if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
- pos += startPos + 1;
- len -= pos;
- int pos2 = FindCharPosInString(path + pos, FTEXT('\\'));
- if (pos2 < 0 || pos2 == (int)len - 1)
+ ClearBase();
+ Name.Empty();
+ Attrib = attrib;
+ return true;
+ }
+ }
+ else if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0)
+ {
+ DWORD attrib = GetFileAttrib(path);
+ if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
+ {
+ ClearBase();
+ Attrib = attrib;
+ Name = path + rootSize;
+ Name.DeleteFrom(2); // we don't need backslash (C:)
+ return true;
+ }
+ }
+ else
+ {
+ unsigned prefixSize = GetNetworkServerPrefixSize(path);
+ if (prefixSize > 0 && path[prefixSize] != 0)
+ {
+ if (NName::FindSepar(path + prefixSize) < 0)
{
FString s = path;
- if (pos2 < 0)
- {
- pos2 = len;
- s += FTEXT('\\');
- }
+ s.Add_PathSepar();
s += FCHAR_ANY_MASK;
+
+ bool isOK = false;
if (finder.FindFirst(s, *this))
+ {
if (Name == FTEXT("."))
{
- Name.SetFrom(s.Ptr(pos), pos2);
+ Name = path + prefixSize;;
+ return true;
+ }
+ isOK = true;
+ /* if "\\server\share" maps to root folder "d:\", there is no "." item.
+ But it's possible that there are another items */
+ }
+ {
+ DWORD attrib = GetFileAttrib(path);
+ if (isOK || attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
+ {
+ ClearBase();
+ if (attrib != INVALID_FILE_ATTRIBUTES)
+ Attrib = attrib;
+ else
+ SetAsDir();
+ Name = path + prefixSize;
return true;
}
+ }
::SetLastError(lastError);
}
}
@@ -432,6 +586,7 @@ bool CFileInfo::Find(CFSTR path)
}
}
#endif
+
return false;
}
@@ -446,12 +601,14 @@ bool DoesDirExist(CFSTR name)
CFileInfo fi;
return fi.Find(name) && fi.IsDir();
}
+
bool DoesFileOrDirExist(CFSTR name)
{
CFileInfo fi;
return fi.Find(name);
}
+
bool CEnumerator::NextAny(CFileInfo &fi)
{
if (_findFile.IsHandleAllocated())
@@ -509,9 +666,9 @@ HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD n
#ifdef WIN_LONG_PATH
if (!IsHandleAllocated())
{
- UString longPath;
- if (GetSuperPath(path, longPath, USE_MAIN_PATH))
- _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
+ UString superPath;
+ if (GetSuperPath(path, superPath, USE_MAIN_PATH))
+ _handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter);
}
#endif
}
@@ -530,23 +687,22 @@ bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)
UINT32 size = GetLogicalDriveStrings(0, NULL);
if (size == 0)
return false;
- AString buf;
- UINT32 newSize = GetLogicalDriveStrings(size, buf.GetBuffer(size));
+ CObjArray<char> buf(size);
+ UINT32 newSize = GetLogicalDriveStrings(size, buf);
if (newSize == 0 || newSize > size)
return false;
AString s;
+ UINT32 prev = 0;
for (UINT32 i = 0; i < newSize; i++)
{
- char c = buf[i];
- if (c == '\0')
+ if (buf[i] == 0)
{
+ s = buf + prev;
+ prev = i + 1;
driveStrings.Add(fas2fs(s));
- s.Empty();
}
- else
- s += c;
}
- return s.IsEmpty();
+ return prev == newSize;;
}
else
#endif
@@ -554,23 +710,22 @@ bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)
UINT32 size = GetLogicalDriveStringsW(0, NULL);
if (size == 0)
return false;
- UString buf;
- UINT32 newSize = GetLogicalDriveStringsW(size, buf.GetBuffer(size));
+ CObjArray<wchar_t> buf(size);
+ UINT32 newSize = GetLogicalDriveStringsW(size, buf);
if (newSize == 0 || newSize > size)
return false;
UString s;
+ UINT32 prev = 0;
for (UINT32 i = 0; i < newSize; i++)
{
- WCHAR c = buf[i];
- if (c == L'\0')
+ if (buf[i] == 0)
{
+ s = buf + prev;
+ prev = i + 1;
driveStrings.Add(us2fs(s));
- s.Empty();
}
- else
- s += c;
}
- return s.IsEmpty();
+ return prev == newSize;
}
}
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
index aaa7499b..615c2dfe 100644
--- a/CPP/Windows/FileFind.h
+++ b/CPP/Windows/FileFind.h
@@ -41,8 +41,8 @@ public:
#endif
*/
- CFileInfoBase() { Clear(); }
- void Clear() throw();
+ CFileInfoBase() { ClearBase(); }
+ void ClearBase() throw();
void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; }
@@ -68,7 +68,7 @@ struct CFileInfo: public CFileInfoBase
#endif
bool IsDots() const throw();
- bool Find(CFSTR wildcard);
+ bool Find(CFSTR path);
};
class CFindFileBase
@@ -96,7 +96,8 @@ struct CStreamInfo
UString Name;
UInt64 Size;
- UString GetReducedName() const;
+ UString GetReducedName() const; // returns ":Name"
+ // UString GetReducedName2() const; // returns "Name"
bool IsMainStream() const throw();
};
@@ -124,6 +125,8 @@ bool DoesFileExist(CFSTR name);
bool DoesDirExist(CFSTR name);
bool DoesFileOrDirExist(CFSTR name);
+DWORD GetFileAttrib(CFSTR path);
+
class CEnumerator
{
CFindFile _findFile;
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
index ea692a3d..56e6ca45 100644
--- a/CPP/Windows/FileIO.cpp
+++ b/CPP/Windows/FileIO.cpp
@@ -130,7 +130,7 @@ bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition
if (low == 0xFFFFFFFF)
if (::GetLastError() != NO_ERROR)
return false;
- newPosition = (((UInt64)high) << 32) + low;
+ newPosition = (((UInt64)(UInt32)high) << 32) + low;
return true;
}
diff --git a/CPP/Windows/FileLink.cpp b/CPP/Windows/FileLink.cpp
index e65566fd..25d49ac3 100644
--- a/CPP/Windows/FileLink.cpp
+++ b/CPP/Windows/FileLink.cpp
@@ -102,6 +102,8 @@ void WriteString(Byte *dest, const wchar_t *path)
}
}
+#if defined(_WIN32) && !defined(UNDER_CE)
+
bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
{
bool isAbs = IsAbsolutePath(path);
@@ -175,13 +177,21 @@ bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink)
return true;
}
+#endif
+
static void GetString(const Byte *p, unsigned len, UString &res)
{
- wchar_t *s = res.GetBuffer(len);
- for (unsigned i = 0; i < len; i++)
- s[i] = Get16(p + i * 2);
- s[len] = 0;
- res.ReleaseBuffer();
+ wchar_t *s = res.GetBuf(len);
+ unsigned i;
+ for (i = 0; i < len; i++)
+ {
+ wchar_t c = Get16(p + i * 2);
+ if (c == 0)
+ break;
+ s[i] = c;
+ }
+ s[i] = 0;
+ res.ReleaseBuf_SetLen(i);
}
bool CReparseAttr::Parse(const Byte *p, size_t size)
@@ -367,7 +377,7 @@ bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMA
static bool CreatePrefixDirOfFile(CFSTR path)
{
FString path2 = path;
- int pos = path2.ReverseFind(FCHAR_PATH_SEPARATOR);
+ int pos = path2.ReverseFind_PathSepar();
if (pos < 0)
return true;
#ifdef _WIN32
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
index 6f0f6bce..382c2e56 100644
--- a/CPP/Windows/FileName.cpp
+++ b/CPP/Windows/FileName.cpp
@@ -12,13 +12,41 @@ namespace NWindows {
namespace NFile {
namespace NName {
+#define IS_SEPAR(c) IS_PATH_SEPAR(c)
+
+int FindSepar(const wchar_t *s) throw()
+{
+ for (const wchar_t *p = s;; p++)
+ {
+ const wchar_t c = *p;
+ if (c == 0)
+ return -1;
+ if (IS_SEPAR(c))
+ return (int)(p - s);
+ }
+}
+
+#ifndef USE_UNICODE_FSTRING
+int FindSepar(const FChar *s) throw()
+{
+ for (const FChar *p = s;; p++)
+ {
+ const FChar c = *p;
+ if (c == 0)
+ return -1;
+ if (IS_SEPAR(c))
+ return (int)(p - s);
+ }
+}
+#endif
+
#ifndef USE_UNICODE_FSTRING
void NormalizeDirPathPrefix(FString &dirPath)
{
if (dirPath.IsEmpty())
return;
- if (dirPath.Back() != FCHAR_PATH_SEPARATOR)
- dirPath += FCHAR_PATH_SEPARATOR;
+ if (!IsPathSepar(dirPath.Back()))
+ dirPath.Add_PathSepar();
}
#endif
@@ -26,26 +54,51 @@ void NormalizeDirPathPrefix(UString &dirPath)
{
if (dirPath.IsEmpty())
return;
- if (dirPath.Back() != WCHAR_PATH_SEPARATOR)
- dirPath += WCHAR_PATH_SEPARATOR;
+ if (!IsPathSepar(dirPath.Back()))
+ dirPath.Add_PathSepar();
}
+#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
-#ifdef _WIN32
+bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
+
+bool IsAltPathPrefix(CFSTR s) throw()
+{
+ unsigned len = MyStringLen(s);
+ if (len == 0)
+ return false;
+ if (s[len - 1] != ':')
+ return false;
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (IsDevicePath(s))
+ return false;
+ if (IsSuperPath(s))
+ {
+ s += kSuperPathPrefixSize;
+ len -= kSuperPathPrefixSize;
+ }
+ if (len == 2 && IsDrivePath2(s))
+ return false;
+ #endif
+
+ return true;
+}
+
+#if defined(_WIN32) && !defined(UNDER_CE)
const wchar_t *kSuperPathPrefix = L"\\\\?\\";
static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\";
-#define IS_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\')
-#define IS_SUPER_PREFIX(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '?' && (s)[3] == '\\')
-#define IS_SUPER_OR_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && ((s)[2] == '?' || (s)[2] == '.') && (s)[3] == '\\')
-#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
+#define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))
+#define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))
+#define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3]))
#define IS_UNC_WITH_SLASH(s) ( \
- ((s)[0] == 'U' || (s)[0] == 'u') && \
- ((s)[1] == 'N' || (s)[1] == 'n') && \
- ((s)[2] == 'C' || (s)[2] == 'c') && \
- (s)[3] == '\\')
+ ((s)[0] == 'U' || (s)[0] == 'u') \
+ && ((s)[1] == 'N' || (s)[1] == 'n') \
+ && ((s)[2] == 'C' || (s)[2] == 'c') \
+ && IS_SEPAR((s)[3]))
bool IsDevicePath(CFSTR s) throw()
{
@@ -81,50 +134,133 @@ bool IsDevicePath(CFSTR s) throw()
}
bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
+bool IsNetworkPath(CFSTR s) throw()
+{
+ if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
+ return false;
+ if (IsSuperUncPath(s))
+ return true;
+ FChar c = s[2];
+ return (c != '.' && c != '?');
+}
-bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; }
+unsigned GetNetworkServerPrefixSize(CFSTR s) throw()
+{
+ if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
+ return 0;
+ unsigned prefixSize = 2;
+ if (IsSuperUncPath(s))
+ prefixSize = kSuperUncPathPrefixSize;
+ else
+ {
+ FChar c = s[2];
+ if (c == '.' || c == '?')
+ return 0;
+ }
+ int pos = FindSepar(s + prefixSize);
+ if (pos < 0)
+ return 0;
+ return prefixSize + pos + 1;
+}
+
+bool IsNetworkShareRootPath(CFSTR s) throw()
+{
+ unsigned prefixSize = GetNetworkServerPrefixSize(s);
+ if (prefixSize == 0)
+ return false;
+ s += prefixSize;
+ int pos = FindSepar(s);
+ if (pos < 0)
+ return true;
+ return s[(unsigned)pos + 1] == 0;
+}
+
+static const unsigned kDrivePrefixSize = 3; /* c:\ */
+
+bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
+// bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }
bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
-// bool IsSuperUncPath(const wchar_t *s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
+// bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
#ifndef USE_UNICODE_FSTRING
-bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; }
+bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
+// bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
+bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
#endif // USE_UNICODE_FSTRING
+/*
+bool IsDrivePath_SuperAllowed(CFSTR s)
+{
+ if (IsSuperPath(s))
+ s += kSuperPathPrefixSize;
+ return IsDrivePath(s);
+}
+*/
+
+bool IsDriveRootPath_SuperAllowed(CFSTR s) throw()
+{
+ if (IsSuperPath(s))
+ s += kSuperPathPrefixSize;
+ return IsDrivePath(s) && s[kDrivePrefixSize] == 0;
+}
+
bool IsAbsolutePath(const wchar_t *s) throw()
{
- return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s);
+ return IS_SEPAR(s[0]) || IsDrivePath2(s);
}
-static const unsigned kDrivePrefixSize = 3; /* c:\ */
+int FindAltStreamColon(CFSTR path)
+{
+ unsigned i = 0;
+ if (IsDrivePath2(path))
+ i = 2;
+ int colonPos = -1;
+ for (;; i++)
+ {
+ FChar c = path[i];
+ if (c == 0)
+ return colonPos;
+ if (c == ':')
+ {
+ if (colonPos < 0)
+ colonPos = i;
+ continue;
+ }
+ if (IS_SEPAR(c))
+ colonPos = -1;
+ }
+}
#ifndef USE_UNICODE_FSTRING
-static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) throw()
+static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)
{
// Network path: we look "server\path\" as root prefix
- int pos = FindCharPosInString(s, '\\');
+ int pos = FindSepar(s);
if (pos < 0)
return 0;
- int pos2 = FindCharPosInString(s + pos + 1, '\\');
+ int pos2 = FindSepar(s + (unsigned)pos + 1);
if (pos2 < 0)
return 0;
return pos + pos2 + 2;
}
-static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) throw()
+static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)
{
if (IsDrivePath(s))
return kDrivePrefixSize;
- if (s[0] != '\\' || s[1] != '\\')
+ if (!IS_SEPAR(s[0]))
return 0;
+ if (s[1] == 0 || !IS_SEPAR(s[1]))
+ return 1;
unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
return (size == 0) ? 0 : 2 + size;
}
-static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw()
+static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)
{
if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
{
@@ -132,13 +268,13 @@ static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw()
return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
}
// we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
- int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR);
+ int pos = FindSepar(s + kSuperPathPrefixSize);
if (pos < 0)
return 0;
return kSuperPathPrefixSize + pos + 1;
}
-unsigned GetRootPrefixSize(CFSTR s) throw()
+unsigned GetRootPrefixSize(CFSTR s)
{
if (IS_DEVICE_PATH(s))
return kDevicePathPrefixSize;
@@ -149,29 +285,31 @@ unsigned GetRootPrefixSize(CFSTR s) throw()
#endif // USE_UNICODE_FSTRING
-static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()
+static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s)
{
// Network path: we look "server\path\" as root prefix
- int pos = FindCharPosInString(s, L'\\');
+ int pos = FindSepar(s);
if (pos < 0)
return 0;
- int pos2 = FindCharPosInString(s + pos + 1, L'\\');
+ int pos2 = FindSepar(s + (unsigned)pos + 1);
if (pos2 < 0)
return 0;
return pos + pos2 + 2;
}
-static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()
+static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s)
{
if (IsDrivePath(s))
return kDrivePrefixSize;
- if (s[0] != '\\' || s[1] != '\\')
+ if (!IS_SEPAR(s[0]))
return 0;
+ if (s[1] == 0 || !IS_SEPAR(s[1]))
+ return 1;
unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
return (size == 0) ? 0 : 2 + size;
}
-static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
+static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s)
{
if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
{
@@ -179,7 +317,7 @@ static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
}
// we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
- int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\');
+ int pos = FindSepar(s + kSuperPathPrefixSize);
if (pos < 0)
return 0;
return kSuperPathPrefixSize + pos + 1;
@@ -196,12 +334,12 @@ unsigned GetRootPrefixSize(const wchar_t *s) throw()
#else // _WIN32
-bool IsAbsolutePath(const wchar_t *s) throw() { return s[0] == WCHAR_PATH_SEPARATOR }
+bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); }
#ifndef USE_UNICODE_FSTRING
-unsigned GetRootPrefixSize(CFSTR s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }
+unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; }
#endif
-unsigned GetRootPrefixSize(const wchar_t *s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }
+unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; }
#endif // _WIN32
@@ -234,26 +372,26 @@ static bool GetCurDir(UString &path)
static bool ResolveDotsFolders(UString &s)
{
#ifdef _WIN32
- s.Replace(L'/', WCHAR_PATH_SEPARATOR);
+ // s.Replace(L'/', WCHAR_PATH_SEPARATOR);
#endif
- for (int i = 0;;)
+ for (unsigned i = 0;;)
{
wchar_t c = s[i];
if (c == 0)
return true;
- if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR))
+ if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
{
wchar_t c1 = s[i + 1];
if (c1 == '.')
{
wchar_t c2 = s[i + 2];
- if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0)
+ if (IS_SEPAR(c2) || c2 == 0)
{
if (i == 0)
return false;
int k = i - 2;
for (; k >= 0; k--)
- if (s[k] == WCHAR_PATH_SEPARATOR)
+ if (IS_SEPAR(s[(unsigned)k]))
break;
unsigned num;
if (k >= 0)
@@ -272,7 +410,7 @@ static bool ResolveDotsFolders(UString &s)
}
else
{
- if (c1 == WCHAR_PATH_SEPARATOR || c1 == 0)
+ if (IS_SEPAR(c1) || c1 == 0)
{
unsigned num = 2;
if (i != 0)
@@ -308,11 +446,11 @@ static bool AreThereDotsFolders(CFSTR s)
FChar c = s[i];
if (c == 0)
return false;
- if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR))
+ if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
{
FChar c1 = s[i + 1];
- if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR ||
- (c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR)))
+ if (c1 == 0 || IS_SEPAR(c1) ||
+ (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2]))))
return true;
}
}
@@ -360,16 +498,16 @@ int GetUseSuperPathType(CFSTR s) throw()
if (c == '.' || c == ' ')
{
FChar c2 = s[i + 1];
- if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR)
+ if (c2 == 0 || IS_SEPAR(c2))
{
// if it's "." or "..", it's not bad name.
if (c == '.')
{
- if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)
+ if (i == 0 || IS_SEPAR(s[i - 1]))
continue;
if (s[i - 1] == '.')
{
- if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR)
+ if (i - 1 == 0 || IS_SEPAR(s[i - 2]))
continue;
}
}
@@ -431,14 +569,17 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
return true;
}
- if (c == CHAR_PATH_SEPARATOR)
+ if (IS_SEPAR(c))
{
- if (s[1] == CHAR_PATH_SEPARATOR)
+ if (IS_SEPAR(s[1]))
{
UString temp = fs2us(s + 2);
unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp);
- if (fixedSize == 0) // maybe we must ignore that error to allow short network paths?
+ // we ignore that error to allow short network paths server\share?
+ /*
+ if (fixedSize == 0)
return false;
+ */
UString rem = &temp[fixedSize];
if (!ResolveDotsFolders(rem))
return false;
@@ -451,14 +592,17 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
}
else
{
- if (IsDrivePath(s))
+ if (IsDrivePath2(s))
{
UString temp = fs2us(s);
- UString rem = &temp[kDrivePrefixSize];
+ unsigned prefixSize = 2;
+ if (IsDrivePath(s))
+ prefixSize = kDrivePrefixSize;
+ UString rem = temp.Ptr(prefixSize);
if (!ResolveDotsFolders(rem))
return true;
res += kSuperPathPrefix;
- temp.DeleteFrom(kDrivePrefixSize);
+ temp.DeleteFrom(prefixSize);
res += temp;
res += rem;
return true;
@@ -468,8 +612,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
UString curDir;
if (!GetCurDir(curDir))
return false;
- if (curDir.Back() != WCHAR_PATH_SEPARATOR)
- curDir += WCHAR_PATH_SEPARATOR;
+ NormalizeDirPathPrefix(curDir);
unsigned fixedSizeStart = 0;
unsigned fixedSize = 0;
@@ -489,10 +632,10 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
}
else
{
- if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR)
+ if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
return false;
fixedSizeStart = 2;
- fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);
+ fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
if (fixedSize == 0)
return false;
superMarker = kSuperUncPrefix;
@@ -500,7 +643,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
}
UString temp;
- if (c == CHAR_PATH_SEPARATOR)
+ if (IS_SEPAR(c))
{
temp = fs2us(s + 1);
}
@@ -584,7 +727,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
#ifdef UNDER_CE
- if (s[0] != CHAR_PATH_SEPARATOR)
+ if (!IS_SEPAR(s[0]))
{
if (!dirPrefix)
return false;
@@ -614,7 +757,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
return true;
if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
return true;
- if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR)
+ if (IS_SEPAR(c) && IS_SEPAR(s[1]))
return true;
if (IsDrivePath(s))
return true;
@@ -628,8 +771,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
if (!GetCurDir(curDir))
return false;
}
- if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR)
- curDir += WCHAR_PATH_SEPARATOR;
+ NormalizeDirPathPrefix(curDir);
unsigned fixedSize = 0;
@@ -647,9 +789,9 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
fixedSize = kDrivePrefixSize;
else
{
- if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR)
+ if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
return false;
- fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);
+ fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
if (fixedSize == 0)
return false;
fixedSize += 2;
@@ -659,7 +801,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
#endif // _WIN32
UString temp;
- if (s[0] == CHAR_PATH_SEPARATOR)
+ if (IS_SEPAR(s[0]))
{
temp = fs2us(s + 1);
}
diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h
index 04fc79b2..6f9b6e03 100644
--- a/CPP/Windows/FileName.h
+++ b/CPP/Windows/FileName.h
@@ -9,29 +9,70 @@ namespace NWindows {
namespace NFile {
namespace NName {
+int FindSepar(const wchar_t *s) throw();
+#ifndef USE_UNICODE_FSTRING
+int FindSepar(const FChar *s) throw();
+#endif
+
void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty
void NormalizeDirPathPrefix(UString &dirPath);
-#ifdef _WIN32
+bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars like "a:\\"
+
+bool IsAltPathPrefix(CFSTR s) throw(); /* name: */
+
+#if defined(_WIN32) && !defined(UNDER_CE)
extern const wchar_t *kSuperPathPrefix; /* \\?\ */
const unsigned kDevicePathPrefixSize = 4;
const unsigned kSuperPathPrefixSize = 4;
const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4;
-bool IsDevicePath(CFSTR s) throw(); /* \\.\ */
-bool IsSuperUncPath(CFSTR s) throw();
+bool IsDevicePath(CFSTR s) throw(); /* \\.\ */
+bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */
+bool IsNetworkPath(CFSTR s) throw(); /* \\?\UNC\ or \\SERVER */
+
+/* GetNetworkServerPrefixSize() returns size of server prefix:
+ \\?\UNC\SERVER\
+ \\SERVER\
+ in another cases it returns 0
+*/
+
+unsigned GetNetworkServerPrefixSize(CFSTR s) throw();
-bool IsDrivePath(const wchar_t *s) throw();
+bool IsNetworkShareRootPath(CFSTR s) throw(); /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */
+
+// bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\"
+bool IsDriveRootPath_SuperAllowed(CFSTR s) throw(); // exact drive root path "a:\" or "\\?\a:\"
+
+bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:"
+// bool IsDriveName2(const wchar_t *s) throw(); // is drive name like "a:"
bool IsSuperPath(const wchar_t *s) throw();
bool IsSuperOrDevicePath(const wchar_t *s) throw();
#ifndef USE_UNICODE_FSTRING
+bool IsDrivePath2(CFSTR s) throw(); // first 2 chars are drive chars like "a:"
+// bool IsDriveName2(CFSTR s) throw(); // is drive name like "a:"
bool IsDrivePath(CFSTR s) throw();
bool IsSuperPath(CFSTR s) throw();
bool IsSuperOrDevicePath(CFSTR s) throw();
+
+/* GetRootPrefixSize() returns size of ROOT PREFIX for cases:
+ \
+ \\.\
+ C:\
+ \\?\C:\
+ \\?\UNC\SERVER\Shared\
+ \\SERVER\Shared\
+ in another cases it returns 0
+*/
+
+unsigned GetRootPrefixSize(CFSTR s) throw();
+
#endif
+int FindAltStreamColon(CFSTR path);
+
#endif // _WIN32
bool IsAbsolutePath(const wchar_t *s) throw();
@@ -44,7 +85,7 @@ const int kSuperPathType_UseOnlySuper = 1;
const int kSuperPathType_UseMainAndSuper = 2;
int GetUseSuperPathType(CFSTR s) throw();
-bool GetSuperPath(CFSTR path, UString &longPath, bool onlyIfNew);
+bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew);
bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew);
#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper)
diff --git a/CPP/Windows/MemoryGlobal.h b/CPP/Windows/MemoryGlobal.h
index 3f44f742..94e5f508 100644
--- a/CPP/Windows/MemoryGlobal.h
+++ b/CPP/Windows/MemoryGlobal.h
@@ -12,7 +12,7 @@ class CGlobal
public:
CGlobal(): _global(NULL){};
~CGlobal() { Free(); }
- operator HGLOBAL() const { return _global; };
+ operator HGLOBAL() const { return _global; }
void Attach(HGLOBAL hGlobal)
{
Free();
diff --git a/CPP/Windows/Menu.h b/CPP/Windows/Menu.h
index 75f840d0..aacdc7c3 100644
--- a/CPP/Windows/Menu.h
+++ b/CPP/Windows/Menu.h
@@ -81,14 +81,18 @@ public:
HMENU GetSubMenu(int pos) { return ::GetSubMenu(_menu, pos); }
#ifndef UNDER_CE
+ /*
bool GetItemString(UINT idItem, UINT flag, CSysString &result)
{
result.Empty();
int len = ::GetMenuString(_menu, idItem, 0, 0, flag);
- len = ::GetMenuString(_menu, idItem, result.GetBuffer(len + 2), len + 1, flag);
- result.ReleaseBuffer();
+ int len2 = ::GetMenuString(_menu, idItem, result.GetBuf(len + 2), len + 1, flag);
+ if (len > len2)
+ len = len2;
+ result.ReleaseBuf_CalcLen(len + 2);
return (len != 0);
}
+ */
UINT GetItemID(int pos) { return ::GetMenuItemID(_menu, pos); }
UINT GetItemState(UINT id, UINT flags) { return ::GetMenuState(_menu, id, flags); }
#endif
diff --git a/CPP/Windows/NationalTime.cpp b/CPP/Windows/NationalTime.cpp
index afd98778..0dcd31e0 100644
--- a/CPP/Windows/NationalTime.cpp
+++ b/CPP/Windows/NationalTime.cpp
@@ -16,8 +16,8 @@ bool MyGetTimeFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,
if (numChars == 0)
return false;
numChars = ::GetTimeFormat(locale, flags, time, format,
- resultString.GetBuffer(numChars), numChars + 1);
- resultString.ReleaseBuffer();
+ resultString.GetBuf(numChars), numChars + 1);
+ resultString.ReleaseBuf_CalcLen(numChars);
return (numChars != 0);
}
@@ -29,8 +29,8 @@ bool MyGetDateFormat(LCID locale, DWORD flags, CONST SYSTEMTIME *time,
if (numChars == 0)
return false;
numChars = ::GetDateFormat(locale, flags, time, format,
- resultString.GetBuffer(numChars), numChars + 1);
- resultString.ReleaseBuffer();
+ resultString.GetBuf(numChars), numChars + 1);
+ resultString.ReleaseBuf_CalcLen(numChars);
return (numChars != 0);
}
diff --git a/CPP/Windows/ProcessUtils.h b/CPP/Windows/ProcessUtils.h
index fb9e8dbb..c7226813 100644
--- a/CPP/Windows/ProcessUtils.h
+++ b/CPP/Windows/ProcessUtils.h
@@ -65,9 +65,9 @@ public:
{ return ::GetModuleBaseName(_handle, hModule, baseName, size); }
bool MyGetModuleBaseName(HMODULE hModule, CSysString &name)
{
- const int length = 1000;
- DWORD resultLen = MyGetModuleBaseName(hModule, name.GetBuffer(length), length);
- name.ReleaseBuffer();
+ const unsigned len = MAX_PATH + 100;
+ DWORD resultLen = MyGetModuleBaseName(hModule, name.GetBuf(len), len);
+ name.ReleaseBuf_CalcLen(len);
return (resultLen != 0);
}
@@ -75,9 +75,9 @@ public:
{ return ::GetModuleFileNameEx(_handle, hModule, baseName, size); }
bool MyGetModuleFileNameEx(HMODULE hModule, CSysString &name)
{
- const int length = MAX_PATH + 100;
- DWORD resultLen = MyGetModuleFileNameEx(hModule, name.GetBuffer(length), length);
- name.ReleaseBuffer();
+ const unsigned len = MAX_PATH + 100;
+ DWORD resultLen = MyGetModuleFileNameEx(hModule, name.GetBuf(len), len);
+ name.ReleaseBuf_CalcLen(len);
return (resultLen != 0);
}
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
index d16f576c..8c7d5e19 100644
--- a/CPP/Windows/PropVariant.cpp
+++ b/CPP/Windows/PropVariant.cpp
@@ -35,7 +35,7 @@ HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()
p->vt = VT_BSTR;
BSTR dest = p->bstrVal;
for (UINT i = 0; i <= len; i++)
- dest[i] = s[i];
+ dest[i] = (Byte)s[i];
return S_OK;
}
@@ -97,6 +97,48 @@ CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
return *this;
}
+CPropVariant& CPropVariant::operator=(const UString &s)
+{
+ InternalClear();
+ vt = VT_BSTR;
+ wReserved1 = 0;
+ bstrVal = ::SysAllocStringLen(s, s.Len());
+ if (!bstrVal)
+ throw kMemException;
+ return *this;
+}
+
+CPropVariant& CPropVariant::operator=(const UString2 &s)
+{
+ /*
+ if (s.IsEmpty())
+ *this = L"";
+ else
+ */
+ {
+ InternalClear();
+ vt = VT_BSTR;
+ wReserved1 = 0;
+ bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());
+ if (!bstrVal)
+ throw kMemException;
+ /* SysAllocStringLen probably appends a null-terminating character for NULL string.
+ But it doesn't specified in MSDN.
+ But we suppose that it works
+
+ if (!s.GetRawPtr())
+ {
+ *bstrVal = 0;
+ }
+ */
+
+ /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)
+ pointers to this function causes an unexpected termination of the application.
+ Is it safe? Maybe we must chamnge the code for that case ? */
+ }
+ return *this;
+}
+
CPropVariant& CPropVariant::operator=(const char *s)
{
InternalClear();
@@ -112,8 +154,9 @@ CPropVariant& CPropVariant::operator=(const char *s)
}
else
{
+ BSTR dest = bstrVal;
for (UINT i = 0; i <= len; i++)
- bstrVal[i] = s[i];
+ dest[i] = (Byte)s[i];
}
return *this;
}
diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h
index 70907c88..adece3e3 100644
--- a/CPP/Windows/PropVariant.h
+++ b/CPP/Windows/PropVariant.h
@@ -5,6 +5,7 @@
#include "../Common/MyTypes.h"
#include "../Common/MyWindows.h"
+#include "../Common/MyString.h"
namespace NWindows {
namespace NCOM {
@@ -57,7 +58,7 @@ public:
CPropVariant(const CPropVariant &varSrc);
CPropVariant(BSTR bstrSrc);
CPropVariant(LPCOLESTR lpszSrc);
- CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); };
+ CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }
CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }
private:
@@ -74,6 +75,8 @@ public:
CPropVariant& operator=(const PROPVARIANT &varSrc);
CPropVariant& operator=(BSTR bstrSrc);
CPropVariant& operator=(LPCOLESTR lpszSrc);
+ CPropVariant& operator=(const UString &s);
+ CPropVariant& operator=(const UString2 &s);
CPropVariant& operator=(const char *s);
CPropVariant& operator=(bool bSrc) throw();
diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp
index dfb93d6d..78f98720 100644
--- a/CPP/Windows/PropVariantConv.cpp
+++ b/CPP/Windows/PropVariantConv.cpp
@@ -93,7 +93,7 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) thr
case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;
- case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return;
+ case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return;
default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);
}
}
diff --git a/CPP/Windows/PropVariantUtils.cpp b/CPP/Windows/PropVariantUtils.cpp
index 92b355a4..5ffe7121 100644
--- a/CPP/Windows/PropVariantUtils.cpp
+++ b/CPP/Windows/PropVariantUtils.cpp
@@ -37,20 +37,20 @@ void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM:
}
-AString TypeToString(const char *table[], unsigned num, UInt32 value)
+AString TypeToString(const char * const table[], unsigned num, UInt32 value)
{
if (value < num)
return table[value];
return GetHex(value);
}
-void TypeToProp(const char *table[], unsigned num, UInt32 value, NCOM::CPropVariant &prop)
+void TypeToProp(const char * const table[], unsigned num, UInt32 value, NCOM::CPropVariant &prop)
{
prop = TypeToString(table, num, value);
}
-AString FlagsToString(const char **names, unsigned num, UInt32 flags)
+AString FlagsToString(const char * const *names, unsigned num, UInt32 flags)
{
AString s;
for (unsigned i = 0; i < num; i++)
diff --git a/CPP/Windows/PropVariantUtils.h b/CPP/Windows/PropVariantUtils.h
index c9946144..0da9c3b7 100644
--- a/CPP/Windows/PropVariantUtils.h
+++ b/CPP/Windows/PropVariantUtils.h
@@ -16,12 +16,12 @@ struct CUInt32PCharPair
AString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value);
void PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);
-AString FlagsToString(const char **names, unsigned num, UInt32 flags);
+AString FlagsToString(const char * const *names, unsigned num, UInt32 flags);
AString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags);
void FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop);
-AString TypeToString(const char *table[], unsigned num, UInt32 value);
-void TypeToProp(const char *table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);
+AString TypeToString(const char * const table[], unsigned num, UInt32 value);
+void TypeToProp(const char * const table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);
#define PAIR_TO_PROP(pairs, value, prop) PairToProp(pairs, ARRAY_SIZE(pairs), value, prop)
#define FLAGS_TO_PROP(pairs, value, prop) FlagsToProp(pairs, ARRAY_SIZE(pairs), value, prop)
diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp
index fe826276..c000e628 100644
--- a/CPP/Windows/Registry.cpp
+++ b/CPP/Windows/Registry.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <wchar.h>
+
#ifndef _UNICODE
#include "../Common/StringConvert.h"
#endif
@@ -75,15 +77,15 @@ LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw()
if (res != ERROR_SUCCESS)
return res;
FILETIME fileTime;
- const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL
- DWORD size = kBufferSize;
- TCHAR buffer[kBufferSize];
+ const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL
+ DWORD size = kBufSize;
+ TCHAR buffer[kBufSize];
while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS)
{
res = key.RecurseDeleteKey(buffer);
if (res != ERROR_SUCCESS)
return res;
- size = kBufferSize;
+ size = kBufSize;
}
key.Close();
return DeleteSubKey(subKeyName);
@@ -226,7 +228,6 @@ LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw()
LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw()
{
- MYASSERT(count != NULL);
DWORD type = 0;
LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
@@ -237,38 +238,47 @@ LONG CKey::QueryValue(LPCTSTR name, CSysString &value)
{
value.Empty();
DWORD type = 0;
- UInt32 currentSize = 0;
- LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&currentSize);
+ UInt32 curSize = 0;
+ LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&curSize);
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
return res;
- res = QueryValue(name, value.GetBuffer(currentSize), currentSize);
- value.ReleaseBuffer();
+ UInt32 curSize2 = curSize;
+ res = QueryValue(name, value.GetBuf(curSize), curSize2);
+ if (curSize > curSize2)
+ curSize = curSize2;
+ value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR));
return res;
}
+
#ifndef _UNICODE
+
LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count)
{
- MYASSERT(count != NULL);
DWORD type = 0;
LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count);
MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
return res;
}
+
LONG CKey::QueryValue(LPCWSTR name, UString &value)
{
value.Empty();
DWORD type = 0;
- UInt32 currentSize = 0;
+ UInt32 curSize = 0;
LONG res;
+
if (g_IsNT)
{
- res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&currentSize);
+ res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize);
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
return res;
- res = QueryValue(name, value.GetBuffer(currentSize), currentSize);
- value.ReleaseBuffer();
+ UInt32 curSize2 = curSize;
+ res = QueryValue(name, value.GetBuf(curSize), curSize2);
+ if (curSize > curSize2)
+ curSize = curSize2;
+ value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t));
}
else
{
@@ -276,10 +286,13 @@ LONG CKey::QueryValue(LPCWSTR name, UString &value)
res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp);
value = GetUnicodeString(vTemp);
}
+
return res;
}
+
#endif
+
LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw()
{
DWORD type = 0;
@@ -304,14 +317,14 @@ LONG CKey::EnumKeys(CSysStringVector &keyNames)
{
keyNames.Clear();
CSysString keyName;
- for (UInt32 index = 0; ; index++)
+ for (DWORD index = 0; ; index++)
{
- const UInt32 kBufferSize = MAX_PATH + 1; // 256 in ATL
+ const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL
FILETIME lastWriteTime;
- UInt32 nameSize = kBufferSize;
- LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuffer(kBufferSize),
+ UInt32 nameSize = kBufSize;
+ LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize),
(DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime);
- keyName.ReleaseBuffer();
+ keyName.ReleaseBuf_CalcLen(kBufSize);
if (result == ERROR_NO_MORE_ITEMS)
break;
if (result != ERROR_SUCCESS)
@@ -321,47 +334,56 @@ LONG CKey::EnumKeys(CSysStringVector &keyNames)
return ERROR_SUCCESS;
}
-LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw()
+LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)
{
- UInt32 numChars = 0;
+ size_t numChars = 0;
+
unsigned i;
+
for (i = 0; i < strings.Size(); i++)
numChars += strings[i].Len() + 1;
- CBuffer<wchar_t> buffer(numChars);
- unsigned pos = 0;
+
+ CObjArray<wchar_t> buffer(numChars);
+ size_t pos = 0;
+
for (i = 0; i < strings.Size(); i++)
{
const UString &s = strings[i];
- MyStringCopy((wchar_t *)buffer + pos, (const wchar_t *)s);
- pos += s.Len() + 1;
+ size_t size = s.Len() + 1;
+ wmemcpy(buffer + pos, s, size);
+ pos += size;
}
- return SetValue(valueName, buffer, numChars * sizeof(wchar_t));
+ return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t));
}
LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)
{
strings.Clear();
CByteBuffer buffer;
- UInt32 dataSize;
+ UInt32 dataSize = 0;
LONG res = QueryValue(valueName, buffer, dataSize);
if (res != ERROR_SUCCESS)
return res;
+ if (dataSize > buffer.Size())
+ return E_FAIL;
if (dataSize % sizeof(wchar_t) != 0)
return E_FAIL;
+
const wchar_t *data = (const wchar_t *)(const Byte *)buffer;
- unsigned numChars = dataSize / sizeof(wchar_t);
+ size_t numChars = dataSize / sizeof(wchar_t);
+ size_t prev = 0;
UString s;
- for (unsigned i = 0; i < numChars; i++)
+
+ for (size_t i = 0; i < numChars; i++)
{
- wchar_t c = data[i];
- if (c == 0)
+ if (data[i] == 0)
{
+ s = data + prev;
strings.Add(s);
- s.Empty();
+ prev = i + 1;
}
- else
- s += c;
}
+
return res;
}
diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h
index 32ee10b0..ca79dfe3 100644
--- a/CPP/Windows/Registry.h
+++ b/CPP/Windows/Registry.h
@@ -55,7 +55,7 @@ public:
LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw();
- LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) throw();
+ LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings);
LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings);
LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw();
diff --git a/CPP/Windows/ResourceString.cpp b/CPP/Windows/ResourceString.cpp
index eb28bd3b..cc8b964a 100644
--- a/CPP/Windows/ResourceString.cpp
+++ b/CPP/Windows/ResourceString.cpp
@@ -25,10 +25,10 @@ static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID)
do
{
size <<= 1;
- len = ::LoadString(hInstance, resourceID, s.GetBuffer(size - 1), size);
+ len = ::LoadString(hInstance, resourceID, s.GetBuf(size - 1), size);
}
while (size - len <= 1);
- s.ReleaseBuffer();
+ s.ReleaseBuf_CalcLen(len);
return s;
}
@@ -43,10 +43,10 @@ static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s)
do
{
size <<= 1;
- len = ::LoadStringW(hInstance, resourceID, s.GetBuffer(size - 1), size);
+ len = ::LoadStringW(hInstance, resourceID, s.GetBuf(size - 1), size);
}
while (size - len <= 1);
- s.ReleaseBuffer();
+ s.ReleaseBuf_CalcLen(len);
}
// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it.
diff --git a/CPP/Windows/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp
index 99ac04bc..1f21b6a6 100644
--- a/CPP/Windows/SecurityUtils.cpp
+++ b/CPP/Windows/SecurityUtils.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../Common/MyString.h"
+
#include "SecurityUtils.h"
namespace NWindows {
@@ -14,17 +16,18 @@ bool MyLookupAccountSid(LPCTSTR systemName, PSID sid,
DWORD accountNameSize = 0, domainNameSize = 0;
if (!::LookupAccountSid(systemName, sid,
- accountName.GetBuffer(0), &accountNameSize,
- domainName.GetBuffer(0), &domainNameSize, sidNameUse))
+ accountName.GetBuf(0), &accountNameSize,
+ domainName.GetBuf(0), &domainNameSize, sidNameUse))
{
if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return false;
}
+ DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize;
bool result = BOOLToBool(::LookupAccountSid(systemName, sid,
- accountName.GetBuffer(accountNameSize), &accountNameSize,
- domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse));
- accountName.ReleaseBuffer();
- domainName.ReleaseBuffer();
+ accountName.GetBuf(accountNameSize), &accountNameSize2,
+ domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse));
+ accountName.ReleaseBuf_CalcLen(accountNameSize);
+ domainName.ReleaseBuf_CalcLen(domainNameSize);
return result;
}
*/
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp
index 2eb1a960..0d2ac618 100644
--- a/CPP/Windows/Shell.cpp
+++ b/CPP/Windows/Shell.cpp
@@ -95,16 +95,18 @@ UString CDrop::QueryFileName(UINT fileIndex)
{
AString fileNameA;
UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);
- QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1);
- fileNameA.ReleaseBuffer();
+ const unsigned len = bufferSize + 2;
+ QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1);
+ fileNameA.ReleaseBuf_CalcLen(len);
fileName = GetUnicodeString(fileNameA);
}
else
#endif
{
UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);
- QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1);
- fileName.ReleaseBuffer();
+ const unsigned len = bufferSize + 2;
+ QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1);
+ fileName.ReleaseBuf_CalcLen(len);
}
return fileName;
}
@@ -120,8 +122,9 @@ void CDrop::QueryFileNames(UStringVector &fileNames)
bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)
{
- bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2)));
- path.ReleaseBuffer();
+ const unsigned len = MAX_PATH * 2;
+ bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));
+ path.ReleaseBuf_CalcLen(len);
return result;
}
@@ -208,14 +211,16 @@ bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
browseInfo.hwndOwner = owner;
browseInfo.pidlRoot = NULL;
- // there are Unicode/astring problems in WinCE SDK!!!
+ // there are Unicode/Astring problems in some WinCE SDK ?
+ /*
#ifdef UNDER_CE
- browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH);
+ browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH);
browseInfo.lpszTitle = (LPCSTR)title;
#else
- browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
+ */
+ browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
browseInfo.lpszTitle = title;
- #endif
+ // #endif
browseInfo.ulFlags = ulFlags;
browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
browseInfo.lParam = (LPARAM)initialFolder;
@@ -244,8 +249,9 @@ bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");
if (shGetPathFromIDListW == 0)
return false;
- bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2)));
- path.ReleaseBuffer();
+ const unsigned len = MAX_PATH * 2;
+ bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));
+ path.ReleaseBuf_CalcLen(len);
return result;
}
@@ -302,7 +308,7 @@ static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
BROWSEINFOW browseInfo;
browseInfo.hwndOwner = owner;
browseInfo.pidlRoot = NULL;
- browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
+ browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);
browseInfo.lpszTitle = title;
browseInfo.ulFlags = ulFlags;
browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;
diff --git a/CPP/Windows/Window.cpp b/CPP/Windows/Window.cpp
index f1d4d95b..36585022 100644
--- a/CPP/Windows/Window.cpp
+++ b/CPP/Windows/Window.cpp
@@ -114,13 +114,18 @@ bool MySetWindowText(HWND wnd, LPCWSTR s)
bool CWindow::GetText(CSysString &s)
{
s.Empty();
- int length = GetTextLength();
- if (length == 0)
+ int len = GetTextLength();
+ if (len == 0)
+ return (::GetLastError() == ERROR_SUCCESS);
+ TCHAR *p = s.GetBuf(len);
+ {
+ int len2 = GetText(p, len + 1);
+ if (len > len2)
+ len = len2;
+ }
+ s.ReleaseBuf_CalcLen(len);
+ if (len == 0)
return (::GetLastError() == ERROR_SUCCESS);
- length = GetText(s.GetBuffer(length), length + 1);
- s.ReleaseBuffer();
- if (length == 0)
- return (::GetLastError() != ERROR_SUCCESS);
return true;
}
@@ -130,18 +135,23 @@ bool CWindow::GetText(UString &s)
if (g_IsNT)
{
s.Empty();
- int length = GetWindowTextLengthW(_window);
- if (length == 0)
+ int len = GetWindowTextLengthW(_window);
+ if (len == 0)
return (::GetLastError() == ERROR_SUCCESS);
- length = GetWindowTextW(_window, s.GetBuffer(length), length + 1);
- s.ReleaseBuffer();
- if (length == 0)
+ wchar_t *p = s.GetBuf(len);
+ {
+ int len2 = GetWindowTextW(_window, p, len + 1);
+ if (len > len2)
+ len = len2;
+ }
+ s.ReleaseBuf_CalcLen(len);
+ if (len == 0)
return (::GetLastError() == ERROR_SUCCESS);
return true;
}
CSysString sysString;
bool result = GetText(sysString);
- s = GetUnicodeString(sysString);
+ MultiByteToUnicodeString2(s, sysString);
return result;
}
#endif
diff --git a/DOC/7zip.inf b/DOC/7zip.inf
index ca01cb48..8d9fda6d 100644
--- a/DOC/7zip.inf
+++ b/DOC/7zip.inf
@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName%
[Strings]
-AppVer = "9.38"
-AppDate = "2015-01-03"
+AppVer = "15.05"
+AppDate = "2015-06-14"
[CEDevice]
; ProcessorType = 2577 ; ARM
diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi
index e2093e42..0fe8a6dd 100644
--- a/DOC/7zip.nsi
+++ b/DOC/7zip.nsi
@@ -1,8 +1,8 @@
;--------------------------------
;Defines
-!define VERSION_MAJOR 9
-!define VERSION_MINOR 38
+!define VERSION_MAJOR 15
+!define VERSION_MINOR 05
!define VERSION_POSTFIX_FULL " beta"
!ifdef WIN64
!ifdef IA64
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs
index 767b6101..45f3b5ba 100644
--- a/DOC/7zip.wxs
+++ b/DOC/7zip.wxs
@@ -1,10 +1,10 @@
<?xml version="1.0"?>
-<?define VerMajor = "9" ?>
-<?define VerMinor = "38" ?>
+<?define VerMajor = "15" ?>
+<?define VerMinor = "05" ?>
<?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
-<?define MmHex = "0$(var.VerMajor)$(var.VerMinor)" ?>
+<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
<?define MmmmVer = "$(var.MmVer).$(var.VerBuild).0" ?>
<?define UpgradeMinVer = "4.38" ?>
@@ -112,6 +112,7 @@
<Property Id="ALLUSERS">2</Property>
+ <Property Id="LicenseAccepted">1</Property>
<Property Id="ARPURLINFOABOUT" Value="$(var.AboutURL)" />
<Property Id="ARPHELPLINK" Value="$(var.SupportURL)" />
diff --git a/DOC/Methods.txt b/DOC/Methods.txt
index ede83041..7eb6c6bf 100644
--- a/DOC/Methods.txt
+++ b/DOC/Methods.txt
@@ -1,12 +1,17 @@
-7-Zip method IDs (9.24)
------------------------
+7-Zip method IDs for 7z and xz archives
+---------------------------------------
-Each compression or crypto method in 7z has unique binary value (ID).
+Version: 15.00
+Date: 2015-04-01
+
+Each compression or crypto method in 7z is associated with unique binary value (ID).
The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes).
+xz and 7z formats use same ID map.
+
If you want to add some new ID, you have two ways:
-1) Write request for allocating IDs to 7-zip developers.
-2) Generate 8-bytes ID:
+ 1) Write request for allocating IDs to 7-Zip developers.
+ 2) Generate 8-bytes ID:
3F ZZ ZZ ZZ ZZ ZZ MM MM
@@ -26,87 +31,104 @@ List of defined IDs
00 - Copy
03 - Delta
-04 - x86 (BCJ)
-05 - PPC (Big Endian)
+04 - BCJ (x86)
+05 - PPC (big-endian)
06 - IA64
-07 - ARM (little endian)
-08 - ARM Thumb (little endian)
+07 - ARM (little-endian)
+08 - ARMT (little-endian)
09 - SPARC
+
21 - LZMA2
02.. - Common
- 03 Swap
+ 03 [Swap]
- 2 Swap2
- 4 Swap4
03.. - 7z
- 01 - LZMA
- 01 - Version
+ 01 -
+ 01 - LZMA
- 03 - Branch
- 01 - x86
+ 03 - [Branch Codecs]
+ 01 - [x86 Codecs]
03 - BCJ
- 1B - BCJ2
- 02 - PPC
- 05 - PPC (Big Endian)
- 03 - Alpha
+ 1B - BCJ2 (4 packed streams)
+ 02 -
+ 05 - PPC (big-endian)
+ 03 -
01 - Alpha
- 04 - IA64
+ 04 -
01 - IA64
- 05 - ARM
- 01 - ARM
- 06 - M68
- 05 - M68 (Big Endian)
- 07 - ARM Thumb
- 01 - ARMT
- 08 - SPARC
+ 05 -
+ 01 - ARM (little-endian)
+ 06 -
+ 05 - M68 (big-endian)
+ 07 -
+ 01 - ARMT (little-endian)
+ 08 -
05 - SPARC
- 04 - PPMD
- 01 - Version
+ 04 -
+ 01 - PPMD
7F -
- 01 - experimental methods.
+ 01 - experimental method.
-04.. - Misc
+04.. - Misc codecs
+
00 - Reserved
- 01 - Zip
- 00 - Copy (not used). Use {00} instead
+
+ 01 - [Zip]
+ 00 - Copy (not used. Use {00} instead)
01 - Shrink
06 - Implode
08 - Deflate
09 - Deflate64
10 - Imploding
- 12 - BZip2 (not used). Use {04 02 02} instead
- 14 - LZMA
+ 12 - BZip2 (not used. Use {040202} instead)
+ 14 - LZMA (LZMA-zip)
+ 5F - xz
60 - Jpeg
61 - WavPack
- 62 - PPMd
+ 62 - PPMd (PPMd-zip)
63 - wzAES
- 02 - BZip
+
+ 02 -
02 - BZip2
- 03 - Rar
+
+ 03 - [Rar]
01 - Rar15
02 - Rar20
03 - Rar29
- 04 - Arj
- 01 - Arj (1,2,3)
- 02 - Arj 4
- 05 - Z
- 06 - Lzh
+
+ 04 - [Arj]
+ 01 - Arj(1,2,3)
+ 02 - Arj4
+
+ 05 - [Z]
+
+ 06 - [Lzh]
+
07 - Reserved for 7z
- 08 - Cab
- 09 - NSIS
+
+ 08 - [Cab]
+
+ 09 - [NSIS]
01 - DeflateNSIS
02 - BZip2NSIS
+ F7 - External codecs (that are not included to 7-Zip)
+
+ 0x xx - reserved
+ 10 xx - reserved
+
06.. - Crypto
F0 - Ciphers without hashing algo
- 01 - AES
+ 01 - [AES]
0x - AES-128
4x - AES-192
8x - AES-256
@@ -119,13 +141,16 @@ List of defined IDs
x4 - CTR
F1 - Combine Ciphers
- 01 - Zip
- 01 - Main Zip crypto algo
- 03 - RAR
+
+ 01 - [Zip]
+ 01 - ZipCrypto (Main Zip crypto algo)
+
+ 03 - [RAR]
02 -
- 03 - Rar29 AES-128 + (modified SHA-1)
- 07 - 7z
- 01 - AES-256 + SHA-256
+ 03 - Rar29AES (AES-128 + modified SHA-1)
+
+ 07 - [7z]
+ 01 - 7zAES (AES-256 + SHA-256)
---
diff --git a/DOC/readme.txt b/DOC/readme.txt
index b22fff0c..ca1be590 100644
--- a/DOC/readme.txt
+++ b/DOC/readme.txt
@@ -1,5 +1,5 @@
-7-Zip 9.38 Sources
-------------------
+7-Zip 15.05 Sources
+-------------------
7-Zip is a file archiver for Windows.
diff --git a/DOC/src-history.txt b/DOC/src-history.txt
index ed3b4fbd..c17689c1 100644
--- a/DOC/src-history.txt
+++ b/DOC/src-history.txt
@@ -3,7 +3,7 @@ HISTORY of the 7-Zip source code
9.38 beta 2015-01-03
-------------------------
-- The BUG in 9.30-9.37 was fixed:
+- The BUG in 9.31-9.37 was fixed:
IArchiveGetRawProps interface was disabled for 7z archives.
- The BUG in 9.26-9.36 was fixed:
Some code in CPP\7zip\Archive\7z\ worked correctly only under Windows.