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
path: root/CPP
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 /CPP
parent0713a3ab803e57401f18432148b4139e5fe6e5dd (diff)
15.0515.05
Diffstat (limited to 'CPP')
-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
516 files changed, 28460 insertions, 14891 deletions
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