summaryrefslogtreecommitdiffstats
path: root/other-licenses/7zstub/src/CPP/7zip
diff options
context:
space:
mode:
Diffstat (limited to 'other-licenses/7zstub/src/CPP/7zip')
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/7zip.mak240
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Aes.mak7
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.h76
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.cpp567
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.h70
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.cpp678
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.h92
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zExtract.cpp423
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.cpp139
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.h61
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.cpp756
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.h181
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandlerOut.cpp939
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.cpp19
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.h148
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.cpp1663
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.h435
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zItem.h202
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.cpp901
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.h335
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.cpp174
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.h22
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zRegister.cpp21
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.cpp22
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.h35
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.cpp2497
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.h139
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Archive.def12
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Archive2.def19
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/ArchiveExports.cpp151
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.cpp1124
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.h447
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.cpp17
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.h25
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.cpp232
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.h110
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.cpp46
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.h67
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.cpp88
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.h28
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.cpp191
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.h89
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp18
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.h37
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.h6
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Common/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/DllExports2.cpp122
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/IArchive.h608
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/Icons/7z.icobin0 -> 4710 bytes
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/LzmaHandler.cpp605
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/SplitHandler.cpp359
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.cpp1308
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.h11
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Asm.mak9
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsp1901
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsw29
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/makefile158
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/resource.rc7
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/makefile96
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/resource.rc5
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/makefile116
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/resource.rc5
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp799
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp477
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw29
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile59
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile.gcc195
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/resource.rc3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp715
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/7z.icobin0 -> 1078 bytes
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsp912
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsw29
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SfxCon.cpp482
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/makefile135
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/resource.rc5
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp246
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h86
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp137
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h11
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp803
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw29
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp875
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.h13
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/makefile117
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.rc18
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/setup.icobin0 -> 1078 bytes
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/7z.icobin0 -> 1078 bytes
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsp988
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsw29
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SfxWin.cpp241
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.h14
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/makefile153
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.h1
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.rc50
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.cpp250
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.h120
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.cpp536
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.h192
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.cpp46
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.h10
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.cpp475
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.h166
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.cpp418
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.h235
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.cpp163
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.h92
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.cpp127
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.h48
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.cpp367
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.h252
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.h6
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/MethodId.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/MethodId.h10
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp509
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.h264
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.cpp39
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.h26
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.cpp111
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.h66
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.cpp51
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.h35
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/PropId.cpp108
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/RegisterArc.h78
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/RegisterCodec.h106
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.cpp156
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.h60
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.cpp285
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.h157
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.cpp56
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.h13
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.cpp57
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.h26
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.cpp48
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.h24
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.cpp666
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.h120
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Register.cpp24
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.cpp24
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.h31
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/BcjRegister.cpp17
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.cpp23
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.h35
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/BranchRegister.cpp41
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/ByteSwap.cpp92
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/CodecExports.cpp344
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.cpp120
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.h49
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/CopyRegister.cpp15
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/DeltaFilter.cpp128
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp265
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.h96
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.cpp122
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.h42
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Register.cpp22
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.cpp343
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.h113
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.cpp182
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.h46
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/LzmaRegister.cpp22
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.cpp170
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.h86
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.cpp152
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.h58
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/PpmdRegister.cpp22
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.cpp150
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.h92
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.cpp245
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.h46
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crc.mak8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crc64.mak8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.cpp280
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.h118
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/7zAesRegister.cpp17
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.cpp112
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.h57
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/MyAesReg.cpp16
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.cpp124
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.h21
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Crypto/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/GuiCommon.rc84
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/Guid.txt220
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/ICoder.h399
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/IDecl.h28
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/IPassword.h23
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/IProgress.h19
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/IStream.h127
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/LzmaDec.mak5
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/MyVersion.h2
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/MyVersionInfo.rc2
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/PropID.h127
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/SubBuild.mak3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.cpp993
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsp235
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsw29
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Client7z/makefile28
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Client7z/resource.rc3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.cpp1281
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.h136
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp1691
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.h403
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.cpp78
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.h13
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp154
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.h112
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.cpp3492
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.h72
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.cpp37
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.h11
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/DirItem.h190
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.cpp1086
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.h41
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ExitCode.h27
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.cpp482
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.h94
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractMode.h34
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.cpp280
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.h31
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.cpp347
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.h106
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/IFileExtractCallback.h114
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.cpp1074
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.h424
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.cpp3550
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.h436
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.cpp668
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.h18
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/Property.h14
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.cpp80
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.h10
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.cpp25
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.h10
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.cpp19
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.h16
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.cpp1667
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.h200
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.cpp64
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.h66
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.cpp771
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.h162
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.cpp233
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.h27
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.cpp70
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.h55
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.cpp94
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.h26
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Common/ZipRegistry.h130
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.cpp41
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.h14
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.mak36
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.manifest13
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.cpp69
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.h33
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp825
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.h164
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.cpp367
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.h48
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/List.cpp1349
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/List.h27
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/Main.cpp1151
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/MainAr.cpp167
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.cpp115
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.h66
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.cpp183
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.h62
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.cpp3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.h8
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp702
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.h124
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.cpp110
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.h27
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/makefile69
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Console/resource.rc7
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.cpp37
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.h16
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.cpp1025
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.h21
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialogRes.h9
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.cpp64
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.h28
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialogRes.h4
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/DialogSize.h16
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.cpp1033
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.h328
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.cpp28
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.h14
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/LangUtils.h40
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/MyWindowsNew.h76
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.cpp122
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.h69
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.rc91
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialogRes.h17
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.cpp58
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.h28
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.rc14
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialogRes.h5
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.cpp197
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.h170
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.rc12
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.cpp1337
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.h351
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.rc40
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2Res.h48
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2a.rc80
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialogRes.h3
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.cpp23
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.h10
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyNameRes.h95
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.cpp255
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.h62
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resource.h177
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resourceGui.h15
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/Extract.rc59
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.cpp418
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.h113
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.rc98
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialogRes.h24
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.cpp278
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.h38
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractRes.h51
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/HashGUI.h27
-rw-r--r--other-licenses/7zstub/src/CPP/7zip/UI/GUI/resource2.h2
345 files changed, 72696 insertions, 0 deletions
diff --git a/other-licenses/7zstub/src/CPP/7zip/7zip.mak b/other-licenses/7zstub/src/CPP/7zip/7zip.mak
new file mode 100644
index 0000000000..7fec27cf3f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/7zip.mak
@@ -0,0 +1,240 @@
+OBJS = \
+ $O\StdAfx.obj \
+ $(CURRENT_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(WIN_CTRL_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(UI_COMMON_OBJS) \
+ $(AGENT_OBJS) \
+ $(CONSOLE_OBJS) \
+ $(EXPLORER_OBJS) \
+ $(FM_OBJS) \
+ $(GUI_OBJS) \
+ $(7Z_OBJS) \
+ $(CAB_OBJS) \
+ $(CHM_OBJS) \
+ $(COM_OBJS) \
+ $(ISO_OBJS) \
+ $(NSIS_OBJS) \
+ $(RAR_OBJS) \
+ $(TAR_OBJS) \
+ $(UDF_OBJS) \
+ $(WIM_OBJS) \
+ $(ZIP_OBJS) \
+ $(COMPRESS_OBJS) \
+ $(CRYPTO_OBJS) \
+ $(C_OBJS) \
+ $(ASM_OBJS) \
+ $O\resource.res \
+
+!include "../../../Build.mak"
+
+# MAK_SINGLE_FILE = 1
+
+!IFDEF MAK_SINGLE_FILE
+
+!IFDEF CURRENT_OBJS
+$(CURRENT_OBJS): ./$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+
+!IFDEF COMMON_OBJS
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF WIN_OBJS
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF WIN_CTRL_OBJS
+$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF 7ZIP_COMMON_OBJS
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF AR_OBJS
+$(AR_OBJS): ../../Archive/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF AR_COMMON_OBJS
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF 7Z_OBJS
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF CAB_OBJS
+$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF CHM_OBJS
+$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF COM_OBJS
+$(COM_OBJS): ../../Archive/Com/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF ISO_OBJS
+$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF NSIS_OBJS
+$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF RAR_OBJS
+$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF TAR_OBJS
+$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF UDF_OBJS
+$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF WIM_OBJS
+$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF ZIP_OBJS
+$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF COMPRESS_OBJS
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp
+ $(COMPL_O2)
+!ENDIF
+
+!IFDEF CRYPTO_OBJS
+$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp
+ $(COMPL_O2)
+!ENDIF
+
+!IFDEF UI_COMMON_OBJS
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF AGENT_OBJS
+$(AGENT_OBJS): ../../UI/Agent/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF CONSOLE_OBJS
+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF EXPLORER_OBJS
+$(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF FM_OBJS
+$(FM_OBJS): ../../UI/FileManager/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF GUI_OBJS
+$(GUI_OBJS): ../../UI/GUI/$(*B).cpp
+ $(COMPL)
+!ENDIF
+
+!IFDEF C_OBJS
+$(C_OBJS): ../../../../C/$(*B).c
+ $(COMPL_O2)
+!ENDIF
+
+
+!ELSE
+
+{.}.cpp{$O}.obj::
+ $(COMPLB)
+{../../../Common}.cpp{$O}.obj::
+ $(COMPLB)
+{../../../Windows}.cpp{$O}.obj::
+ $(COMPLB)
+{../../../Windows/Control}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Common}.cpp{$O}.obj::
+ $(COMPLB)
+
+{../../UI/Common}.cpp{$O}.obj::
+ $(COMPLB)
+{../../UI/Agent}.cpp{$O}.obj::
+ $(COMPLB)
+{../../UI/Console}.cpp{$O}.obj::
+ $(COMPLB)
+{../../UI/Explorer}.cpp{$O}.obj::
+ $(COMPLB)
+{../../UI/FileManager}.cpp{$O}.obj::
+ $(COMPLB)
+{../../UI/GUI}.cpp{$O}.obj::
+ $(COMPLB)
+
+
+{../../Archive}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Common}.cpp{$O}.obj::
+ $(COMPLB)
+
+{../../Archive/7z}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Cab}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Chm}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Com}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Iso}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Nsis}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Rar}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Tar}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Udf}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Wim}.cpp{$O}.obj::
+ $(COMPLB)
+{../../Archive/Zip}.cpp{$O}.obj::
+ $(COMPLB)
+
+{../../Compress}.cpp{$O}.obj::
+ $(COMPLB_O2)
+{../../Crypto}.cpp{$O}.obj::
+ $(COMPLB_O2)
+{../../../../C}.c{$O}.obj::
+ $(CCOMPLB)
+
+!ENDIF
+
+!include "Asm.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Aes.mak b/other-licenses/7zstub/src/CPP/7zip/Aes.mak
new file mode 100644
index 0000000000..4d5e98b37e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Aes.mak
@@ -0,0 +1,7 @@
+C_OBJS = $(C_OBJS) \
+ $O\Aes.obj
+
+!IF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM" && "$(CPU)" != "ARM64"
+ASM_OBJS = $(ASM_OBJS) \
+ $O\AesOpt.obj
+!ENDIF
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.cpp
new file mode 100644
index 0000000000..232c638203
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.cpp
@@ -0,0 +1,3 @@
+// CompressionMethod.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.h
new file mode 100644
index 0000000000..23600171d1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -0,0 +1,76 @@
+// 7zCompressionMode.h
+
+#ifndef __7Z_COMPRESSION_MODE_H
+#define __7Z_COMPRESSION_MODE_H
+
+#include "../../Common/MethodId.h"
+#include "../../Common/MethodProps.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CMethodFull: public CMethodProps
+{
+ CMethodId Id;
+ UInt32 NumStreams;
+ int CodecIndex;
+
+ CMethodFull(): CodecIndex(-1) {}
+ bool IsSimpleCoder() const { return NumStreams == 1; }
+};
+
+struct CBond2
+{
+ 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<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():
+ DefaultMethod_was_Inserted(false),
+ Filter_was_Inserted(false),
+ PasswordIsDefined(false)
+ #ifndef _7ZIP_ST
+ , NumThreads(1)
+ , MultiThreadMixer(true)
+ #endif
+ {}
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.cpp
new file mode 100644
index 0000000000..2705ecb9ae
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -0,0 +1,567 @@
+// 7zDecode.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamObjects.h"
+
+#include "7zDecode.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CDecProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+ 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.Bonds.Size(); i++)
+ {
+ NCoderMixer2::CBond &bond = bi.Bonds[i];
+ const N7z::CBond &folderBond = folder.Bonds[i];
+ bond.PackIndex = folderBond.PackIndex;
+ bond.UnpackIndex = folderBond.UnpackIndex;
+ }
+
+ bi.Coders.ClearAndSetSize(folder.Coders.Size());
+ bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
+ for (i = 0; i < folder.Coders.Size(); i++)
+ {
+ const CCoderInfo &coderInfo = folder.Coders[i];
+ bi.Coders[i].NumStreams = coderInfo.NumStreams;
+ bi.CoderMethodIDs[i] = coderInfo.MethodID;
+ }
+
+ /*
+ if (!bi.SetUnpackCoder())
+ throw 1112;
+ */
+ bi.UnpackCoder = folder.UnpackCoder;
+ bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
+ for (i = 0; i < folder.PackStreams.Size(); i++)
+ bi.PackStreams[i] = folder.PackStreams[i];
+}
+
+static inline bool AreCodersEqual(
+ const NCoderMixer2::CCoderStreamsInfo &a1,
+ const NCoderMixer2::CCoderStreamsInfo &a2)
+{
+ return (a1.NumStreams == a2.NumStreams);
+}
+
+static inline bool AreBondsEqual(
+ const NCoderMixer2::CBond &a1,
+ const NCoderMixer2::CBond &a2)
+{
+ return
+ (a1.PackIndex == a2.PackIndex) &&
+ (a1.UnpackIndex == a2.UnpackIndex);
+}
+
+static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
+{
+ if (a1.Coders.Size() != a2.Coders.Size())
+ return false;
+ unsigned i;
+ for (i = 0; i < a1.Coders.Size(); i++)
+ if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
+ return false;
+
+ if (a1.Bonds.Size() != a2.Bonds.Size())
+ return false;
+ 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.PackStreams.Size() != a2.PackStreams.Size())
+ return false;
+ 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 useMixerMT):
+ _bindInfoPrev_Defined(false),
+ _useMixerMT(useMixerMT)
+{}
+
+
+struct CLockedInStream:
+ public IUnknown,
+ public CMyUnknownImp
+{
+ CMyComPtr<IInStream> Stream;
+ UInt64 Pos;
+
+ MY_UNKNOWN_IMP
+
+ #ifdef USE_MIXER_MT
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
+ #endif
+};
+
+
+#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, unsigned folderIndex,
+ const UInt64 *unpackSize
+
+ , ISequentialOutStream *outStream
+ , ICompressProgressInfo *compressProgress
+
+ , ISequentialInStream **
+ #ifdef USE_MIXER_ST
+ inStreamMainRes
+ #endif
+
+ , bool &dataAfterEnd_Error
+
+ _7Z_DECODER_CRYPRO_VARS_DECL
+
+ #if !defined(_7ZIP_ST)
+ , bool mtMode, UInt32 numThreads, UInt64 memUsage
+ #endif
+ )
+{
+ dataAfterEnd_Error = false;
+
+ const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
+ CFolderEx folderInfo;
+ folders.ParseFolderEx(folderIndex, folderInfo);
+
+ 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
+ */
+
+ if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
+ {
+ _mixerRef.Release();
+
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT)
+ #endif
+ {
+ _mixerMT = new NCoderMixer2::CMixerMT(false);
+ _mixerRef = _mixerMT;
+ _mixer = _mixerMT;
+ }
+ #ifdef USE_MIXER_ST
+ else
+ #endif
+ #endif
+ {
+ #ifdef USE_MIXER_ST
+ _mixerST = new NCoderMixer2::CMixerST(false);
+ _mixerRef = _mixerST;
+ _mixer = _mixerST;
+ #endif
+ }
+
+ RINOK(_mixer->SetBindInfo(bindInfo));
+
+ FOR_VECTOR(i, folderInfo.Coders)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+
+ #ifndef _SFX
+ // we don't support RAR codecs here
+ if ((coderInfo.MethodID >> 8) == 0x403)
+ return E_NOTIMPL;
+ #endif
+
+ CCreatedCoder cod;
+ RINOK(CreateCoder_Id(
+ EXTERNAL_CODECS_LOC_VARS
+ coderInfo.MethodID, false, cod));
+
+ if (coderInfo.IsSimpleCoder())
+ {
+ if (!cod.Coder)
+ return E_NOTIMPL;
+ // CMethodId m = coderInfo.MethodID;
+ // isFilter = (IsFilterMethod(m) || m == k_AES);
+ }
+ else
+ {
+ if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
+ return E_NOTIMPL;
+ }
+ _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
+ */
+ }
+
+ _bindInfoPrev = bindInfo;
+ _bindInfoPrev_Defined = true;
+ }
+
+ _mixer->ReInit();
+
+ UInt32 packStreamIndex = 0;
+ UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
+
+ unsigned i;
+
+ bool mt_wasUsed = false;
+
+ for (i = 0; i < folderInfo.Coders.Size(); i++)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
+
+ #if !defined(_7ZIP_ST)
+ if (!mt_wasUsed)
+ {
+ if (mtMode)
+ {
+ CMyComPtr<ICompressSetCoderMt> setCoderMt;
+ decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
+ if (setCoderMt)
+ {
+ mt_wasUsed = true;
+ RINOK(setCoderMt->SetNumberOfThreads(numThreads));
+ }
+ }
+ // if (memUsage != 0)
+ {
+ CMyComPtr<ICompressSetMemLimit> setMemLimit;
+ decoder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit);
+ if (setMemLimit)
+ {
+ mt_wasUsed = true;
+ RINOK(setMemLimit->SetMemLimit(memUsage));
+ }
+ }
+ }
+ #endif
+
+ {
+ CMyComPtr<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;
+ HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
+ if (res == E_INVALIDARG)
+ res = E_NOTIMPL;
+ RINOK(res);
+ }
+ }
+
+ #ifndef _NO_CRYPTO
+ {
+ CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+ decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
+ if (cryptoSetPassword)
+ {
+ isEncrypted = true;
+ if (!getTextPassword)
+ return E_NOTIMPL;
+ CMyComBSTR passwordBSTR;
+ RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
+ passwordIsDefined = true;
+ password.Empty();
+ size_t len = 0;
+ if (passwordBSTR)
+ {
+ password = passwordBSTR;
+ len = password.Len();
+ }
+ CByteBuffer buffer(len * 2);
+ for (size_t k = 0; k < len; k++)
+ {
+ wchar_t c = passwordBSTR[k];
+ ((Byte *)buffer)[k * 2] = (Byte)c;
+ ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
+ }
+ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
+ }
+ }
+ #endif
+
+ bool finishMode = false;
+ {
+ CMyComPtr<ICompressSetFinishMode> setFinishMode;
+ decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
+ if (setFinishMode)
+ {
+ finishMode = fullUnpack;
+ RINOK(setFinishMode->SetFinishMode(BoolToInt(finishMode)));
+ }
+ }
+
+ UInt32 numStreams = (UInt32)coderInfo.NumStreams;
+
+ CObjArray<UInt64> packSizes(numStreams);
+ CObjArray<const UInt64 *> packSizesPointers(numStreams);
+
+ for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
+ {
+ int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
+
+ if (bond >= 0)
+ packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
+ else
+ {
+ int index = folderInfo.Find_in_PackStreams(packStreamIndex);
+ if (index < 0)
+ 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];
+
+ _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode);
+ }
+
+ 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]);
+ }
+
+ unsigned num = inStreams.Size();
+ CObjArray<ISequentialInStream *> inStreamPointers(num);
+ for (i = 0; i < num; i++)
+ inStreamPointers[i] = inStreams[i];
+
+ 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,
+ dataAfterEnd_Error);
+ }
+
+ #ifdef USE_MIXER_ST
+ return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
+ #else
+ return E_FAIL;
+ #endif
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.h
new file mode 100644
index 0000000000..944f8a3171
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.h
@@ -0,0 +1,70 @@
+// 7zDecode.h
+
+#ifndef __7Z_DECODE_H
+#define __7Z_DECODE_H
+
+#include "../Common/CoderMixer2.h"
+
+#include "7zIn.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CBindInfoEx: public NCoderMixer2::CBindInfo
+{
+ CRecordVector<CMethodId> CoderMethodIDs;
+
+ void Clear()
+ {
+ CBindInfo::Clear();
+ CoderMethodIDs.Clear();
+ }
+};
+
+class CDecoder
+{
+ bool _bindInfoPrev_Defined;
+ CBindInfoEx _bindInfoPrev;
+
+ bool _useMixerMT;
+
+ #ifdef USE_MIXER_ST
+ NCoderMixer2::CMixerST *_mixerST;
+ #endif
+
+ #ifdef USE_MIXER_MT
+ NCoderMixer2::CMixerMT *_mixerMT;
+ #endif
+
+ NCoderMixer2::CMixer *_mixer;
+ CMyComPtr<IUnknown> _mixerRef;
+
+public:
+
+ CDecoder(bool useMixerMT);
+
+ HRESULT Decode(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ IInStream *inStream,
+ UInt64 startPos,
+ 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
+ , bool &dataAfterEnd_Error
+
+ _7Z_DECODER_CRYPRO_VARS_DECL
+
+ #if !defined(_7ZIP_ST)
+ , bool mtMode, UInt32 numThreads, UInt64 memUsage
+ #endif
+ );
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.cpp
new file mode 100644
index 0000000000..4c0d22149a
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -0,0 +1,678 @@
+// 7zEncode.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/FilterCoder.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/InOutTempBuffer.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamObjects.h"
+
+#include "7zEncode.h"
+#include "7zSpecStream.h"
+
+namespace NArchive {
+namespace N7z {
+
+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)
+{
+ folder.Bonds.SetSize(_bindInfo.Bonds.Size());
+
+ unsigned i;
+
+ for (i = 0; i < _bindInfo.Bonds.Size(); i++)
+ {
+ 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++)
+ {
+ CCoderInfo &coderInfo = folder.Coders[i];
+ 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.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;
+ coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
+ if (setCoderProperties)
+ return props.SetCoderProps(setCoderProperties, 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)
+{
+ #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 (m, _options.Methods)
+ {
+ const CMethodFull &methodFull = _options.Methods[m];
+
+ CCreatedCoder cod;
+
+ if (methodFull.CodecIndex >= 0)
+ {
+ RINOK(CreateCoder_Index(
+ EXTERNAL_CODECS_LOC_VARS
+ methodFull.CodecIndex, true, cod));
+ }
+ else
+ {
+ RINOK(CreateCoder_Id(
+ EXTERNAL_CODECS_LOC_VARS
+ methodFull.Id, true, cod));
+ }
+
+ if (cod.NumStreams != methodFull.NumStreams)
+ return E_FAIL;
+ if (!cod.Coder && !cod.Coder2)
+ return E_FAIL;
+
+ CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
+
+ #ifndef _7ZIP_ST
+ {
+ CMyComPtr<ICompressSetCoderMt> setCoderMt;
+ encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ if (setCoderMt)
+ {
+ RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
+ }
+ }
+ #endif
+
+ RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon));
+
+ /*
+ CMyComPtr<ICryptoResetSalt> resetSalt;
+ encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
+ if (resetSalt)
+ {
+ resetSalt->ResetSalt();
+ }
+ */
+
+ // 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 unsigned sizeInBytes = _options.Password.Len() * 2;
+ CByteBuffer buffer(sizeInBytes);
+ for (unsigned i = 0; i < _options.Password.Len(); i++)
+ {
+ wchar_t c = _options.Password[i];
+ ((Byte *)buffer)[i * 2] = (Byte)c;
+ ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+ }
+ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes));
+ }
+
+ _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,
+ CFolder &folderItem,
+ CRecordVector<UInt64> &coderUnpackSizes,
+ UInt64 &unpackSize,
+ ISequentialOutStream *outStream,
+ CRecordVector<UInt64> &packSizes,
+ ICompressProgressInfo *compressProgress)
+{
+ RINOK(EncoderConstr());
+
+ if (!_mixerRef)
+ {
+ RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
+ }
+
+ _mixer->ReInit();
+
+ CMtEncMultiProgress *mtProgressSpec = NULL;
+ CMyComPtr<ICompressProgressInfo> mtProgress;
+
+ CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
+ CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
+
+ CObjectVector<CInOutTempBuffer> inOutTempBuffers;
+ CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
+ CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
+
+ unsigned numMethods = _bindInfo.Coders.Size();
+
+ unsigned i;
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
+ {
+ CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
+ iotb.Create();
+ iotb.InitWriting();
+ }
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
+ {
+ CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2;
+ CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
+ tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
+ tempBuffers.Add(tempBuffer);
+ tempBufferSpecs.Add(tempBufferSpec);
+ }
+
+ for (i = 0; i < numMethods; i++)
+ _mixer->SetCoderInfo(i, NULL, NULL, false);
+
+
+ /* 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)
+ _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
+ */
+
+
+ CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
+ CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
+
+ CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
+ CMyComPtr<ISequentialOutStream> outStreamSizeCount;
+
+ inStreamSizeCountSpec->Init(inStream);
+
+ ISequentialInStream *inStreamPointer = inStreamSizeCount;
+ CRecordVector<ISequentialOutStream *> outStreamPointers;
+
+ SetFolder(folderItem);
+
+ for (i = 0; i < numMethods; i++)
+ {
+ IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
+
+ CMyComPtr<ICryptoResetInitVector> resetInitVector;
+ coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
+ if (resetInitVector)
+ {
+ resetInitVector->ResetInitVector();
+ }
+
+ {
+ CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;
+ coder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);
+ if (optProps)
+ {
+ PROPID propID = NCoderPropID::kExpectedDataSize;
+ NWindows::NCOM::CPropVariant prop = (UInt64)unpackSize;
+ RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1));
+ }
+ }
+
+ CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
+ coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+
+ CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props;
+
+ if (writeCoderProperties)
+ {
+ CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
+ CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
+ outStreamSpec->Init();
+ RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream));
+ outStreamSpec->CopyToBuffer(props);
+ }
+ else
+ props.Free();
+ }
+
+ _mixer->SelectMainCoder(false);
+ UInt32 mainCoder = _mixer->MainCoderIndex;
+
+ bool useMtProgress = false;
+ if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
+ {
+ #ifdef _7ZIP_ST
+ if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
+ #endif
+ useMtProgress = true;
+ }
+
+ if (useMtProgress)
+ {
+ mtProgressSpec = new CMtEncMultiProgress;
+ mtProgress = mtProgressSpec;
+ mtProgressSpec->Init(compressProgress);
+
+ mtOutStreamNotifySpec = new CSequentialOutMtNotify;
+ mtOutStreamNotify = mtOutStreamNotifySpec;
+ mtOutStreamNotifySpec->_stream = outStream;
+ mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec;
+
+ FOR_VECTOR(t, tempBufferSpecs)
+ {
+ tempBufferSpecs[t]->_mtProgresSpec = mtProgressSpec;
+ }
+ }
+
+
+ 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]);
+
+ bool dataAfterEnd_Error;
+
+ RINOK(_mixer->Code(
+ &inStreamPointer,
+ &outStreamPointers.Front(),
+ mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error));
+
+ if (_bindInfo.PackStreams.Size() != 0)
+ packSizes.Add(outStreamSizeCountSpec->GetSize());
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
+ {
+ CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
+ RINOK(inOutTempBuffer.WriteToStream(outStream));
+ packSizes.Add(inOutTempBuffer.GetDataSize());
+ }
+
+ unpackSize = 0;
+
+ for (i = 0; i < _bindInfo.Coders.Size(); i++)
+ {
+ int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]);
+ UInt64 streamSize;
+ if (bond < 0)
+ {
+ streamSize = inStreamSizeCountSpec->GetSize();
+ unpackSize = streamSize;
+ }
+ else
+ streamSize = _mixer->GetBondStreamSize(bond);
+ coderUnpackSizes.Add(streamSize);
+ }
+
+ return S_OK;
+}
+
+
+CEncoder::CEncoder(const CCompressionMethodMode &options):
+ _constructed(false)
+{
+ if (options.IsEmpty())
+ throw 1;
+
+ _options = options;
+
+ #ifdef USE_MIXER_ST
+ _mixerST = NULL;
+ #endif
+
+ #ifdef USE_MIXER_MT
+ _mixerMT = NULL;
+ #endif
+
+ _mixer = NULL;
+}
+
+
+HRESULT CEncoder::EncoderConstr()
+{
+ if (_constructed)
+ return S_OK;
+ if (_options.Methods.IsEmpty())
+ {
+ // it has only password method;
+ if (!_options.PasswordIsDefined)
+ throw 1;
+ if (!_options.Bonds.IsEmpty())
+ throw 1;
+
+ CMethodFull method;
+ method.Id = k_AES;
+ method.NumStreams = 1;
+ _options.Methods.Add(method);
+
+ NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
+ coderStreamsInfo.NumStreams = 1;
+ _bindInfo.Coders.Add(coderStreamsInfo);
+
+ _bindInfo.PackStreams.Add(0);
+ _bindInfo.UnpackCoder = 0;
+ }
+ else
+ {
+
+ UInt32 numOutStreams = 0;
+ unsigned i;
+
+ for (i = 0; i < _options.Methods.Size(); i++)
+ {
+ const CMethodFull &methodFull = _options.Methods[i];
+ NCoderMixer2::CCoderStreamsInfo cod;
+
+ cod.NumStreams = methodFull.NumStreams;
+
+ if (_options.Bonds.IsEmpty())
+ {
+ // if there are no bonds in options, we create bonds via first streams of coders
+ if (i != _options.Methods.Size() - 1)
+ {
+ NCoderMixer2::CBond bond;
+ bond.PackIndex = numOutStreams;
+ bond.UnpackIndex = i + 1; // it's next coder
+ _bindInfo.Bonds.Add(bond);
+ }
+ else if (cod.NumStreams != 0)
+ _bindInfo.PackStreams.Insert(0, numOutStreams);
+
+ for (UInt32 j = 1; j < cod.NumStreams; j++)
+ _bindInfo.PackStreams.Add(numOutStreams + j);
+ }
+
+ numOutStreams += cod.NumStreams;
+
+ _bindInfo.Coders.Add(cod);
+ }
+
+ if (!_options.Bonds.IsEmpty())
+ {
+ for (i = 0; i < _options.Bonds.Size(); i++)
+ {
+ 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 < numOutStreams; i++)
+ if (_bindInfo.FindBond_for_PackStream(i) == -1)
+ _bindInfo.PackStreams.Add(i);
+ }
+
+ if (!_bindInfo.SetUnpackCoder())
+ return E_INVALIDARG;
+
+ if (!_bindInfo.CalcMapsAndCheck())
+ return E_INVALIDARG;
+
+ if (_bindInfo.PackStreams.Size() != 1)
+ {
+ /* 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 (;;)
+ {
+ 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;
+ }
+
+ int si = _bindInfo.FindStream_in_PackStreams(outIndex);
+ if (si >= 0)
+ _bindInfo.PackStreams.MoveToFront(si);
+ break;
+ }
+ }
+
+ if (_options.PasswordIsDefined)
+ {
+ unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
+
+ unsigned numInStreams = _bindInfo.Coders.Size();
+
+ for (i = 0; i < numCryptoStreams; i++)
+ {
+ NCoderMixer2::CBond bond;
+ bond.UnpackIndex = numInStreams + i;
+ bond.PackIndex = _bindInfo.PackStreams[i];
+ _bindInfo.Bonds.Add(bond);
+ }
+ _bindInfo.PackStreams.Clear();
+
+ /*
+ if (numCryptoStreams == 0)
+ numCryptoStreams = 1;
+ */
+
+ for (i = 0; i < numCryptoStreams; i++)
+ {
+ CMethodFull method;
+ method.NumStreams = 1;
+ method.Id = k_AES;
+ _options.Methods.Add(method);
+
+ NCoderMixer2::CCoderStreamsInfo cod;
+ cod.NumStreams = 1;
+ _bindInfo.Coders.Add(cod);
+
+ _bindInfo.PackStreams.Add(numOutStreams++);
+ }
+ }
+
+ }
+
+ for (unsigned i = _options.Methods.Size(); i != 0;)
+ _decompressionMethods.Add(_options.Methods[--i].Id);
+
+ 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() {}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.h
new file mode 100644
index 0000000000..434cbecd3c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.h
@@ -0,0 +1,92 @@
+// 7zEncode.h
+
+#ifndef __7Z_ENCODE_H
+#define __7Z_ENCODE_H
+
+#include "7zCompressionMode.h"
+
+#include "../Common/CoderMixer2.h"
+
+#include "7zItem.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CMtEncMultiProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+ CMyComPtr<ICompressProgressInfo> _progress;
+ #ifndef _7ZIP_ST
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
+ #endif
+
+public:
+ UInt64 OutSize;
+
+ CMtEncMultiProgress(): OutSize(0) {}
+
+ void Init(ICompressProgressInfo *progress);
+
+ 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;
+ 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,
+ CFolder &folderItem,
+ CRecordVector<UInt64> &coderUnpackSizes,
+ UInt64 &unpackSize,
+ ISequentialOutStream *outStream,
+ CRecordVector<UInt64> &packSizes,
+ ICompressProgressInfo *compressProgress);
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zExtract.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zExtract.cpp
new file mode 100644
index 0000000000..075644ffda
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -0,0 +1,423 @@
+// 7zExtract.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/7zCrc.h"
+
+#include "../../../Common/ComTry.h"
+
+#include "../../Common/ProgressUtils.h"
+
+#include "7zDecode.h"
+#include "7zHandler.h"
+
+// EXTERN_g_ExternalCodecs
+
+namespace NArchive {
+namespace N7z {
+
+class CFolderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ 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)
+ {
+ 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)
+ {
+ UInt32 cur = (size < _rem ? size : (UInt32)_rem);
+ if (_calcCrc)
+ {
+ const UInt32 k_Step = (UInt32)1 << 20;
+ if (cur > k_Step)
+ cur = k_Step;
+ }
+ 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
+
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+
+ UInt64 importantTotalUnpacked = 0;
+
+ // numItems = (UInt32)(Int32)-1;
+
+ bool allFilesMode = (numItems == (UInt32)(Int32)-1);
+ if (allFilesMode)
+ numItems = _db.Files.Size();
+
+ if (numItems == 0)
+ return S_OK;
+
+ {
+ CNum prevFolder = kNumNoIndex;
+ UInt32 nextFile = 0;
+
+ UInt32 i;
+
+ for (i = 0; i < numItems; i++)
+ {
+ UInt32 fileIndex = allFilesMode ? i : indices[i];
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex == kNumNoIndex)
+ continue;
+ 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(
+ #if !defined(USE_MIXER_MT)
+ false
+ #elif !defined(USE_MIXER_ST)
+ true
+ #elif !defined(__7Z_SET_PROPERTIES)
+ #ifdef _7ZIP_ST
+ false
+ #else
+ true
+ #endif
+ #else
+ _useMultiThreadMixer
+ #endif
+ );
+
+ UInt64 curPacked, curUnpacked;
+
+ CMyComPtr<IArchiveExtractCallbackMessage> callbackMessage;
+ extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage);
+
+ CFolderOutStream *folderOutStream = new CFolderOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
+
+ folderOutStream->_db = &_db;
+ folderOutStream->ExtractCallback = extractCallback;
+ folderOutStream->TestMode = (testModeSpec != 0);
+ folderOutStream->CheckCrc = (_crcSize != 0);
+
+ for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)
+ {
+ RINOK(lps->SetCur());
+
+ if (i >= numItems)
+ break;
+
+ curUnpacked = 0;
+ curPacked = 0;
+
+ UInt32 fileIndex = allFilesMode ? i : indices[i];
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];
+
+ UInt32 numSolidFiles = 1;
+
+ 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);
+
+ i += numSolidFiles;
+
+ RINOK(result);
+ }
+
+ // to test solid block with zero unpacked size we disable that code
+ if (folderOutStream->WasWritingFinished())
+ continue;
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+ if (extractCallback)
+ extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+ #endif
+
+ try
+ {
+ #ifndef _NO_CRYPTO
+ bool isEncrypted = false;
+ bool passwordIsDefined = false;
+ UString password;
+ #endif
+
+
+ bool dataAfterEnd_Error = false;
+
+ HRESULT result = decoder.Decode(
+ EXTERNAL_CODECS_VARS
+ _inStream,
+ _db.ArcInfo.DataStartPosition,
+ _db, folderIndex,
+ &curUnpacked,
+
+ outStream,
+ progress,
+ NULL // *inStreamMainRes
+ , dataAfterEnd_Error
+
+ _7Z_DECODER_CRYPRO_VARS
+ #if !defined(_7ZIP_ST)
+ , true, _numThreads, _memUsage
+ #endif
+ );
+
+ if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error)
+ {
+ bool wasFinished = folderOutStream->WasWritingFinished();
+
+ int resOp = NExtract::NOperationResult::kDataError;
+
+ if (result != S_FALSE)
+ {
+ if (result == E_NOTIMPL)
+ resOp = NExtract::NOperationResult::kUnsupportedMethod;
+ else if (wasFinished && dataAfterEnd_Error)
+ resOp = NExtract::NOperationResult::kDataAfterEnd;
+ }
+
+ 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;
+
+ RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ catch(...)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
+ // continue;
+ return E_FAIL;
+ }
+ }
+
+ return S_OK;
+
+ COM_TRY_END
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.cpp
new file mode 100644
index 0000000000..eee11a0855
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -0,0 +1,139 @@
+// 7zFolderInStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zFolderInStream.h"
+
+namespace NArchive {
+namespace N7z {
+
+void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
+ const UInt32 *indexes, unsigned numFiles)
+{
+ _updateCallback = updateCallback;
+ _indexes = indexes;
+ _numFiles = numFiles;
+ _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()
+{
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ while (_index < _numFiles)
+ {
+ CMyComPtr<ISequentialInStream> stream;
+ HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
+ if (result != S_OK)
+ {
+ if (result != S_FALSE)
+ return result;
+ }
+
+ _stream = stream;
+
+ if (stream)
+ {
+ CMyComPtr<IStreamGetSize> streamGetSize;
+ stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
+ if (streamGetSize)
+ {
+ if (streamGetSize->GetSize(&_size) == S_OK)
+ _size_Defined = true;
+ }
+ return S_OK;
+ }
+
+ _index++;
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ AddFileInfo(result == S_OK);
+ }
+ return S_OK;
+}
+
+void CFolderInStream::AddFileInfo(bool isProcessed)
+{
+ Processed.Add(isProcessed);
+ Sizes.Add(_pos);
+ CRCs.Add(CRC_GET_DIGEST(_crc));
+}
+
+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ while (size != 0)
+ {
+ if (_stream)
+ {
+ UInt32 cur = size;
+ const UInt32 kMax = (UInt32)1 << 20;
+ if (cur > kMax)
+ cur = kMax;
+ RINOK(_stream->Read(data, cur, &cur));
+ if (cur != 0)
+ {
+ _crc = CrcUpdate(_crc, data, cur);
+ _pos += cur;
+ if (processedSize)
+ *processedSize = cur;
+ return S_OK;
+ }
+
+ _stream.Release();
+ _index++;
+ AddFileInfo(true);
+
+ _pos = 0;
+ _crc = CRC_INIT_VAL;
+ _size_Defined = false;
+ _size = 0;
+
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ }
+
+ if (_index >= _numFiles)
+ break;
+ RINOK(OpenStream());
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+ *value = 0;
+ if (subStream > Sizes.Size())
+ return S_FALSE; // E_FAIL;
+
+ unsigned index = (unsigned)subStream;
+ if (index < Sizes.Size())
+ {
+ *value = Sizes[index];
+ return S_OK;
+ }
+
+ if (!_size_Defined)
+ {
+ *value = _pos;
+ return S_FALSE;
+ }
+
+ *value = (_pos > _size ? _pos : _size);
+ return S_OK;
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.h
new file mode 100644
index 0000000000..f2b1c599ae
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -0,0 +1,61 @@
+// 7zFolderInStream.h
+
+#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"
+
+namespace NArchive {
+namespace N7z {
+
+class CFolderInStream:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _pos;
+ UInt32 _crc;
+ bool _size_Defined;
+ UInt64 _size;
+
+ const UInt32 *_indexes;
+ unsigned _numFiles;
+ unsigned _index;
+
+ CMyComPtr<IArchiveUpdateCallback> _updateCallback;
+
+ HRESULT OpenStream();
+ void AddFileInfo(bool isProcessed);
+
+public:
+ CRecordVector<bool> Processed;
+ CRecordVector<UInt32> CRCs;
+ CRecordVector<UInt64> Sizes;
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+
+ void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);
+
+ bool WasFinished() const { return _index == _numFiles; }
+
+ UInt64 GetFullSize() const
+ {
+ UInt64 size = 0;
+ FOR_VECTOR (i, Sizes)
+ size += Sizes[i];
+ return size;
+ }
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.cpp
new file mode 100644
index 0000000000..a3b0bce1d7
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -0,0 +1,756 @@
+// 7zHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+
+#ifndef __7Z_SET_PROPERTIES
+#include "../../../Windows/System.h"
+#endif
+
+#include "../Common/ItemNameUtils.h"
+
+#include "7zHandler.h"
+#include "7zProperties.h"
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+#include "../Common/ParseProperties.h"
+#endif
+#endif
+
+using namespace NWindows;
+using namespace NCOM;
+
+namespace NArchive {
+namespace N7z {
+
+CHandler::CHandler()
+{
+ #ifndef _NO_CRYPTO
+ _isEncrypted = false;
+ _passwordIsDefined = false;
+ #endif
+
+ #ifdef EXTRACT_ONLY
+
+ _crcSize = 4;
+
+ #ifdef __7Z_SET_PROPERTIES
+ _useMultiThreadMixer = true;
+ #endif
+
+ #endif
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _db.Files.Size();
+ return S_OK;
+}
+
+#ifdef _SFX
+
+IMP_IInArchive_ArcProps_NO_Table
+
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
+{
+ *numProps = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
+ BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
+{
+ return E_NOTIMPL;
+}
+
+#else
+
+static const Byte kArcProps[] =
+{
+ kpidHeadersSize,
+ kpidMethod,
+ kpidSolid,
+ kpidNumBlocks
+ // , kpidIsTree
+};
+
+IMP_IInArchive_ArcProps
+
+static inline char GetHex(unsigned value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)
+{
+ int len = 0;
+ do
+ {
+ s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
+ s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
+ }
+ while (id != 0);
+ return (unsigned)-len;
+}
+
+static void ConvertMethodIdToString(AString &res, UInt64 id)
+{
+ const unsigned kLen = 32;
+ char s[kLen];
+ unsigned len = kLen - 1;
+ s[len] = 0;
+ res += s + len - ConvertMethodIdToString_Back(s + len, id);
+}
+
+static unsigned GetStringForSizeValue(char *s, UInt32 val)
+{
+ unsigned i;
+ for (i = 0; i <= 31; i++)
+ if (((UInt32)1 << i) == val)
+ {
+ if (i < 10)
+ {
+ s[0] = (char)('0' + i);
+ s[1] = 0;
+ return 1;
+ }
+ if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); }
+ else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); }
+ else { s[0] = '3'; s[1] = (char)('0' + i - 30); }
+ s[2] = 0;
+ return 2;
+ }
+ char c = 'b';
+ if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
+ else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
+ ::ConvertUInt32ToString(val, s);
+ unsigned pos = MyStringLen(s);
+ s[pos++] = c;
+ s[pos] = 0;
+ return pos;
+}
+
+/*
+static inline void AddHexToString(UString &res, Byte value)
+{
+ res += GetHex((Byte)(value >> 4));
+ res += GetHex((Byte)(value & 0xF));
+}
+*/
+
+static char *AddProp32(char *s, const char *name, UInt32 v)
+{
+ *s++ = ':';
+ s = MyStpCpy(s, name);
+ ::ConvertUInt32ToString(v, s);
+ return s + MyStringLen(s);
+}
+
+void CHandler::AddMethodName(AString &s, UInt64 id)
+{
+ AString name;
+ FindMethod(EXTERNAL_CODECS_VARS id, name);
+ if (name.IsEmpty())
+ ConvertMethodIdToString(s, id);
+ else
+ s += name;
+}
+
+#endif
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ #ifndef _SFX
+ COM_TRY_BEGIN
+ #endif
+ NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ #ifndef _SFX
+ case kpidMethod:
+ {
+ AString s;
+ const CParsedMethods &pm = _db.ParsedMethods;
+ FOR_VECTOR (i, pm.IDs)
+ {
+ UInt64 id = pm.IDs[i];
+ s.Add_Space_if_NotEmpty();
+ char temp[16];
+ if (id == k_LZMA2)
+ {
+ s += "LZMA2:";
+ if ((pm.Lzma2Prop & 1) == 0)
+ ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp);
+ else
+ GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11));
+ s += temp;
+ }
+ else if (id == k_LZMA)
+ {
+ s += "LZMA:";
+ GetStringForSizeValue(temp, pm.LzmaDic);
+ s += temp;
+ }
+ else
+ AddMethodName(s, id);
+ }
+ prop = s;
+ break;
+ }
+ case kpidSolid: prop = _db.IsSolid(); break;
+ case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;
+ case kpidHeadersSize: prop = _db.HeadersSize; break;
+ case kpidPhySize: prop = _db.PhySize; break;
+ case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;
+ /*
+ case kpidIsTree: if (_db.IsTree) prop = true; break;
+ case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;
+ case kpidIsAux: if (_db.IsTree) prop = true; break;
+ */
+ // case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break;
+ #endif
+
+ case kpidWarningFlags:
+ {
+ UInt32 v = 0;
+ if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;
+ if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;
+ if (v != 0)
+ prop = v;
+ break;
+ }
+
+ case kpidErrorFlags:
+ {
+ UInt32 v = 0;
+ if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;
+ if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;
+ if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
+ // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;
+ if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;
+ prop = v;
+ break;
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+ #ifndef _SFX
+ COM_TRY_END
+ #endif
+}
+
+static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)
+{
+ UInt64 value;
+ if (v.GetItem(index, value))
+ PropVarEm_Set_FileTime64(prop, value);
+}
+
+bool CHandler::IsFolderEncrypted(CNum folderIndex) const
+{
+ if (folderIndex == kNumNoIndex)
+ return false;
+ size_t startPos = _db.FoCodersDataOffset[folderIndex];
+ const Byte *p = _db.CodersData + startPos;
+ size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
+ CInByte2 inByte;
+ inByte.Init(p, size);
+
+ CNum numCoders = inByte.ReadNum();
+ for (; numCoders != 0; numCoders--)
+ {
+ Byte mainByte = inByte.ReadByte();
+ unsigned idSize = (mainByte & 0xF);
+ const Byte *longID = inByte.GetPtr();
+ UInt64 id64 = 0;
+ for (unsigned j = 0; j < idSize; j++)
+ id64 = ((id64 << 8) | longID[j]);
+ inByte.SkipDataNoCheck(idSize);
+ if (id64 == k_AES)
+ return true;
+ if ((mainByte & 0x20) != 0)
+ inByte.SkipDataNoCheck(inByte.ReadNum());
+ }
+ return false;
+}
+
+STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
+{
+ *numProps = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
+{
+ *name = NULL;
+ *propID = kpidNtSecure;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
+{
+ /*
+ const CFileItem &file = _db.Files[index];
+ *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);
+ *parent = (UInt32)(Int32)file.Parent;
+ */
+ *parentType = NParentType::kDir;
+ *parent = (UInt32)(Int32)-1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ *data = NULL;
+ *dataSize = 0;
+ *propType = 0;
+
+ if (/* _db.IsTree && propID == kpidName ||
+ !_db.IsTree && */ propID == kpidPath)
+ {
+ if (_db.NameOffsets && _db.NamesBuf)
+ {
+ size_t offset = _db.NameOffsets[index];
+ size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
+ if (size < ((UInt32)1 << 31))
+ {
+ *data = (const void *)(_db.NamesBuf + offset * 2);
+ *dataSize = (UInt32)size;
+ *propType = NPropDataType::kUtf16z;
+ }
+ }
+ return S_OK;
+ }
+ /*
+ if (propID == kpidNtSecure)
+ {
+ if (index < (UInt32)_db.SecureIDs.Size())
+ {
+ int id = _db.SecureIDs[index];
+ size_t offs = _db.SecureOffsets[id];
+ size_t size = _db.SecureOffsets[id + 1] - offs;
+ if (size >= 0)
+ {
+ *data = _db.SecureBuf + offs;
+ *dataSize = (UInt32)size;
+ *propType = NPropDataType::kRaw;
+ }
+ }
+ }
+ */
+ return S_OK;
+}
+
+#ifndef _SFX
+
+HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
+{
+ PropVariant_Clear(prop);
+ if (folderIndex == kNumNoIndex)
+ return S_OK;
+ // for (int ttt = 0; ttt < 1; ttt++) {
+ const unsigned kTempSize = 256;
+ char temp[kTempSize];
+ unsigned pos = kTempSize;
+ temp[--pos] = 0;
+
+ size_t startPos = _db.FoCodersDataOffset[folderIndex];
+ const Byte *p = _db.CodersData + startPos;
+ size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
+ CInByte2 inByte;
+ inByte.Init(p, size);
+
+ // numCoders == 0 ???
+ CNum numCoders = inByte.ReadNum();
+ bool needSpace = false;
+
+ for (; numCoders != 0; numCoders--, needSpace = true)
+ {
+ if (pos < 32) // max size of property
+ break;
+ Byte mainByte = inByte.ReadByte();
+ unsigned idSize = (mainByte & 0xF);
+ const Byte *longID = inByte.GetPtr();
+ UInt64 id64 = 0;
+ for (unsigned j = 0; j < idSize; j++)
+ id64 = ((id64 << 8) | longID[j]);
+ inByte.SkipDataNoCheck(idSize);
+
+ if ((mainByte & 0x10) != 0)
+ {
+ inByte.ReadNum(); // NumInStreams
+ inByte.ReadNum(); // NumOutStreams
+ }
+
+ CNum propsSize = 0;
+ const Byte *props = NULL;
+ if ((mainByte & 0x20) != 0)
+ {
+ propsSize = inByte.ReadNum();
+ props = inByte.GetPtr();
+ inByte.SkipDataNoCheck(propsSize);
+ }
+
+ const char *name = NULL;
+ char s[32];
+ s[0] = 0;
+
+ if (id64 <= (UInt32)0xFFFFFFFF)
+ {
+ UInt32 id = (UInt32)id64;
+ if (id == k_LZMA)
+ {
+ name = "LZMA";
+ if (propsSize == 5)
+ {
+ UInt32 dicSize = GetUi32((const Byte *)props + 1);
+ char *dest = s + GetStringForSizeValue(s, dicSize);
+ UInt32 d = props[0];
+ if (d != 0x5D)
+ {
+ UInt32 lc = d % 9;
+ d /= 9;
+ UInt32 pb = d / 5;
+ UInt32 lp = d % 5;
+ if (lc != 3) dest = AddProp32(dest, "lc", lc);
+ if (lp != 0) dest = AddProp32(dest, "lp", lp);
+ if (pb != 2) dest = AddProp32(dest, "pb", pb);
+ }
+ }
+ }
+ else if (id == k_LZMA2)
+ {
+ name = "LZMA2";
+ if (propsSize == 1)
+ {
+ Byte d = props[0];
+ if ((d & 1) == 0)
+ ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);
+ else
+ GetStringForSizeValue(s, 3 << ((d >> 1) + 11));
+ }
+ }
+ else if (id == k_PPMD)
+ {
+ name = "PPMD";
+ if (propsSize == 5)
+ {
+ Byte order = *props;
+ char *dest = s;
+ *dest++ = 'o';
+ ConvertUInt32ToString(order, dest);
+ dest += MyStringLen(dest);
+ dest = MyStpCpy(dest, ":mem");
+ GetStringForSizeValue(dest, GetUi32(props + 1));
+ }
+ }
+ else if (id == k_Delta)
+ {
+ name = "Delta";
+ if (propsSize == 1)
+ ConvertUInt32ToString((UInt32)props[0] + 1, s);
+ }
+ else if (id == k_BCJ2) name = "BCJ2";
+ else if (id == k_BCJ) name = "BCJ";
+ else if (id == k_AES)
+ {
+ name = "7zAES";
+ if (propsSize >= 1)
+ {
+ Byte firstByte = props[0];
+ UInt32 numCyclesPower = firstByte & 0x3F;
+ ConvertUInt32ToString(numCyclesPower, s);
+ }
+ }
+ }
+
+ if (name)
+ {
+ unsigned nameLen = MyStringLen(name);
+ unsigned propsLen = MyStringLen(s);
+ unsigned totalLen = nameLen + propsLen;
+ if (propsLen != 0)
+ totalLen++;
+ if (needSpace)
+ totalLen++;
+ if (totalLen + 5 >= pos)
+ break;
+ pos -= totalLen;
+ MyStringCopy(temp + pos, name);
+ if (propsLen != 0)
+ {
+ char *dest = temp + pos + nameLen;
+ *dest++ = ':';
+ MyStringCopy(dest, s);
+ }
+ if (needSpace)
+ temp[pos + totalLen - 1] = ' ';
+ }
+ else
+ {
+ AString methodName;
+ FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
+ if (needSpace)
+ temp[--pos] = ' ';
+ if (methodName.IsEmpty())
+ pos -= ConvertMethodIdToString_Back(temp + pos, id64);
+ else
+ {
+ unsigned len = methodName.Len();
+ if (len + 5 > pos)
+ break;
+ pos -= len;
+ for (unsigned i = 0; i < len; i++)
+ temp[pos + i] = methodName[i];
+ }
+ }
+ }
+
+ if (numCoders != 0 && pos >= 4)
+ {
+ temp[--pos] = ' ';
+ temp[--pos] = '.';
+ temp[--pos] = '.';
+ temp[--pos] = '.';
+ }
+
+ return PropVarEm_Set_Str(prop, temp + pos);
+ // }
+}
+
+#endif
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ PropVariant_Clear(value);
+ // COM_TRY_BEGIN
+ // NCOM::CPropVariant prop;
+
+ /*
+ const CRef2 &ref2 = _refs[index];
+ if (ref2.Refs.IsEmpty())
+ return E_FAIL;
+ const CRef &ref = ref2.Refs.Front();
+ */
+
+ const CFileItem &item = _db.Files[index];
+ const UInt32 index2 = index;
+
+ switch (propID)
+ {
+ case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
+ case kpidSize:
+ {
+ PropVarEm_Set_UInt64(value, item.Size);
+ // prop = ref2.Size;
+ break;
+ }
+ case kpidPackSize:
+ {
+ // prop = ref2.PackSize;
+ {
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
+ PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));
+ /*
+ else
+ PropVarEm_Set_UInt64(value, 0);
+ */
+ }
+ else
+ PropVarEm_Set_UInt64(value, 0);
+ }
+ break;
+ }
+ // case kpidIsAux: prop = _db.IsItemAux(index2); break;
+ case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }
+ case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
+ case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
+ case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
+ case kpidAttrib: if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break;
+ case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
+ case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
+ case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
+ /*
+ case kpidIsAltStream: prop = item.IsAltStream; break;
+ case kpidNtSecure:
+ {
+ int id = _db.SecureIDs[index];
+ size_t offs = _db.SecureOffsets[id];
+ size_t size = _db.SecureOffsets[id + 1] - offs;
+ if (size >= 0)
+ {
+ prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);
+ }
+ break;
+ }
+ */
+
+ case kpidPath: return _db.GetPath_Prop(index, value);
+
+ #ifndef _SFX
+
+ case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
+ case kpidBlock:
+ {
+ CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ 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)
+ {
+ if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
+ _db.FoStartPackStreamIndex[folderIndex + 1] -
+ _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))
+ {
+ PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));
+ }
+ }
+ else
+ PropVarEm_Set_UInt64(value, 0);
+ }
+ break;
+ */
+
+ #endif
+ }
+ // prop.Detach(value);
+ return S_OK;
+ // COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ #ifndef _SFX
+ _fileInfoPopIDs.Clear();
+ #endif
+
+ try
+ {
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+ if (openArchiveCallback)
+ openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+ #endif
+
+ CInArchive archive(
+ #ifdef __7Z_SET_PROPERTIES
+ _useMultiThreadMixer
+ #else
+ true
+ #endif
+ );
+ _db.IsArc = false;
+ RINOK(archive.Open(stream, maxCheckStartPosition));
+ _db.IsArc = true;
+
+ HRESULT result = archive.ReadDatabase(
+ EXTERNAL_CODECS_VARS
+ _db
+ #ifndef _NO_CRYPTO
+ , getTextPassword, _isEncrypted, _passwordIsDefined, _password
+ #endif
+ );
+ RINOK(result);
+
+ _inStream = stream;
+ }
+ catch(...)
+ {
+ Close();
+ // return E_INVALIDARG;
+ // return S_FALSE;
+ // we must return out_of_memory here
+ return E_OUTOFMEMORY;
+ }
+ // _inStream = stream;
+ #ifndef _SFX
+ FillPopIDs();
+ #endif
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ COM_TRY_BEGIN
+ _inStream.Release();
+ _db.Clear();
+ #ifndef _NO_CRYPTO
+ _isEncrypted = false;
+ _passwordIsDefined = false;
+ _password.Empty();
+ #endif
+ return S_OK;
+ COM_TRY_END
+}
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
+{
+ COM_TRY_BEGIN
+
+ InitCommon();
+ _useMultiThreadMixer = true;
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ UString name = names[i];
+ name.MakeLower_Ascii();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+ const PROPVARIANT &value = values[i];
+ UInt32 number;
+ unsigned index = ParseStringToUInt32(name, number);
+ if (index == 0)
+ {
+ if (name.IsEqualTo("mtf"))
+ {
+ RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer));
+ continue;
+ }
+ {
+ HRESULT hres;
+ if (SetCommonProperty(name, value, hres))
+ {
+ RINOK(hres);
+ continue;
+ }
+ }
+ return E_INVALIDARG;
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+#endif
+#endif
+
+IMPL_ISetCompressCodecsInfo
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.h
new file mode 100644
index 0000000000..7d5a5f0099
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.h
@@ -0,0 +1,181 @@
+// 7z/Handler.h
+
+#ifndef __7Z_HANDLER_H
+#define __7Z_HANDLER_H
+
+#include "../../ICoder.h"
+#include "../IArchive.h"
+
+#include "../../Common/CreateCoder.h"
+
+#ifndef __7Z_SET_PROPERTIES
+
+#ifdef EXTRACT_ONLY
+ #if !defined(_7ZIP_ST) && !defined(_SFX)
+ #define __7Z_SET_PROPERTIES
+ #endif
+#else
+ #define __7Z_SET_PROPERTIES
+#endif
+
+#endif
+
+// #ifdef __7Z_SET_PROPERTIES
+#include "../Common/HandlerOut.h"
+// #endif
+
+#include "7zCompressionMode.h"
+#include "7zIn.h"
+
+namespace NArchive {
+namespace N7z {
+
+
+#ifndef EXTRACT_ONLY
+
+class COutHandler: public CMultiMethodProps
+{
+ HRESULT SetSolidFromString(const UString &s);
+ HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);
+public:
+ UInt64 _numSolidFiles;
+ UInt64 _numSolidBytes;
+ bool _numSolidBytesDefined;
+ bool _solidExtension;
+ bool _useTypeSorting;
+
+ bool _compressHeaders;
+ bool _encryptHeadersSpecified;
+ bool _encryptHeaders;
+ // bool _useParents; 9.26
+
+ CBoolPair Write_CTime;
+ CBoolPair Write_ATime;
+ CBoolPair Write_MTime;
+ CBoolPair Write_Attrib;
+
+ bool _useMultiThreadMixer;
+
+ bool _removeSfxBlock;
+
+ // bool _volumeMode;
+
+ void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
+ void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
+ void InitSolid()
+ {
+ InitSolidFiles();
+ InitSolidSize();
+ _solidExtension = false;
+ _numSolidBytesDefined = false;
+ }
+
+ void InitProps7z();
+ void InitProps();
+
+ COutHandler() { InitProps7z(); }
+
+ HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
+};
+
+#endif
+
+class CHandler:
+ public IInArchive,
+ public IArchiveGetRawProps,
+
+ #ifdef __7Z_SET_PROPERTIES
+ public ISetProperties,
+ #endif
+
+ #ifndef EXTRACT_ONLY
+ public IOutArchive,
+ #endif
+
+ PUBLIC_ISetCompressCodecsInfo
+
+ public CMyUnknownImp,
+
+ #ifndef EXTRACT_ONLY
+ public COutHandler
+ #else
+ public CCommonMethodProps
+ #endif
+{
+public:
+ MY_QUERYINTERFACE_BEGIN2(IInArchive)
+ MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
+ #ifdef __7Z_SET_PROPERTIES
+ MY_QUERYINTERFACE_ENTRY(ISetProperties)
+ #endif
+ #ifndef EXTRACT_ONLY
+ MY_QUERYINTERFACE_ENTRY(IOutArchive)
+ #endif
+ QUERY_ENTRY_ISetCompressCodecsInfo
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ INTERFACE_IInArchive(;)
+ INTERFACE_IArchiveGetRawProps(;)
+
+ #ifdef __7Z_SET_PROPERTIES
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
+ #endif
+
+ #ifndef EXTRACT_ONLY
+ INTERFACE_IOutArchive(;)
+ #endif
+
+ DECL_ISetCompressCodecsInfo
+
+ CHandler();
+
+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
+ bool _useMultiThreadMixer;
+ #endif
+
+ UInt32 _crcSize;
+
+ #else
+
+ CRecordVector<CBond2> _bonds;
+
+ HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
+ HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
+ HRESULT SetMainMethod(CCompressionMethodMode &method
+ #ifndef _7ZIP_ST
+ , UInt32 numThreads
+ #endif
+ );
+
+
+ #endif
+
+ bool IsFolderEncrypted(CNum folderIndex) const;
+ #ifndef _SFX
+
+ CRecordVector<UInt64> _fileInfoPopIDs;
+ void FillPopIDs();
+ void AddMethodName(AString &s, UInt64 id);
+ HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const;
+
+ #endif
+
+ DECL_EXTERNAL_CODECS_VARS
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandlerOut.cpp
new file mode 100644
index 0000000000..f0474bbfe8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -0,0 +1,939 @@
+// 7zHandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringToInt.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/ParseProperties.h"
+
+#include "7zHandler.h"
+#include "7zOut.h"
+#include "7zUpdate.h"
+
+#ifndef EXTRACT_ONLY
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace N7z {
+
+#define k_LZMA_Name "LZMA"
+#define kDefaultMethodName "LZMA2"
+#define k_Copy_Name "Copy"
+
+#define k_MatchFinder_ForHeaders "BT2"
+
+static const UInt32 k_NumFastBytes_ForHeaders = 273;
+static const UInt32 k_Level_ForHeaders = 5;
+static const UInt32 k_Dictionary_ForHeaders =
+ #ifdef UNDER_CE
+ 1 << 18;
+ #else
+ 1 << 20;
+ #endif
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kWindows;
+ return S_OK;
+}
+
+HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)
+{
+ dest.CodecIndex = FindMethod_Index(
+ EXTERNAL_CODECS_VARS
+ m.MethodName, true,
+ dest.Id, dest.NumStreams);
+ if (dest.CodecIndex < 0)
+ return E_INVALIDARG;
+ (CProps &)dest = (CProps &)m;
+ return S_OK;
+}
+
+HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
+{
+ if (!_compressHeaders)
+ return S_OK;
+ COneMethodInfo m;
+ m.MethodName = k_LZMA_Name;
+ 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.AddProp_NumThreads(1);
+
+ CMethodFull &methodFull = headerMethod.Methods.AddNew();
+ return PropsMethod_To_FullMethod(methodFull, m);
+}
+
+HRESULT CHandler::SetMainMethod(
+ CCompressionMethodMode &methodMode
+ #ifndef _7ZIP_ST
+ , UInt32 numThreads
+ #endif
+ )
+{
+ 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];
+
+ SetGlobalLevelTo(oneMethodInfo);
+ #ifndef _7ZIP_ST
+ CMultiMethodProps::SetMethodThreadsTo(oneMethodInfo, numThreads);
+ #endif
+
+ CMethodFull &methodFull = methodMode.Methods.AddNew();
+ RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
+
+ if (methodFull.Id != k_Copy)
+ needSolid = true;
+
+ if (_numSolidBytesDefined)
+ continue;
+
+ UInt32 dicSize;
+ switch (methodFull.Id)
+ {
+ case k_LZMA:
+ case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;
+ case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;
+ case k_Deflate: dicSize = (UInt32)1 << 15; break;
+ 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;
+ _numSolidBytesDefined = true;
+ }
+
+ if (!_numSolidBytesDefined)
+ if (needSolid)
+ _numSolidBytes = kSolidBytes_Max;
+ else
+ _numSolidBytes = 0;
+ _numSolidBytesDefined = true;
+ return S_OK;
+}
+
+static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined)
+{
+ // ft = 0;
+ // ftDefined = false;
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32);
+ ftDefined = true;
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ else
+ {
+ ft = 0;
+ ftDefined = false;
+ }
+ return S_OK;
+}
+
+/*
+
+#ifdef _WIN32
+static const wchar_t kDirDelimiter1 = L'\\';
+#endif
+static const wchar_t kDirDelimiter2 = L'/';
+
+static inline bool IsCharDirLimiter(wchar_t c)
+{
+ return (
+ #ifdef _WIN32
+ c == kDirDelimiter1 ||
+ #endif
+ c == kDirDelimiter2);
+}
+
+static int FillSortIndex(CObjectVector<CTreeFolder> &treeFolders, int cur, int curSortIndex)
+{
+ CTreeFolder &tf = treeFolders[cur];
+ tf.SortIndex = curSortIndex++;
+ for (int i = 0; i < tf.SubFolders.Size(); i++)
+ curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex);
+ tf.SortIndexEnd = curSortIndex;
+ return curSortIndex;
+}
+
+static int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos)
+{
+ const CIntVector &subFolders = treeFolders[cur].SubFolders;
+ int left = 0, right = subFolders.Size();
+ insertPos = -1;
+ for (;;)
+ {
+ if (left == right)
+ {
+ insertPos = left;
+ return -1;
+ }
+ int mid = (left + right) / 2;
+ int midFolder = subFolders[mid];
+ int compare = CompareFileNames(name, treeFolders[midFolder].Name);
+ if (compare == 0)
+ return midFolder;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+}
+
+static int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name)
+{
+ int insertPos;
+ int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos);
+ if (folderIndex < 0)
+ {
+ folderIndex = treeFolders.Size();
+ CTreeFolder &newFolder = treeFolders.AddNew();
+ newFolder.Parent = cur;
+ newFolder.Name = name;
+ treeFolders[cur].SubFolders.Insert(insertPos, folderIndex);
+ }
+ // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234;
+ return folderIndex;
+}
+*/
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ COM_TRY_BEGIN
+
+ const CDbEx *db = 0;
+ #ifdef _7Z_VOL
+ if (_volumes.Size() > 1)
+ return E_FAIL;
+ const CVolume *volume = 0;
+ if (_volumes.Size() == 1)
+ {
+ volume = &_volumes.Front();
+ db = &volume->Database;
+ }
+ #else
+ if (_inStream != 0)
+ db = &_db;
+ #endif
+
+ /*
+ CMyComPtr<IArchiveGetRawProps> getRawProps;
+ updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);
+
+ CUniqBlocks secureBlocks;
+ secureBlocks.AddUniq(NULL, 0);
+
+ CObjectVector<CTreeFolder> treeFolders;
+ {
+ CTreeFolder folder;
+ folder.Parent = -1;
+ treeFolders.Add(folder);
+ }
+ */
+
+ CObjectVector<CUpdateItem> updateItems;
+
+ bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
+ bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
+ bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
+ bool need_Attrib = (Write_Attrib.Def && Write_Attrib.Val || !Write_Attrib.Def);
+
+ if (db && !db->Files.IsEmpty())
+ {
+ if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
+ if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
+ if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();
+ if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty();
+ }
+
+ // UString s;
+ UString name;
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ Int32 newData, newProps;
+ UInt32 indexInArchive;
+ if (!updateCallback)
+ return E_FAIL;
+ RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+ CUpdateItem ui;
+ ui.NewProps = IntToBool(newProps);
+ ui.NewData = IntToBool(newData);
+ ui.IndexInArchive = indexInArchive;
+ ui.IndexInClient = i;
+ ui.IsAnti = false;
+ ui.Size = 0;
+
+ name.Empty();
+ // bool isAltStream = false;
+ if (ui.IndexInArchive != -1)
+ {
+ if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size())
+ return E_INVALIDARG;
+ const CFileItem &fi = db->Files[ui.IndexInArchive];
+ if (!ui.NewProps)
+ {
+ _db.GetPath(ui.IndexInArchive, name);
+ }
+ ui.IsDir = fi.IsDir;
+ ui.Size = fi.Size;
+ // isAltStream = fi.IsAltStream;
+ ui.IsAnti = db->IsItemAnti(ui.IndexInArchive);
+
+ if (!ui.NewProps)
+ {
+ ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);
+ ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);
+ ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);
+ }
+ }
+
+ if (ui.NewProps)
+ {
+ bool folderStatusIsDefined;
+ if (need_Attrib)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.AttribDefined = false;
+ else if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ else
+ {
+ ui.Attrib = prop.ulVal;
+ ui.AttribDefined = true;
+ }
+ }
+
+ // we need MTime to sort files.
+ if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined));
+ if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined));
+ if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined));
+
+ /*
+ if (getRawProps)
+ {
+ const void *data;
+ UInt32 dataSize;
+ UInt32 propType;
+
+ getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);
+ if (dataSize != 0 && propType != NPropDataType::kRaw)
+ return E_FAIL;
+ ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize);
+ }
+ */
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidPath, &prop));
+ if (prop.vt == VT_EMPTY)
+ {
+ }
+ else if (prop.vt != VT_BSTR)
+ return E_INVALIDARG;
+ else
+ {
+ name = prop.bstrVal;
+ NItemName::ReplaceSlashes_OsToUnix(name);
+ }
+ }
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop));
+ if (prop.vt == VT_EMPTY)
+ folderStatusIsDefined = false;
+ else if (prop.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ {
+ ui.IsDir = (prop.boolVal != VARIANT_FALSE);
+ folderStatusIsDefined = true;
+ }
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.IsAnti = false;
+ else if (prop.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ ui.IsAnti = (prop.boolVal != VARIANT_FALSE);
+ }
+
+ /*
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop));
+ if (prop.vt == VT_EMPTY)
+ isAltStream = false;
+ else if (prop.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ isAltStream = (prop.boolVal != VARIANT_FALSE);
+ }
+ */
+
+ if (ui.IsAnti)
+ {
+ ui.AttribDefined = false;
+
+ ui.CTimeDefined = false;
+ ui.ATimeDefined = false;
+ ui.MTimeDefined = false;
+
+ ui.Size = 0;
+ }
+
+ if (!folderStatusIsDefined && ui.AttribDefined)
+ ui.SetDirStatusFromAttrib();
+ }
+ else
+ {
+ /*
+ if (_db.SecureIDs.IsEmpty())
+ ui.SecureIndex = secureBlocks.AddUniq(NULL, 0);
+ else
+ {
+ int id = _db.SecureIDs[ui.IndexInArchive];
+ size_t offs = _db.SecureOffsets[id];
+ size_t size = _db.SecureOffsets[id + 1] - offs;
+ ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size);
+ }
+ */
+ }
+
+ /*
+ {
+ int folderIndex = 0;
+ if (_useParents)
+ {
+ int j;
+ s.Empty();
+ for (j = 0; j < name.Len(); j++)
+ {
+ wchar_t c = name[j];
+ if (IsCharDirLimiter(c))
+ {
+ folderIndex = AddFolder(treeFolders, folderIndex, s);
+ s.Empty();
+ continue;
+ }
+ s += c;
+ }
+ if (isAltStream)
+ {
+ int colonPos = s.Find(':');
+ if (colonPos < 0)
+ {
+ // isAltStream = false;
+ return E_INVALIDARG;
+ }
+ UString mainName = s.Left(colonPos);
+ int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName);
+ if (treeFolders[newFolderIndex].UpdateItemIndex < 0)
+ {
+ for (int j = updateItems.Size() - 1; j >= 0; j--)
+ {
+ CUpdateItem &ui2 = updateItems[j];
+ if (ui2.ParentFolderIndex == folderIndex
+ && ui2.Name == mainName)
+ {
+ ui2.TreeFolderIndex = newFolderIndex;
+ treeFolders[newFolderIndex].UpdateItemIndex = j;
+ }
+ }
+ }
+ folderIndex = newFolderIndex;
+ s.Delete(0, colonPos + 1);
+ }
+ ui.Name = s;
+ }
+ else
+ ui.Name = name;
+ ui.IsAltStream = isAltStream;
+ ui.ParentFolderIndex = folderIndex;
+ ui.TreeFolderIndex = -1;
+ if (ui.IsDir && !s.IsEmpty())
+ {
+ ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s);
+ treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size();
+ }
+ }
+ */
+ ui.Name = name;
+
+ if (ui.NewData)
+ {
+ ui.Size = 0;
+ if (!ui.IsDir)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ ui.Size = (UInt64)prop.uhVal.QuadPart;
+ if (ui.Size != 0 && ui.IsAnti)
+ return E_INVALIDARG;
+ }
+ }
+
+ updateItems.Add(ui);
+ }
+
+ /*
+ FillSortIndex(treeFolders, 0, 0);
+ for (i = 0; i < (UInt32)updateItems.Size(); i++)
+ {
+ CUpdateItem &ui = updateItems[i];
+ ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex;
+ ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd;
+ }
+ */
+
+ CCompressionMethodMode methodMode, headerMethod;
+
+ HRESULT res = SetMainMethod(methodMode
+ #ifndef _7ZIP_ST
+ , _numThreads
+ #endif
+ );
+ RINOK(res);
+
+ RINOK(SetHeaderMethod(headerMethod));
+
+ #ifndef _7ZIP_ST
+ methodMode.NumThreads = _numThreads;
+ methodMode.MultiThreadMixer = _useMultiThreadMixer;
+ headerMethod.NumThreads = 1;
+ headerMethod.MultiThreadMixer = _useMultiThreadMixer;
+ #endif
+
+ CMyComPtr<ICryptoGetTextPassword2> getPassword2;
+ updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
+
+ methodMode.PasswordIsDefined = false;
+ methodMode.Password.Empty();
+ if (getPassword2)
+ {
+ CMyComBSTR password;
+ Int32 passwordIsDefined;
+ RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
+ methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
+ if (methodMode.PasswordIsDefined && password)
+ methodMode.Password = password;
+ }
+
+ bool compressMainHeader = _compressHeaders; // check it
+
+ 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)
+ encryptHeaders = _encryptHeaders;
+ #ifndef _NO_CRYPTO
+ else
+ encryptHeaders = _passwordIsDefined;
+ #endif
+ compressMainHeader = true;
+ if (encryptHeaders)
+ {
+ headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;
+ headerMethod.Password = methodMode.Password;
+ }
+ }
+
+ if (numItems < 2)
+ compressMainHeader = false;
+
+ int level = GetLevel();
+
+ CUpdateOptions options;
+ options.Method = &methodMode;
+ 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;
+ /*
+ options.HeaderOptions.WriteCTime = Write_CTime;
+ options.HeaderOptions.WriteATime = Write_ATime;
+ options.HeaderOptions.WriteMTime = Write_MTime;
+ options.HeaderOptions.WriteAttrib = Write_Attrib;
+ */
+
+ options.NumSolidFiles = _numSolidFiles;
+ options.NumSolidBytes = _numSolidBytes;
+ options.SolidExtension = _solidExtension;
+ options.UseTypeSorting = _useTypeSorting;
+
+ options.RemoveSfxBlock = _removeSfxBlock;
+ // options.VolumeMode = _volumeMode;
+
+ options.MultiThreadMixer = _useMultiThreadMixer;
+
+ COutArchive archive;
+ CArchiveDatabaseOut newDatabase;
+
+ CMyComPtr<ICryptoGetTextPassword> getPassword;
+ updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
+
+ /*
+ if (secureBlocks.Sorted.Size() > 1)
+ {
+ secureBlocks.GetReverseMap();
+ for (int i = 0; i < updateItems.Size(); i++)
+ {
+ int &secureIndex = updateItems[i].SecureIndex;
+ secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex];
+ }
+ }
+ */
+
+ res = Update(
+ EXTERNAL_CODECS_VARS
+ #ifdef _7Z_VOL
+ volume ? volume->Stream: 0,
+ volume ? db : 0,
+ #else
+ _inStream,
+ db,
+ #endif
+ updateItems,
+ // treeFolders,
+ // secureBlocks,
+ archive, newDatabase, outStream, updateCallback, options
+ #ifndef _NO_CRYPTO
+ , getPassword
+ #endif
+ );
+
+ RINOK(res);
+
+ updateItems.ClearAndFree();
+
+ return archive.WriteDatabase(EXTERNAL_CODECS_VARS
+ newDatabase, options.HeaderMethod, options.HeaderOptions);
+
+ COM_TRY_END
+}
+
+static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)
+{
+ stream = 0;
+ {
+ unsigned index = ParseStringToUInt32(srcString, coder);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.DeleteFrontal(index);
+ }
+ if (srcString[0] == 's')
+ {
+ srcString.Delete(0);
+ unsigned index = ParseStringToUInt32(srcString, stream);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.DeleteFrontal(index);
+ }
+ return S_OK;
+}
+
+void COutHandler::InitProps7z()
+{
+ _removeSfxBlock = false;
+ _compressHeaders = true;
+ _encryptHeadersSpecified = false;
+ _encryptHeaders = false;
+ // _useParents = false;
+
+ Write_CTime.Init();
+ Write_ATime.Init();
+ Write_MTime.Init();
+ Write_Attrib.Init();
+
+ _useMultiThreadMixer = true;
+
+ // _volumeMode = false;
+
+ InitSolid();
+ _useTypeSorting = false;
+}
+
+void COutHandler::InitProps()
+{
+ CMultiMethodProps::Init();
+ InitProps7z();
+}
+
+
+
+HRESULT COutHandler::SetSolidFromString(const UString &s)
+{
+ UString s2 = s;
+ s2.MakeLower_Ascii();
+ for (unsigned i = 0; i < s2.Len();)
+ {
+ const wchar_t *start = ((const wchar_t *)s2) + i;
+ const wchar_t *end;
+ UInt64 v = ConvertStringToUInt64(start, &end);
+ if (start == end)
+ {
+ if (s2[i++] != 'e')
+ return E_INVALIDARG;
+ _solidExtension = true;
+ continue;
+ }
+ i += (int)(end - start);
+ if (i == s2.Len())
+ return E_INVALIDARG;
+ wchar_t c = s2[i++];
+ if (c == 'f')
+ {
+ if (v < 1)
+ v = 1;
+ _numSolidFiles = v;
+ }
+ else
+ {
+ unsigned numBits;
+ switch (c)
+ {
+ case 'b': numBits = 0; break;
+ case 'k': numBits = 10; break;
+ case 'm': numBits = 20; break;
+ case 'g': numBits = 30; break;
+ case 't': numBits = 40; break;
+ default: return E_INVALIDARG;
+ }
+ _numSolidBytes = (v << numBits);
+ _numSolidBytesDefined = true;
+ /*
+ if (_numSolidBytes == 0)
+ _numSolidFiles = 1;
+ */
+ }
+ }
+ return S_OK;
+}
+
+HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
+{
+ bool isSolid;
+ switch (value.vt)
+ {
+ case VT_EMPTY: isSolid = true; break;
+ case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
+ case VT_BSTR:
+ if (StringToBool(value.bstrVal, isSolid))
+ break;
+ return SetSolidFromString(value.bstrVal);
+ default: return E_INVALIDARG;
+ }
+ if (isSolid)
+ InitSolid();
+ else
+ _numSolidFiles = 1;
+ return S_OK;
+}
+
+static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
+{
+ RINOK(PROPVARIANT_to_bool(prop, dest.Val));
+ dest.Def = true;
+ return S_OK;
+}
+
+HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
+{
+ UString name = nameSpec;
+ name.MakeLower_Ascii();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ if (name[0] == L's')
+ {
+ name.Delete(0);
+ if (name.IsEmpty())
+ return SetSolidFromPROPVARIANT(value);
+ if (value.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return SetSolidFromString(name);
+ }
+
+ UInt32 number;
+ int index = ParseStringToUInt32(name, number);
+ // UString realName = name.Ptr(index);
+ if (index == 0)
+ {
+ if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
+ if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders);
+ // if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents);
+
+ if (name.IsEqualTo("hcf"))
+ {
+ bool compressHeadersFull = true;
+ RINOK(PROPVARIANT_to_bool(value, compressHeadersFull));
+ return compressHeadersFull ? S_OK: E_INVALIDARG;
+ }
+
+ if (name.IsEqualTo("he"))
+ {
+ RINOK(PROPVARIANT_to_bool(value, _encryptHeaders));
+ _encryptHeadersSpecified = true;
+ return S_OK;
+ }
+
+ if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime);
+ 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("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib);
+
+ if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
+
+ if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
+
+ // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
+ }
+ return CMultiMethodProps::SetProperty(name, value);
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
+{
+ COM_TRY_BEGIN
+ _bonds.Clear();
+ InitProps();
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ UString name = names[i];
+ name.MakeLower_Ascii();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ const PROPVARIANT &value = values[i];
+
+ if (name[0] == 'b')
+ {
+ if (value.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ name.Delete(0);
+
+ CBond2 bond;
+ RINOK(ParseBond(name, bond.OutCoder, bond.OutStream));
+ if (name[0] != ':')
+ return E_INVALIDARG;
+ name.Delete(0);
+ UInt32 inStream = 0;
+ RINOK(ParseBond(name, bond.InCoder, inStream));
+ if (inStream != 0)
+ return E_INVALIDARG;
+ if (!name.IsEmpty())
+ return E_INVALIDARG;
+ _bonds.Add(bond);
+ continue;
+ }
+
+ RINOK(SetProperty(name, value));
+ }
+
+ unsigned numEmptyMethods = GetNumEmptyMethods();
+ if (numEmptyMethods > 0)
+ {
+ unsigned k;
+ for (k = 0; k < _bonds.Size(); k++)
+ {
+ const CBond2 &bond = _bonds[k];
+ if (bond.InCoder < (UInt32)numEmptyMethods ||
+ bond.OutCoder < (UInt32)numEmptyMethods)
+ return E_INVALIDARG;
+ }
+ for (k = 0; k < _bonds.Size(); k++)
+ {
+ CBond2 &bond = _bonds[k];
+ bond.InCoder -= (UInt32)numEmptyMethods;
+ bond.OutCoder -= (UInt32)numEmptyMethods;
+ }
+ _methods.DeleteFrontal(numEmptyMethods);
+ }
+
+ FOR_VECTOR (k, _bonds)
+ {
+ const CBond2 &bond = _bonds[k];
+ if (bond.InCoder >= (UInt32)_methods.Size() ||
+ bond.OutCoder >= (UInt32)_methods.Size())
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.cpp
new file mode 100644
index 0000000000..de3990961b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.cpp
@@ -0,0 +1,19 @@
+// 7zHeader.cpp
+
+#include "StdAfx.h"
+
+#include "7zHeader.h"
+
+namespace NArchive {
+namespace N7z {
+
+Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
+#ifdef _7Z_VOL
+Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
+#endif
+
+// We can change signature. So file doesn't contain correct signature.
+// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } };
+// static SignatureInitializer g_SignatureInitializer;
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.h
new file mode 100644
index 0000000000..7de6eee85d
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.h
@@ -0,0 +1,148 @@
+// 7z/7zHeader.h
+
+#ifndef __7Z_HEADER_H
+#define __7Z_HEADER_H
+
+#include "../../../Common/MyTypes.h"
+
+namespace NArchive {
+namespace N7z {
+
+const unsigned kSignatureSize = 6;
+extern Byte kSignature[kSignatureSize];
+
+// #define _7Z_VOL
+// 7z-MultiVolume is not finished yet.
+// It can work already, but I still do not like some
+// things of that new multivolume format.
+// So please keep it commented.
+
+#ifdef _7Z_VOL
+extern Byte kFinishSignature[kSignatureSize];
+#endif
+
+struct CArchiveVersion
+{
+ Byte Major;
+ Byte Minor;
+};
+
+const Byte kMajorVersion = 0;
+
+struct CStartHeader
+{
+ UInt64 NextHeaderOffset;
+ UInt64 NextHeaderSize;
+ UInt32 NextHeaderCRC;
+};
+
+const UInt32 kStartHeaderSize = 20;
+
+#ifdef _7Z_VOL
+struct CFinishHeader: public CStartHeader
+{
+ UInt64 ArchiveStartOffset; // data offset from end if that struct
+ UInt64 AdditionalStartBlockSize; // start signature & start header size
+};
+
+const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;
+#endif
+
+namespace NID
+{
+ enum EEnum
+ {
+ kEnd,
+
+ kHeader,
+
+ kArchiveProperties,
+
+ kAdditionalStreamsInfo,
+ kMainStreamsInfo,
+ kFilesInfo,
+
+ kPackInfo,
+ kUnpackInfo,
+ kSubStreamsInfo,
+
+ kSize,
+ kCRC,
+
+ kFolder,
+
+ kCodersUnpackSize,
+ kNumUnpackStream,
+
+ kEmptyStream,
+ kEmptyFile,
+ kAnti,
+
+ kName,
+ kCTime,
+ kATime,
+ kMTime,
+ kWinAttrib,
+ kComment,
+
+ kEncodedHeader,
+
+ kStartPos,
+ kDummy
+
+ // kNtSecure,
+ // kParent,
+ // kIsAux
+ };
+}
+
+
+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/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.cpp
new file mode 100644
index 0000000000..bbc77b0351
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.cpp
@@ -0,0 +1,1663 @@
+// 7zIn.cpp
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#include <wchar.h>
+#else
+#include <ctype.h>
+#endif
+
+#include "../../../../C/7zCrc.h"
+#include "../../../../C/CpuArch.h"
+
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+
+#include "7zDecode.h"
+#include "7zIn.h"
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
+// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader
+#ifndef _SFX
+#define FORMAT_7Z_RECOVERY
+#endif
+
+using namespace NWindows;
+using namespace NCOM;
+
+namespace NArchive {
+namespace N7z {
+
+unsigned BoolVector_CountSum(const CBoolVector &v)
+{
+ unsigned sum = 0;
+ const unsigned size = v.Size();
+ for (unsigned i = 0; i < size; i++)
+ if (v[i])
+ sum++;
+ return sum;
+}
+
+static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)
+{
+ return (i < v.Size() ? v[i] : false);
+}
+
+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 CInArchiveException {};
+class CUnsupportedFeatureException: public CInArchiveException {};
+
+static void ThrowException() { throw CInArchiveException(); }
+static inline void ThrowEndOfData() { ThrowException(); }
+static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); }
+static inline void ThrowIncorrect() { ThrowException(); }
+
+class CStreamSwitch
+{
+ CInArchive *_archive;
+ bool _needRemove;
+ bool _needUpdatePos;
+public:
+ CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {}
+ ~CStreamSwitch() { Remove(); }
+ void Remove();
+ void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos);
+ void Set(CInArchive *archive, const CByteBuffer &byteBuffer);
+ void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);
+};
+
+void CStreamSwitch::Remove()
+{
+ if (_needRemove)
+ {
+ if (_archive->_inByteBack->GetRem() != 0)
+ _archive->ThereIsHeaderError = true;
+ _archive->DeleteByteStream(_needUpdatePos);
+ _needRemove = false;
+ }
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos)
+{
+ Remove();
+ _archive = archive;
+ _archive->AddByteStream(data, size);
+ _needRemove = true;
+ _needUpdatePos = needUpdatePos;
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)
+{
+ Set(archive, byteBuffer, byteBuffer.Size(), false);
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)
+{
+ Remove();
+ Byte external = archive->ReadByte();
+ if (external != 0)
+ {
+ if (!dataVector)
+ ThrowIncorrect();
+ CNum dataIndex = archive->ReadNum();
+ if (dataIndex >= dataVector->Size())
+ ThrowIncorrect();
+ Set(archive, (*dataVector)[dataIndex]);
+ }
+}
+
+void CInArchive::AddByteStream(const Byte *buf, size_t size)
+{
+ if (_numInByteBufs == kNumBufLevelsMax)
+ ThrowIncorrect();
+ _inByteBack = &_inByteVector[_numInByteBufs++];
+ _inByteBack->Init(buf, size);
+}
+
+
+Byte CInByte2::ReadByte()
+{
+ if (_pos >= _size)
+ ThrowEndOfData();
+ return _buffer[_pos++];
+}
+
+void CInByte2::ReadBytes(Byte *data, size_t size)
+{
+ if (size == 0)
+ return;
+ if (size > _size - _pos)
+ ThrowEndOfData();
+ memcpy(data, _buffer + _pos, size);
+ _pos += size;
+}
+
+void CInByte2::SkipData(UInt64 size)
+{
+ if (size > _size - _pos)
+ ThrowEndOfData();
+ _pos += (size_t)size;
+}
+
+void CInByte2::SkipData()
+{
+ SkipData(ReadNumber());
+}
+
+static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)
+{
+ if (size == 0)
+ {
+ processed = 0;
+ return 0;
+ }
+
+ unsigned b = *p++;
+ size--;
+
+ if ((b & 0x80) == 0)
+ {
+ processed = 1;
+ return b;
+ }
+
+ if (size == 0)
+ {
+ processed = 0;
+ return 0;
+ }
+
+ UInt64 value = (UInt64)*p;
+ p++;
+ size--;
+
+ for (unsigned i = 1; i < 8; i++)
+ {
+ unsigned mask = (unsigned)0x80 >> i;
+ if ((b & mask) == 0)
+ {
+ 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--;
+ }
+
+ processed = 9;
+ return value;
+}
+
+UInt64 CInByte2::ReadNumber()
+{
+ size_t processed;
+ UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed);
+ if (processed == 0)
+ ThrowEndOfData();
+ _pos += processed;
+ return res;
+}
+
+CNum CInByte2::ReadNum()
+{
+ /*
+ if (_pos < _size)
+ {
+ Byte val = _buffer[_pos];
+ if ((unsigned)val < 0x80)
+ {
+ _pos++;
+ return (unsigned)val;
+ }
+ }
+ */
+ UInt64 value = ReadNumber();
+ if (value > kNumMax)
+ ThrowUnsupported();
+ return (CNum)value;
+}
+
+UInt32 CInByte2::ReadUInt32()
+{
+ if (_pos + 4 > _size)
+ ThrowEndOfData();
+ UInt32 res = Get32(_buffer + _pos);
+ _pos += 4;
+ return res;
+}
+
+UInt64 CInByte2::ReadUInt64()
+{
+ if (_pos + 8 > _size)
+ ThrowEndOfData();
+ UInt64 res = Get64(_buffer + _pos);
+ _pos += 8;
+ return res;
+}
+
+#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false;
+
+static inline bool TestSignature(const Byte *p)
+{
+ CHECK_SIGNATURE
+ return CrcCalc(p + 12, 20) == Get32(p + 8);
+}
+
+#ifdef FORMAT_7Z_RECOVERY
+static inline bool TestSignature2(const Byte *p)
+{
+ CHECK_SIGNATURE;
+ if (CrcCalc(p + 12, 20) == Get32(p + 8))
+ return true;
+ for (unsigned i = 8; i < kHeaderSize; i++)
+ if (p[i] != 0)
+ return false;
+ return (p[6] != 0 || p[7] != 0);
+}
+#else
+#define TestSignature2(p) TestSignature(p)
+#endif
+
+HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+ RINOK(ReadStream_FALSE(stream, _header, kHeaderSize));
+
+ if (TestSignature2(_header))
+ return S_OK;
+ if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
+ return S_FALSE;
+
+ const UInt32 kBufSize = 1 << 15;
+ CByteArr buf(kBufSize);
+ memcpy(buf, _header, kHeaderSize);
+ UInt64 offset = 0;
+
+ for (;;)
+ {
+ UInt32 readSize = kBufSize - kHeaderSize;
+ if (searchHeaderSizeLimit)
+ {
+ UInt64 rem = *searchHeaderSizeLimit - offset;
+ if (readSize > rem)
+ readSize = (UInt32)rem;
+ 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;
+ const Byte *lim = buf + processed;
+ for (; p <= lim; p += 4)
+ {
+ if (p[0] == '7') break;
+ if (p[1] == '7') { p += 1; break; }
+ if (p[2] == '7') { p += 2; break; }
+ if (p[3] == '7') { p += 3; break; }
+ };
+ if (p > lim)
+ break;
+ pos = (UInt32)(p - buf);
+ if (TestSignature(p))
+ {
+ memcpy(_header, p, kHeaderSize);
+ _arhiveBeginStreamPosition += offset + pos;
+ return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
+ }
+ }
+
+ offset += processed;
+ memmove(buf, buf + processed, kHeaderSize);
+ }
+}
+
+// S_FALSE means that file is not archive
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+ HeadersSize = 0;
+ Close();
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition))
+ RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL))
+ RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
+ _stream = stream;
+ return S_OK;
+}
+
+void CInArchive::Close()
+{
+ _numInByteBufs = 0;
+ _stream.Release();
+ ThereIsHeaderError = false;
+}
+
+void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
+{
+ for (;;)
+ {
+ if (ReadID() == NID::kEnd)
+ break;
+ SkipData();
+ }
+}
+
+// CFolder &folder can be non empty. So we must set all fields
+
+void CInByte2::ParseFolder(CFolder &folder)
+{
+ UInt32 numCoders = ReadNum();
+
+ if (numCoders == 0)
+ ThrowUnsupported();
+
+ folder.Coders.SetSize(numCoders);
+
+ UInt32 numInStreams = 0;
+ UInt32 i;
+ for (i = 0; i < numCoders; i++)
+ {
+ CCoderInfo &coder = folder.Coders[i];
+ {
+ Byte mainByte = ReadByte();
+ if ((mainByte & 0xC0) != 0)
+ ThrowUnsupported();
+ unsigned idSize = (mainByte & 0xF);
+ if (idSize > 8 || idSize > GetRem())
+ ThrowUnsupported();
+ const Byte *longID = GetPtr();
+ UInt64 id = 0;
+ for (unsigned j = 0; j < idSize; j++)
+ id = ((id << 8) | longID[j]);
+ SkipDataNoCheck(idSize);
+ coder.MethodID = id;
+
+ if ((mainByte & 0x10) != 0)
+ {
+ coder.NumStreams = ReadNum();
+ /* numOutStreams = */ ReadNum();
+ }
+ else
+ {
+ coder.NumStreams = 1;
+ }
+
+ if ((mainByte & 0x20) != 0)
+ {
+ CNum propsSize = ReadNum();
+ coder.Props.Alloc((size_t)propsSize);
+ ReadBytes((Byte *)coder.Props, (size_t)propsSize);
+ }
+ else
+ coder.Props.Free();
+ }
+ numInStreams += coder.NumStreams;
+ }
+
+ UInt32 numBonds = numCoders - 1;
+ folder.Bonds.SetSize(numBonds);
+ for (i = 0; i < numBonds; i++)
+ {
+ CBond &bp = folder.Bonds[i];
+ bp.PackIndex = ReadNum();
+ bp.UnpackIndex = ReadNum();
+ }
+
+ if (numInStreams < numBonds)
+ ThrowUnsupported();
+ UInt32 numPackStreams = numInStreams - numBonds;
+ folder.PackStreams.SetSize(numPackStreams);
+
+ if (numPackStreams == 1)
+ {
+ for (i = 0; i < numInStreams; i++)
+ if (folder.FindBond_for_PackStream(i) < 0)
+ {
+ folder.PackStreams[0] = i;
+ break;
+ }
+ if (i == numInStreams)
+ ThrowUnsupported();
+ }
+ else
+ for (i = 0; i < numPackStreams; i++)
+ folder.PackStreams[i] = ReadNum();
+}
+
+void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const
+{
+ size_t startPos = FoCodersDataOffset[folderIndex];
+ CInByte2 inByte;
+ inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);
+ inByte.ParseFolder(folder);
+ if (inByte.GetRem() != 0)
+ throw 20120424;
+}
+
+
+void CDatabase::GetPath(unsigned index, UString &path) const
+{
+ path.Empty();
+ if (!NameOffsets || !NamesBuf)
+ return;
+
+ size_t offset = NameOffsets[index];
+ size_t size = NameOffsets[index + 1] - offset;
+
+ if (size >= (1 << 28))
+ return;
+
+ wchar_t *s = path.GetBuf((unsigned)size - 1);
+
+ const Byte *p = ((const Byte *)NamesBuf + offset * 2);
+
+ #if defined(_WIN32) && defined(MY_CPU_LE)
+
+ wmemcpy(s, (const wchar_t *)p, size);
+
+ #else
+
+ for (size_t i = 0; i < size; i++)
+ {
+ *s = Get16(p);
+ p += 2;
+ s++;
+ }
+
+ #endif
+
+ path.ReleaseBuf_SetLen((unsigned)size - 1);
+}
+
+HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
+{
+ PropVariant_Clear(path);
+ if (!NameOffsets || !NamesBuf)
+ return S_OK;
+
+ size_t offset = NameOffsets[index];
+ size_t size = NameOffsets[index + 1] - offset;
+
+ if (size >= (1 << 14))
+ return S_OK;
+
+ RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1));
+ wchar_t *s = path->bstrVal;
+
+ const Byte *p = ((const Byte *)NamesBuf + offset * 2);
+
+ for (size_t i = 0; i < size; i++)
+ {
+ wchar_t c = Get16(p);
+ p += 2;
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ if (c == L'/')
+ c = WCHAR_PATH_SEPARATOR;
+ #endif
+ *s++ = c;
+ }
+
+ return S_OK;
+
+ /*
+ unsigned cur = index;
+ unsigned size = 0;
+
+ for (int i = 0;; i++)
+ {
+ size_t len = NameOffsets[cur + 1] - NameOffsets[cur];
+ size += (unsigned)len;
+ if (i > 256 || len > (1 << 14) || size > (1 << 14))
+ return PropVarEm_Set_Str(path, "[TOO-LONG]");
+ cur = Files[cur].Parent;
+ if (cur < 0)
+ break;
+ }
+ size--;
+
+ RINOK(PropVarEm_Alloc_Bstr(path, size));
+ wchar_t *s = path->bstrVal;
+ s += size;
+ *s = 0;
+ cur = index;
+
+ for (;;)
+ {
+ unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);
+ const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;
+ for (; len != 0; len--)
+ {
+ p -= 2;
+ --s;
+ wchar_t c = Get16(p);
+ if (c == '/')
+ c = WCHAR_PATH_SEPARATOR;
+ *s = c;
+ }
+
+ const CFileItem &file = Files[cur];
+ cur = file.Parent;
+ if (cur < 0)
+ return S_OK;
+ *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR);
+ }
+ */
+}
+
+void CInArchive::WaitId(UInt64 id)
+{
+ for (;;)
+ {
+ UInt64 type = ReadID();
+ if (type == id)
+ return;
+ if (type == NID::kEnd)
+ ThrowIncorrect();
+ SkipData();
+ }
+}
+
+
+void CInArchive::Read_UInt32_Vector(CUInt32DefVector &v)
+{
+ unsigned numItems = v.Defs.Size();
+ v.Vals.ClearAndSetSize(numItems);
+ UInt32 *p = &v.Vals[0];
+ const bool *defs = &v.Defs[0];
+ for (unsigned i = 0; i < numItems; i++)
+ {
+ UInt32 a = 0;
+ if (defs[i])
+ a = ReadUInt32();
+ p[i] = a;
+ }
+}
+
+
+void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
+{
+ ReadBoolVector2(numItems, crcs.Defs);
+ Read_UInt32_Vector(crcs);
+}
+
+
+#define k_Scan_NumCoders_MAX 64
+#define k_Scan_NumCodersStreams_in_Folder_MAX 64
+
+void CInArchive::ReadPackInfo(CFolders &f)
+{
+ CNum numPackStreams = ReadNum();
+
+ WaitId(NID::kSize);
+ f.PackPositions.Alloc(numPackStreams + 1);
+ f.NumPackStreams = numPackStreams;
+ UInt64 sum = 0;
+ for (CNum i = 0; i < numPackStreams; i++)
+ {
+ f.PackPositions[i] = sum;
+ UInt64 packSize = ReadNumber();
+ sum += packSize;
+ if (sum < packSize)
+ ThrowIncorrect();
+ }
+ f.PackPositions[numPackStreams] = sum;
+
+ UInt64 type;
+ for (;;)
+ {
+ type = ReadID();
+ if (type == NID::kEnd)
+ return;
+ if (type == NID::kCRC)
+ {
+ CUInt32DefVector PackCRCs;
+ ReadHashDigests(numPackStreams, PackCRCs);
+ continue;
+ }
+ SkipData();
+ }
+}
+
+void CInArchive::ReadUnpackInfo(
+ const CObjectVector<CByteBuffer> *dataVector,
+ CFolders &folders)
+{
+ WaitId(NID::kFolder);
+ CNum numFolders = ReadNum();
+
+ CNum numCodersOutStreams = 0;
+ {
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, dataVector);
+ const Byte *startBufPtr = _inByteBack->GetPtr();
+ folders.NumFolders = numFolders;
+
+ folders.FoStartPackStreamIndex.Alloc(numFolders + 1);
+ folders.FoToMainUnpackSizeIndex.Alloc(numFolders);
+ folders.FoCodersDataOffset.Alloc(numFolders + 1);
+ folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);
+
+ CBoolVector StreamUsed;
+ CBoolVector CoderUsed;
+
+ CNum packStreamIndex = 0;
+ CNum fo;
+ CInByte2 *inByte = _inByteBack;
+
+ for (fo = 0; fo < numFolders; fo++)
+ {
+ UInt32 indexOfMainStream = 0;
+ UInt32 numPackStreams = 0;
+ folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
+
+ 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();
+ if (idSize > inByte->GetRem())
+ ThrowEndOfData();
+ const Byte *longID = inByte->GetPtr();
+ UInt64 id = 0;
+ for (unsigned j = 0; j < idSize; j++)
+ id = ((id << 8) | longID[j]);
+ inByte->SkipDataNoCheck(idSize);
+ if (folders.ParsedMethods.IDs.Size() < 128)
+ folders.ParsedMethods.IDs.AddToUniqueSorted(id);
+
+ CNum coderInStreams = 1;
+ if ((mainByte & 0x10) != 0)
+ {
+ coderInStreams = inByte->ReadNum();
+ if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
+ ThrowUnsupported();
+ if (inByte->ReadNum() != 1)
+ ThrowUnsupported();
+ }
+
+ numInStreams += coderInStreams;
+ if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
+ ThrowUnsupported();
+
+ if ((mainByte & 0x20) != 0)
+ {
+ CNum propsSize = inByte->ReadNum();
+ if (propsSize > inByte->GetRem())
+ ThrowEndOfData();
+ if (id == k_LZMA2 && propsSize == 1)
+ {
+ Byte v = *_inByteBack->GetPtr();
+ if (folders.ParsedMethods.Lzma2Prop < v)
+ folders.ParsedMethods.Lzma2Prop = v;
+ }
+ else if (id == k_LZMA && propsSize == 5)
+ {
+ UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1);
+ if (folders.ParsedMethods.LzmaDic < dicSize)
+ folders.ParsedMethods.LzmaDic = dicSize;
+ }
+ inByte->SkipDataNoCheck((size_t)propsSize);
+ }
+ }
+
+ if (numCoders == 1 && numInStreams == 1)
+ {
+ indexOfMainStream = 0;
+ numPackStreams = 1;
+ }
+ else
+ {
+ UInt32 i;
+ CNum numBonds = numCoders - 1;
+ if (numInStreams < numBonds)
+ ThrowUnsupported();
+
+ BoolVector_Fill_False(StreamUsed, numInStreams);
+ BoolVector_Fill_False(CoderUsed, numCoders);
+
+ for (i = 0; i < numBonds; i++)
+ {
+ CNum index = ReadNum();
+ if (index >= numInStreams || StreamUsed[index])
+ ThrowUnsupported();
+ StreamUsed[index] = true;
+
+ index = ReadNum();
+ if (index >= numCoders || CoderUsed[index])
+ ThrowUnsupported();
+ CoderUsed[index] = true;
+ }
+
+ numPackStreams = numInStreams - numBonds;
+
+ if (numPackStreams != 1)
+ for (i = 0; i < numPackStreams; i++)
+ {
+ CNum index = inByte->ReadNum(); // PackStreams
+ if (index >= numInStreams || StreamUsed[index])
+ ThrowUnsupported();
+ StreamUsed[index] = true;
+ }
+
+ for (i = 0; i < numCoders; i++)
+ if (!CoderUsed[i])
+ {
+ indexOfMainStream = i;
+ break;
+ }
+
+ if (i == numCoders)
+ ThrowUnsupported();
+ }
+
+ folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
+ numCodersOutStreams += numCoders;
+ folders.FoStartPackStreamIndex[fo] = packStreamIndex;
+ if (numPackStreams > folders.NumPackStreams - packStreamIndex)
+ ThrowIncorrect();
+ packStreamIndex += numPackStreams;
+ folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
+ }
+
+ size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
+ folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
+ folders.FoStartPackStreamIndex[fo] = packStreamIndex;
+ folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
+ folders.CodersData.CopyFrom(startBufPtr, dataSize);
+
+ // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();
+ }
+
+ WaitId(NID::kCodersUnpackSize);
+ folders.CoderUnpackSizes.Alloc(numCodersOutStreams);
+ for (CNum i = 0; i < numCodersOutStreams; i++)
+ folders.CoderUnpackSizes[i] = ReadNumber();
+
+ for (;;)
+ {
+ UInt64 type = ReadID();
+ if (type == NID::kEnd)
+ return;
+ if (type == NID::kCRC)
+ {
+ ReadHashDigests(numFolders, folders.FolderCRCs);
+ continue;
+ }
+ SkipData();
+ }
+}
+
+void CInArchive::ReadSubStreamsInfo(
+ CFolders &folders,
+ CRecordVector<UInt64> &unpackSizes,
+ CUInt32DefVector &digests)
+{
+ folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);
+ CNum i;
+ for (i = 0; i < folders.NumFolders; i++)
+ folders.NumUnpackStreamsVector[i] = 1;
+
+ UInt64 type;
+
+ for (;;)
+ {
+ type = ReadID();
+ if (type == NID::kNumUnpackStream)
+ {
+ for (i = 0; i < folders.NumFolders; i++)
+ folders.NumUnpackStreamsVector[i] = ReadNum();
+ continue;
+ }
+ if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd)
+ break;
+ SkipData();
+ }
+
+ if (type == NID::kSize)
+ {
+ for (i = 0; i < folders.NumFolders; i++)
+ {
+ // v3.13 incorrectly worked with empty folders
+ // v4.07: we check that folder is empty
+ CNum numSubstreams = folders.NumUnpackStreamsVector[i];
+ if (numSubstreams == 0)
+ continue;
+ UInt64 sum = 0;
+ for (CNum j = 1; j < numSubstreams; j++)
+ {
+ UInt64 size = ReadNumber();
+ unpackSizes.Add(size);
+ sum += size;
+ if (sum < size)
+ ThrowIncorrect();
+ }
+ UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i);
+ if (folderUnpackSize < sum)
+ ThrowIncorrect();
+ unpackSizes.Add(folderUnpackSize - sum);
+ }
+ type = ReadID();
+ }
+ else
+ {
+ for (i = 0; i < folders.NumFolders; i++)
+ {
+ /* v9.26 - v9.29 incorrectly worked:
+ if (folders.NumUnpackStreamsVector[i] == 0), it threw error */
+ CNum val = folders.NumUnpackStreamsVector[i];
+ if (val > 1)
+ ThrowIncorrect();
+ if (val == 1)
+ unpackSizes.Add(folders.GetFolderUnpackSize(i));
+ }
+ }
+
+ unsigned numDigests = 0;
+ for (i = 0; i < folders.NumFolders; i++)
+ {
+ CNum numSubstreams = folders.NumUnpackStreamsVector[i];
+ if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i))
+ numDigests += numSubstreams;
+ }
+
+ for (;;)
+ {
+ if (type == NID::kEnd)
+ break;
+ if (type == NID::kCRC)
+ {
+ // CUInt32DefVector digests2;
+ // ReadHashDigests(numDigests, digests2);
+ CBoolVector digests2;
+ ReadBoolVector2(numDigests, digests2);
+
+ digests.ClearAndSetSize(unpackSizes.Size());
+
+ unsigned k = 0;
+ unsigned k2 = 0;
+
+ for (i = 0; i < folders.NumFolders; i++)
+ {
+ CNum numSubstreams = folders.NumUnpackStreamsVector[i];
+ if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
+ {
+ digests.Defs[k] = true;
+ digests.Vals[k] = folders.FolderCRCs.Vals[i];
+ k++;
+ }
+ else for (CNum j = 0; j < numSubstreams; j++)
+ {
+ bool defined = digests2[k2++];
+ digests.Defs[k] = defined;
+ UInt32 crc = 0;
+ if (defined)
+ crc = ReadUInt32();
+ digests.Vals[k] = crc;
+ k++;
+ }
+ }
+ // if (k != unpackSizes.Size()) throw 1234567;
+ }
+ else
+ SkipData();
+
+ type = ReadID();
+ }
+
+ if (digests.Defs.Size() != unpackSizes.Size())
+ {
+ digests.ClearAndSetSize(unpackSizes.Size());
+ unsigned k = 0;
+ for (i = 0; i < folders.NumFolders; i++)
+ {
+ CNum numSubstreams = folders.NumUnpackStreamsVector[i];
+ if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))
+ {
+ digests.Defs[k] = true;
+ digests.Vals[k] = folders.FolderCRCs.Vals[i];
+ k++;
+ }
+ else for (CNum j = 0; j < numSubstreams; j++)
+ {
+ digests.Defs[k] = false;
+ digests.Vals[k] = 0;
+ k++;
+ }
+ }
+ }
+}
+
+void CInArchive::ReadStreamsInfo(
+ const CObjectVector<CByteBuffer> *dataVector,
+ UInt64 &dataOffset,
+ CFolders &folders,
+ CRecordVector<UInt64> &unpackSizes,
+ CUInt32DefVector &digests)
+{
+ UInt64 type = ReadID();
+
+ if (type == NID::kPackInfo)
+ {
+ dataOffset = ReadNumber();
+ ReadPackInfo(folders);
+ type = ReadID();
+ }
+
+ if (type == NID::kUnpackInfo)
+ {
+ ReadUnpackInfo(dataVector, folders);
+ type = ReadID();
+ }
+
+ if (folders.NumFolders != 0 && !folders.PackPositions)
+ {
+ // if there are folders, we need PackPositions also
+ folders.PackPositions.Alloc(1);
+ folders.PackPositions[0] = 0;
+ }
+
+ if (type == NID::kSubStreamsInfo)
+ {
+ ReadSubStreamsInfo(folders, unpackSizes, digests);
+ type = ReadID();
+ }
+ else
+ {
+ folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);
+ /* If digests.Defs.Size() == 0, it means that there are no crcs.
+ So we don't need to fill digests with values. */
+ // digests.Vals.ClearAndSetSize(folders.NumFolders);
+ // BoolVector_Fill_False(digests.Defs, folders.NumFolders);
+ for (CNum i = 0; i < folders.NumFolders; i++)
+ {
+ folders.NumUnpackStreamsVector[i] = 1;
+ unpackSizes.Add(folders.GetFolderUnpackSize(i));
+ // digests.Vals[i] = 0;
+ }
+ }
+
+ if (type != NID::kEnd)
+ ThrowIncorrect();
+}
+
+void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v)
+{
+ v.ClearAndSetSize(numItems);
+ Byte b = 0;
+ Byte mask = 0;
+ bool *p = &v[0];
+ for (unsigned i = 0; i < numItems; i++)
+ {
+ if (mask == 0)
+ {
+ b = ReadByte();
+ mask = 0x80;
+ }
+ p[i] = ((b & mask) != 0);
+ mask >>= 1;
+ }
+}
+
+void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v)
+{
+ Byte allAreDefined = ReadByte();
+ if (allAreDefined == 0)
+ {
+ ReadBoolVector(numItems, v);
+ return;
+ }
+ v.ClearAndSetSize(numItems);
+ bool *p = &v[0];
+ for (unsigned i = 0; i < numItems; i++)
+ p[i] = true;
+}
+
+void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
+ CUInt64DefVector &v, unsigned numItems)
+{
+ ReadBoolVector2(numItems, v.Defs);
+
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, &dataVector);
+
+ v.Vals.ClearAndSetSize(numItems);
+ UInt64 *p = &v.Vals[0];
+ const bool *defs = &v.Defs[0];
+
+ for (unsigned i = 0; i < numItems; i++)
+ {
+ UInt64 t = 0;
+ if (defs[i])
+ t = ReadUInt64();
+ p[i] = t;
+ }
+}
+
+HRESULT CInArchive::ReadAndDecodePackedStreams(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ UInt64 baseOffset,
+ UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector
+ _7Z_DECODER_CRYPRO_VARS_DECL
+ )
+{
+ CFolders folders;
+ CRecordVector<UInt64> unpackSizes;
+ CUInt32DefVector digests;
+
+ ReadStreamsInfo(NULL,
+ dataOffset,
+ folders,
+ unpackSizes,
+ digests);
+
+ CDecoder decoder(_useMixerMT);
+
+ for (CNum i = 0; i < folders.NumFolders; i++)
+ {
+ CByteBuffer &data = dataVector.AddNew();
+ UInt64 unpackSize64 = folders.GetFolderUnpackSize(i);
+ size_t unpackSize = (size_t)unpackSize64;
+ if (unpackSize != unpackSize64)
+ ThrowUnsupported();
+ data.Alloc(unpackSize);
+
+ CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+ outStreamSpec->Init(data, unpackSize);
+
+ bool dataAfterEnd_Error = false;
+
+ HRESULT result = decoder.Decode(
+ EXTERNAL_CODECS_LOC_VARS
+ _stream, baseOffset + dataOffset,
+ folders, i,
+ NULL, // *unpackSize
+
+ outStream,
+ NULL, // *compressProgress
+
+ NULL // **inStreamMainRes
+ , dataAfterEnd_Error
+
+ _7Z_DECODER_CRYPRO_VARS
+ #if !defined(_7ZIP_ST)
+ , false // mtMode
+ , 1 // numThreads
+ , 0 // memUsage
+ #endif
+ );
+
+ RINOK(result);
+
+ if (dataAfterEnd_Error)
+ ThereIsHeaderError = true;
+
+ if (folders.FolderCRCs.ValidAndDefined(i))
+ if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
+ ThrowIncorrect();
+ }
+
+ if (folders.PackPositions)
+ HeadersSize += folders.PackPositions[folders.NumPackStreams];
+
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadHeader(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CDbEx &db
+ _7Z_DECODER_CRYPRO_VARS_DECL
+ )
+{
+ UInt64 type = ReadID();
+
+ if (type == NID::kArchiveProperties)
+ {
+ ReadArchiveProperties(db.ArcInfo);
+ type = ReadID();
+ }
+
+ CObjectVector<CByteBuffer> dataVector;
+
+ if (type == NID::kAdditionalStreamsInfo)
+ {
+ HRESULT result = ReadAndDecodePackedStreams(
+ EXTERNAL_CODECS_LOC_VARS
+ db.ArcInfo.StartPositionAfterHeader,
+ db.ArcInfo.DataStartPosition2,
+ dataVector
+ _7Z_DECODER_CRYPRO_VARS
+ );
+ RINOK(result);
+ db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader;
+ type = ReadID();
+ }
+
+ CRecordVector<UInt64> unpackSizes;
+ CUInt32DefVector digests;
+
+ if (type == NID::kMainStreamsInfo)
+ {
+ ReadStreamsInfo(&dataVector,
+ db.ArcInfo.DataStartPosition,
+ (CFolders &)db,
+ unpackSizes,
+ digests);
+ db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader;
+ type = ReadID();
+ }
+
+ if (type == NID::kFilesInfo)
+ {
+
+ const CNum numFiles = ReadNum();
+
+ db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
+ // if (!db.PackSizes.IsEmpty())
+ db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);
+ if (numFiles > 0 && !digests.Defs.IsEmpty())
+ db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
+
+ CBoolVector emptyStreamVector;
+ CBoolVector emptyFileVector;
+ CBoolVector antiFileVector;
+ CNum numEmptyStreams = 0;
+
+ for (;;)
+ {
+ const UInt64 type2 = ReadID();
+ if (type2 == NID::kEnd)
+ break;
+ UInt64 size = ReadNumber();
+ if (size > _inByteBack->GetRem())
+ ThrowIncorrect();
+ CStreamSwitch switchProp;
+ switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);
+ bool addPropIdToList = true;
+ bool isKnownType = true;
+ if (type2 > ((UInt32)1 << 30))
+ isKnownType = false;
+ else switch ((UInt32)type2)
+ {
+ case NID::kName:
+ {
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, &dataVector);
+ size_t rem = _inByteBack->GetRem();
+ db.NamesBuf.Alloc(rem);
+ ReadBytes(db.NamesBuf, rem);
+ db.NameOffsets.Alloc(numFiles + 1);
+ size_t pos = 0;
+ unsigned i;
+ for (i = 0; i < numFiles; i++)
+ {
+ size_t curRem = (rem - pos) / 2;
+ const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos);
+ size_t j;
+ for (j = 0; j < curRem && buf[j] != 0; j++);
+ if (j == curRem)
+ ThrowEndOfData();
+ db.NameOffsets[i] = pos / 2;
+ pos += j * 2 + 2;
+ }
+ db.NameOffsets[i] = pos / 2;
+ if (pos != rem)
+ ThereIsHeaderError = true;
+ break;
+ }
+
+ case NID::kWinAttrib:
+ {
+ ReadBoolVector2(numFiles, db.Attrib.Defs);
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, &dataVector);
+ Read_UInt32_Vector(db.Attrib);
+ break;
+ }
+
+ /*
+ case NID::kIsAux:
+ {
+ ReadBoolVector(numFiles, db.IsAux);
+ break;
+ }
+ case NID::kParent:
+ {
+ db.IsTree = true;
+ // CBoolVector boolVector;
+ // ReadBoolVector2(numFiles, boolVector);
+ // CStreamSwitch streamSwitch;
+ // streamSwitch.Set(this, &dataVector);
+ CBoolVector boolVector;
+ ReadBoolVector2(numFiles, boolVector);
+
+ db.ThereAreAltStreams = false;
+ for (i = 0; i < numFiles; i++)
+ {
+ CFileItem &file = db.Files[i];
+ // file.Parent = -1;
+ // if (boolVector[i])
+ file.Parent = (int)ReadUInt32();
+ file.IsAltStream = !boolVector[i];
+ if (file.IsAltStream)
+ db.ThereAreAltStreams = true;
+ }
+ break;
+ }
+ */
+ case NID::kEmptyStream:
+ {
+ ReadBoolVector(numFiles, emptyStreamVector);
+ numEmptyStreams = BoolVector_CountSum(emptyStreamVector);
+ emptyFileVector.Clear();
+ antiFileVector.Clear();
+ break;
+ }
+ case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break;
+ case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break;
+ case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break;
+ case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break;
+ case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break;
+ case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break;
+ case NID::kDummy:
+ {
+ for (UInt64 j = 0; j < size; j++)
+ if (ReadByte() != 0)
+ ThereIsHeaderError = true;
+ addPropIdToList = false;
+ break;
+ }
+ /*
+ case NID::kNtSecure:
+ {
+ try
+ {
+ {
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, &dataVector);
+ UInt32 numDescriptors = ReadUInt32();
+ size_t offset = 0;
+ db.SecureOffsets.Clear();
+ for (i = 0; i < numDescriptors; i++)
+ {
+ UInt32 size = ReadUInt32();
+ db.SecureOffsets.Add(offset);
+ offset += size;
+ }
+ // ThrowIncorrect();;
+ db.SecureOffsets.Add(offset);
+ db.SecureBuf.SetCapacity(offset);
+ for (i = 0; i < numDescriptors; i++)
+ {
+ offset = db.SecureOffsets[i];
+ ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);
+ }
+ db.SecureIDs.Clear();
+ for (unsigned i = 0; i < numFiles; i++)
+ {
+ db.SecureIDs.Add(ReadNum());
+ // db.SecureIDs.Add(ReadUInt32());
+ }
+ // ReadUInt32();
+ if (_inByteBack->GetRem() != 0)
+ ThrowIncorrect();;
+ }
+ }
+ catch(CInArchiveException &)
+ {
+ ThereIsHeaderError = true;
+ addPropIdToList = isKnownType = false;
+ db.ClearSecure();
+ }
+ break;
+ }
+ */
+ default:
+ addPropIdToList = isKnownType = false;
+ }
+ if (isKnownType)
+ {
+ if (addPropIdToList)
+ db.ArcInfo.FileInfoPopIDs.Add(type2);
+ }
+ else
+ {
+ db.UnsupportedFeatureWarning = true;
+ _inByteBack->SkipRem();
+ }
+ // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02)
+ if (_inByteBack->GetRem() != 0)
+ ThrowIncorrect();
+ }
+
+ type = ReadID(); // Read (NID::kEnd) end of headers
+
+ if (numFiles - numEmptyStreams != unpackSizes.Size())
+ ThrowUnsupported();
+
+ CNum emptyFileIndex = 0;
+ CNum sizeIndex = 0;
+
+ const CNum numAntiItems = BoolVector_CountSum(antiFileVector);
+
+ if (numAntiItems != 0)
+ db.IsAnti.ClearAndSetSize(numFiles);
+
+ db.Files.ClearAndSetSize(numFiles);
+
+ for (CNum i = 0; i < numFiles; i++)
+ {
+ CFileItem &file = db.Files[i];
+ bool isAnti;
+ file.Crc = 0;
+ if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i))
+ {
+ file.HasStream = true;
+ file.IsDir = false;
+ isAnti = false;
+ file.Size = unpackSizes[sizeIndex];
+ file.CrcDefined = digests.ValidAndDefined(sizeIndex);
+ if (file.CrcDefined)
+ file.Crc = digests.Vals[sizeIndex];
+ sizeIndex++;
+ }
+ else
+ {
+ file.HasStream = false;
+ file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex);
+ isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex);
+ emptyFileIndex++;
+ file.Size = 0;
+ file.CrcDefined = false;
+ }
+ if (numAntiItems != 0)
+ db.IsAnti[i] = isAnti;
+ }
+
+ }
+
+ db.FillLinks();
+
+ if (type != NID::kEnd || _inByteBack->GetRem() != 0)
+ {
+ db.UnsupportedFeatureWarning = true;
+ // ThrowIncorrect();
+ }
+
+ return S_OK;
+}
+
+
+void CDbEx::FillLinks()
+{
+ 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;
+ if (indexInFolder == 0)
+ {
+ if (emptyStream)
+ {
+ FileIndexToFolderIndexMap[i] = kNumNoIndex;
+ continue;
+ }
+ // v3.13 incorrectly worked with empty folders
+ // v4.07: we skip empty folders
+ for (;;)
+ {
+ if (folderIndex >= NumFolders)
+ ThrowIncorrect();
+ FolderStartFileIndex[folderIndex] = i;
+ if (NumUnpackStreamsVector[folderIndex] != 0)
+ break;
+ folderIndex++;
+ }
+ }
+ FileIndexToFolderIndexMap[i] = folderIndex;
+ if (emptyStream)
+ continue;
+ if (++indexInFolder >= NumUnpackStreamsVector[folderIndex])
+ {
+ folderIndex++;
+ indexInFolder = 0;
+ }
+ }
+
+ if (indexInFolder != 0)
+ folderIndex++;
+ /*
+ if (indexInFolder != 0)
+ ThrowIncorrect();
+ */
+
+ for (;;)
+ {
+ if (folderIndex >= NumFolders)
+ return;
+ FolderStartFileIndex[folderIndex] = i;
+ /*
+ if (NumUnpackStreamsVector[folderIndex] != 0)
+ ThrowIncorrect();;
+ */
+ folderIndex++;
+ }
+}
+
+
+HRESULT CInArchive::ReadDatabase2(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CDbEx &db
+ _7Z_DECODER_CRYPRO_VARS_DECL
+ )
+{
+ db.Clear();
+ db.ArcInfo.StartPosition = _arhiveBeginStreamPosition;
+
+ db.ArcInfo.Version.Major = _header[6];
+ db.ArcInfo.Version.Minor = _header[7];
+
+ if (db.ArcInfo.Version.Major != kMajorVersion)
+ {
+ // db.UnsupportedVersion = true;
+ return S_FALSE;
+ }
+
+ UInt64 nextHeaderOffset = Get64(_header + 12);
+ UInt64 nextHeaderSize = Get64(_header + 20);
+ UInt32 nextHeaderCRC = Get32(_header + 28);
+
+ #ifdef FORMAT_7Z_RECOVERY
+ UInt32 crcFromArc = Get32(_header + 8);
+ if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
+ {
+ UInt64 cur, fileSize;
+ RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));
+ const unsigned kCheckSize = 512;
+ Byte buf[kCheckSize];
+ RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ UInt64 rem = fileSize - cur;
+ unsigned checkSize = kCheckSize;
+ if (rem < kCheckSize)
+ checkSize = (unsigned)(rem);
+ if (checkSize < 3)
+ return S_FALSE;
+ RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL));
+ RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize));
+
+ if (buf[checkSize - 1] != 0)
+ return S_FALSE;
+
+ unsigned i;
+ for (i = checkSize - 2;; i--)
+ {
+ if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo ||
+ buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo)
+ break;
+ if (i == 0)
+ return S_FALSE;
+ }
+ nextHeaderSize = checkSize - i;
+ nextHeaderOffset = rem - nextHeaderSize;
+ nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
+ RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));
+ db.StartHeaderWasRecovered = true;
+ }
+ else
+ #endif
+ {
+ // Crc was tested already at signature check
+ // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect();
+ }
+
+ db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;
+ db.PhySize = kHeaderSize;
+
+ db.IsArc = false;
+ if ((Int64)nextHeaderOffset < 0 ||
+ nextHeaderSize > ((UInt64)1 << 62))
+ return S_FALSE;
+ if (nextHeaderSize == 0)
+ {
+ if (nextHeaderOffset != 0)
+ return S_FALSE;
+ db.IsArc = true;
+ return S_OK;
+ }
+
+ if (!db.StartHeaderWasRecovered)
+ db.IsArc = true;
+
+ HeadersSize += kHeaderSize + nextHeaderSize;
+ db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;
+ if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize)
+ {
+ db.UnexpectedEnd = true;
+ return S_FALSE;
+ }
+ RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
+
+ size_t nextHeaderSize_t = (size_t)nextHeaderSize;
+ if (nextHeaderSize_t != nextHeaderSize)
+ return E_OUTOFMEMORY;
+ CByteBuffer buffer2(nextHeaderSize_t);
+
+ RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t));
+
+ if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC)
+ ThrowIncorrect();
+
+ if (!db.StartHeaderWasRecovered)
+ db.PhySizeWasConfirmed = true;
+
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, buffer2);
+
+ CObjectVector<CByteBuffer> dataVector;
+
+ UInt64 type = ReadID();
+ if (type != NID::kHeader)
+ {
+ if (type != NID::kEncodedHeader)
+ ThrowIncorrect();
+ HRESULT result = ReadAndDecodePackedStreams(
+ EXTERNAL_CODECS_LOC_VARS
+ db.ArcInfo.StartPositionAfterHeader,
+ db.ArcInfo.DataStartPosition2,
+ dataVector
+ _7Z_DECODER_CRYPRO_VARS
+ );
+ RINOK(result);
+ if (dataVector.Size() == 0)
+ return S_OK;
+ if (dataVector.Size() > 1)
+ ThrowIncorrect();
+ streamSwitch.Remove();
+ streamSwitch.Set(this, dataVector.Front());
+ if (ReadID() != NID::kHeader)
+ ThrowIncorrect();
+ }
+
+ db.IsArc = true;
+
+ db.HeadersSize = HeadersSize;
+
+ return ReadHeader(
+ EXTERNAL_CODECS_LOC_VARS
+ db
+ _7Z_DECODER_CRYPRO_VARS
+ );
+}
+
+
+HRESULT CInArchive::ReadDatabase(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CDbEx &db
+ _7Z_DECODER_CRYPRO_VARS_DECL
+ )
+{
+ try
+ {
+ HRESULT res = ReadDatabase2(
+ EXTERNAL_CODECS_LOC_VARS db
+ _7Z_DECODER_CRYPRO_VARS
+ );
+ if (ThereIsHeaderError)
+ db.ThereIsHeaderError = true;
+ if (res == E_NOTIMPL)
+ ThrowUnsupported();
+ return res;
+ }
+ catch(CUnsupportedFeatureException &)
+ {
+ db.UnsupportedFeatureError = true;
+ return S_FALSE;
+ }
+ catch(CInArchiveException &)
+ {
+ db.ThereIsHeaderError = true;
+ return S_FALSE;
+ }
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.h
new file mode 100644
index 0000000000..c5fb9095f0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.h
@@ -0,0 +1,435 @@
+// 7zIn.h
+
+#ifndef __7Z_IN_H
+#define __7Z_IN_H
+
+#include "../../../Common/MyCom.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../IPassword.h"
+#include "../../IStream.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/InBuffer.h"
+
+#include "7zItem.h"
+
+namespace NArchive {
+namespace N7z {
+
+/*
+ We don't need to init isEncrypted and passwordIsDefined
+ We must upgrade them only */
+
+#ifdef _NO_CRYPTO
+#define _7Z_DECODER_CRYPRO_VARS_DECL
+#define _7Z_DECODER_CRYPRO_VARS
+#else
+#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
+{
+ Byte Lzma2Prop;
+ UInt32 LzmaDic;
+ CRecordVector<UInt64> IDs;
+
+ CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
+};
+
+struct CFolderEx: public CFolder
+{
+ unsigned UnpackCoder;
+};
+
+struct CFolders
+{
+ CNum NumPackStreams;
+ CNum NumFolders;
+
+ CObjArray<UInt64> PackPositions; // NumPackStreams + 1
+ // CUInt32DefVector PackCRCs; // we don't use PackCRCs now
+
+ CUInt32DefVector FolderCRCs; // NumFolders
+ CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
+
+ CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
+ CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
+ CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
+ CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
+
+ CObjArray<size_t> FoCodersDataOffset; // NumFolders + 1
+ CByteBuffer CodersData;
+
+ 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 (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);
+ }
+
+ UInt64 GetFolderUnpackSize(unsigned folderIndex) const
+ {
+ return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];
+ }
+
+ UInt64 GetStreamPackSize(unsigned index) const
+ {
+ return PackPositions[index + 1] - PackPositions[index];
+ }
+
+ CFolders(): NumPackStreams(0), NumFolders(0) {}
+
+ void Clear()
+ {
+ NumPackStreams = 0;
+ PackPositions.Free();
+ // PackCRCs.Clear();
+
+ NumFolders = 0;
+ FolderCRCs.Clear();
+ NumUnpackStreamsVector.Free();
+ CoderUnpackSizes.Free();
+ FoToCoderUnpackSizes.Free();
+ FoStartPackStreamIndex.Free();
+ FoToMainUnpackSizeIndex.Free();
+ FoCodersDataOffset.Free();
+ CodersData.Free();
+ }
+};
+
+struct CDatabase: public CFolders
+{
+ CRecordVector<CFileItem> Files;
+
+ CUInt64DefVector CTime;
+ CUInt64DefVector ATime;
+ CUInt64DefVector MTime;
+ CUInt64DefVector StartPos;
+ CUInt32DefVector Attrib;
+ CBoolVector IsAnti;
+ /*
+ CBoolVector IsAux;
+ CByteBuffer SecureBuf;
+ CRecordVector<UInt32> SecureIDs;
+ */
+
+ CByteBuffer NamesBuf;
+ CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols
+
+ /*
+ void ClearSecure()
+ {
+ SecureBuf.Free();
+ SecureIDs.Clear();
+ }
+ */
+
+ void Clear()
+ {
+ CFolders::Clear();
+ // ClearSecure();
+
+ NamesBuf.Free();
+ NameOffsets.Free();
+
+ Files.Clear();
+ CTime.Clear();
+ ATime.Clear();
+ MTime.Clear();
+ StartPos.Clear();
+ Attrib.Clear();
+ IsAnti.Clear();
+ // IsAux.Clear();
+ }
+
+ bool IsSolid() const
+ {
+ for (CNum i = 0; i < NumFolders; i++)
+ if (NumUnpackStreamsVector[i] > 1)
+ return true;
+ return false;
+ }
+ 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
+ {
+ if (!NameOffsets || !NamesBuf)
+ return NULL;
+ return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);
+ };
+ */
+ void GetPath(unsigned index, UString &path) const;
+ HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
+};
+
+struct CInArchiveInfo
+{
+ CArchiveVersion Version;
+ UInt64 StartPosition;
+ UInt64 StartPositionAfterHeader;
+ UInt64 DataStartPosition;
+ UInt64 DataStartPosition2;
+ CRecordVector<UInt64> FileInfoPopIDs;
+
+ void Clear()
+ {
+ StartPosition = 0;
+ StartPositionAfterHeader = 0;
+ DataStartPosition = 0;
+ DataStartPosition2 = 0;
+ FileInfoPopIDs.Clear();
+ }
+};
+
+struct CDbEx: public CDatabase
+{
+ CInArchiveInfo ArcInfo;
+
+ CObjArray<CNum> FolderStartFileIndex;
+ CObjArray<CNum> FileIndexToFolderIndexMap;
+
+ UInt64 HeadersSize;
+ UInt64 PhySize;
+
+ /*
+ CRecordVector<size_t> SecureOffsets;
+ bool IsTree;
+ bool ThereAreAltStreams;
+ */
+
+ bool IsArc;
+ bool PhySizeWasConfirmed;
+
+ bool ThereIsHeaderError;
+ bool UnexpectedEnd;
+ // bool UnsupportedVersion;
+
+ bool StartHeaderWasRecovered;
+ bool UnsupportedFeatureWarning;
+ bool UnsupportedFeatureError;
+
+ /*
+ void ClearSecureEx()
+ {
+ ClearSecure();
+ SecureOffsets.Clear();
+ }
+ */
+
+ void Clear()
+ {
+ IsArc = false;
+ PhySizeWasConfirmed = false;
+
+ ThereIsHeaderError = false;
+ UnexpectedEnd = false;
+ // UnsupportedVersion = false;
+
+ StartHeaderWasRecovered = false;
+ UnsupportedFeatureError = false;
+ UnsupportedFeatureWarning = false;
+
+ /*
+ IsTree = false;
+ ThereAreAltStreams = false;
+ */
+
+ CDatabase::Clear();
+
+ // SecureOffsets.Clear();
+ ArcInfo.Clear();
+ FolderStartFileIndex.Free();
+ FileIndexToFolderIndexMap.Free();
+
+ HeadersSize = 0;
+ PhySize = 0;
+ }
+
+ void FillLinks();
+
+ UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const
+ {
+ return ArcInfo.DataStartPosition +
+ PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
+ }
+
+ UInt64 GetFolderFullPackSize(CNum folderIndex) const
+ {
+ return
+ PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
+ PackPositions[FoStartPackStreamIndex[folderIndex]];
+ }
+
+ UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const
+ {
+ size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex;
+ return PackPositions[i + 1] - PackPositions[i];
+ }
+
+ UInt64 GetFilePackSize(CNum fileIndex) const
+ {
+ CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex != kNumNoIndex)
+ if (FolderStartFileIndex[folderIndex] == fileIndex)
+ return GetFolderFullPackSize(folderIndex);
+ return 0;
+ }
+};
+
+const unsigned kNumBufLevelsMax = 4;
+
+struct CInByte2
+{
+ const Byte *_buffer;
+public:
+ size_t _size;
+ size_t _pos;
+
+ size_t GetRem() const { return _size - _pos; }
+ const Byte *GetPtr() const { return _buffer + _pos; }
+ void Init(const Byte *buffer, size_t size)
+ {
+ _buffer = buffer;
+ _size = size;
+ _pos = 0;
+ }
+ Byte ReadByte();
+ void ReadBytes(Byte *data, size_t size);
+ void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
+ void SkipData(UInt64 size);
+
+ void SkipData();
+ void SkipRem() { _pos = _size; }
+ UInt64 ReadNumber();
+ CNum ReadNum();
+ UInt32 ReadUInt32();
+ UInt64 ReadUInt64();
+
+ void ParseFolder(CFolder &folder);
+};
+
+class CStreamSwitch;
+
+const UInt32 kHeaderSize = 32;
+
+class CInArchive
+{
+ friend class CStreamSwitch;
+
+ CMyComPtr<IInStream> _stream;
+
+ unsigned _numInByteBufs;
+ CInByte2 _inByteVector[kNumBufLevelsMax];
+
+ CInByte2 *_inByteBack;
+ bool ThereIsHeaderError;
+
+ UInt64 _arhiveBeginStreamPosition;
+ UInt64 _fileEndPosition;
+
+ Byte _header[kHeaderSize];
+
+ UInt64 HeadersSize;
+
+ bool _useMixerMT;
+
+ void AddByteStream(const Byte *buffer, size_t size);
+
+ void DeleteByteStream(bool needUpdatePos)
+ {
+ _numInByteBufs--;
+ if (_numInByteBufs > 0)
+ {
+ _inByteBack = &_inByteVector[_numInByteBufs - 1];
+ if (needUpdatePos)
+ _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;
+ }
+ }
+
+ HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
+
+ void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
+ Byte ReadByte() { return _inByteBack->ReadByte(); }
+ UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
+ CNum ReadNum() { return _inByteBack->ReadNum(); }
+ UInt64 ReadID() { return _inByteBack->ReadNumber(); }
+ UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
+ UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
+ void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
+ void SkipData() { _inByteBack->SkipData(); }
+ void WaitId(UInt64 id);
+
+ void Read_UInt32_Vector(CUInt32DefVector &v);
+
+ void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
+ void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
+
+ void ReadPackInfo(CFolders &f);
+
+ void ReadUnpackInfo(
+ const CObjectVector<CByteBuffer> *dataVector,
+ CFolders &folders);
+
+ void ReadSubStreamsInfo(
+ CFolders &folders,
+ CRecordVector<UInt64> &unpackSizes,
+ CUInt32DefVector &digests);
+
+ void ReadStreamsInfo(
+ const CObjectVector<CByteBuffer> *dataVector,
+ UInt64 &dataOffset,
+ CFolders &folders,
+ CRecordVector<UInt64> &unpackSizes,
+ CUInt32DefVector &digests);
+
+ void ReadBoolVector(unsigned numItems, CBoolVector &v);
+ void ReadBoolVector2(unsigned numItems, CBoolVector &v);
+ void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
+ CUInt64DefVector &v, unsigned numItems);
+ HRESULT ReadAndDecodePackedStreams(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ UInt64 baseOffset, UInt64 &dataOffset,
+ CObjectVector<CByteBuffer> &dataVector
+ _7Z_DECODER_CRYPRO_VARS_DECL
+ );
+ HRESULT ReadHeader(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CDbEx &db
+ _7Z_DECODER_CRYPRO_VARS_DECL
+ );
+ HRESULT ReadDatabase2(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CDbEx &db
+ _7Z_DECODER_CRYPRO_VARS_DECL
+ );
+public:
+ CInArchive(bool useMixerMT):
+ _numInByteBufs(0),
+ _useMixerMT(useMixerMT)
+ {}
+
+ HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
+ void Close();
+
+ HRESULT ReadDatabase(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CDbEx &db
+ _7Z_DECODER_CRYPRO_VARS_DECL
+ );
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zItem.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zItem.h
new file mode 100644
index 0000000000..90cf98c532
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zItem.h
@@ -0,0 +1,202 @@
+// 7zItem.h
+
+#ifndef __7Z_ITEM_H
+#define __7Z_ITEM_H
+
+#include "../../../Common/MyBuffer.h"
+#include "../../../Common/MyString.h"
+
+#include "../../Common/MethodId.h"
+
+#include "7zHeader.h"
+
+namespace NArchive {
+namespace N7z {
+
+typedef UInt32 CNum;
+const CNum kNumMax = 0x7FFFFFFF;
+const CNum kNumNoIndex = 0xFFFFFFFF;
+
+struct CCoderInfo
+{
+ CMethodId MethodID;
+ CByteBuffer Props;
+ UInt32 NumStreams;
+
+ bool IsSimpleCoder() const { return NumStreams == 1; }
+};
+
+
+struct CBond
+{
+ UInt32 PackIndex;
+ UInt32 UnpackIndex;
+};
+
+
+struct CFolder
+{
+ CLASS_NO_COPY(CFolder)
+public:
+ CObjArray2<CCoderInfo> Coders;
+ CObjArray2<CBond> Bonds;
+ CObjArray2<UInt32> PackStreams;
+
+ CFolder() {}
+
+ bool IsDecodingSupported() const { return Coders.Size() <= 32; }
+
+ int Find_in_PackStreams(UInt32 packStream) const
+ {
+ FOR_VECTOR(i, PackStreams)
+ if (PackStreams[i] == packStream)
+ return i;
+ return -1;
+ }
+
+ int FindBond_for_PackStream(UInt32 packStream) const
+ {
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].PackIndex == packStream)
+ return i;
+ return -1;
+ }
+
+ /*
+ int FindBond_for_UnpackStream(UInt32 unpackStream) const
+ {
+ FOR_VECTOR(i, Bonds)
+ if (Bonds[i].UnpackIndex == unpackStream)
+ return i;
+ return -1;
+ }
+
+ int FindOutCoder() const
+ {
+ for (int i = (int)Coders.Size() - 1; i >= 0; i--)
+ if (FindBond_for_UnpackStream(i) < 0)
+ return i;
+ return -1;
+ }
+ */
+
+ bool IsEncrypted() const
+ {
+ FOR_VECTOR(i, Coders)
+ if (Coders[i].MethodID == k_AES)
+ return true;
+ return false;
+ }
+};
+
+
+struct CUInt32DefVector
+{
+ CBoolVector Defs;
+ CRecordVector<UInt32> Vals;
+
+ void ClearAndSetSize(unsigned newSize)
+ {
+ Defs.ClearAndSetSize(newSize);
+ Vals.ClearAndSetSize(newSize);
+ }
+
+ void Clear()
+ {
+ Defs.Clear();
+ Vals.Clear();
+ }
+
+ void ReserveDown()
+ {
+ Defs.ReserveDown();
+ Vals.ReserveDown();
+ }
+
+ bool GetItem(unsigned index, UInt32 &value) const
+ {
+ if (index < Defs.Size() && Defs[index])
+ {
+ value = Vals[index];
+ return true;
+ }
+ value = 0;
+ return false;
+ }
+
+ bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }
+
+ bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
+
+ void SetItem(unsigned index, bool defined, UInt32 value);
+};
+
+
+struct CUInt64DefVector
+{
+ CBoolVector Defs;
+ CRecordVector<UInt64> Vals;
+
+ void Clear()
+ {
+ Defs.Clear();
+ Vals.Clear();
+ }
+
+ void ReserveDown()
+ {
+ Defs.ReserveDown();
+ Vals.ReserveDown();
+ }
+
+ bool GetItem(unsigned index, UInt64 &value) const
+ {
+ if (index < Defs.Size() && Defs[index])
+ {
+ value = Vals[index];
+ return true;
+ }
+ value = 0;
+ return false;
+ }
+
+ bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
+
+ void SetItem(unsigned index, bool defined, UInt64 value);
+};
+
+
+struct CFileItem
+{
+ UInt64 Size;
+ UInt32 Crc;
+ /*
+ int Parent;
+ bool IsAltStream;
+ */
+ bool HasStream; // Test it !!! it means that there is
+ // stream in some folder. It can be empty stream
+ bool IsDir;
+ bool CrcDefined;
+
+ /*
+ void Clear()
+ {
+ HasStream = true;
+ IsDir = false;
+ CrcDefined = false;
+ }
+
+ CFileItem():
+ // Parent(-1),
+ // IsAltStream(false),
+ HasStream(true),
+ IsDir(false),
+ CrcDefined(false),
+ {}
+ */
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.cpp
new file mode 100644
index 0000000000..5bd3a417f7
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.cpp
@@ -0,0 +1,901 @@
+// 7zOut.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/7zCrc.h"
+
+#include "../../../Common/AutoPtr.h"
+
+#include "../../Common/StreamObjects.h"
+
+#include "7zOut.h"
+
+namespace NArchive {
+namespace N7z {
+
+HRESULT COutArchive::WriteSignature()
+{
+ Byte buf[8];
+ memcpy(buf, kSignature, kSignatureSize);
+ buf[kSignatureSize] = kMajorVersion;
+ buf[kSignatureSize + 1] = 4;
+ return WriteDirect(buf, 8);
+}
+
+#ifdef _7Z_VOL
+HRESULT COutArchive::WriteFinishSignature()
+{
+ RINOK(WriteDirect(kFinishSignature, kSignatureSize));
+ CArchiveVersion av;
+ av.Major = kMajorVersion;
+ av.Minor = 2;
+ RINOK(WriteDirectByte(av.Major));
+ return WriteDirectByte(av.Minor);
+}
+#endif
+
+static void SetUInt32(Byte *p, UInt32 d)
+{
+ for (int i = 0; i < 4; i++, d >>= 8)
+ p[i] = (Byte)d;
+}
+
+static void SetUInt64(Byte *p, UInt64 d)
+{
+ for (int i = 0; i < 8; i++, d >>= 8)
+ p[i] = (Byte)d;
+}
+
+HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
+{
+ Byte buf[24];
+ SetUInt64(buf + 4, h.NextHeaderOffset);
+ SetUInt64(buf + 12, h.NextHeaderSize);
+ SetUInt32(buf + 20, h.NextHeaderCRC);
+ SetUInt32(buf, CrcCalc(buf + 4, 20));
+ return WriteDirect(buf, 24);
+}
+
+#ifdef _7Z_VOL
+HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
+{
+ CCRC crc;
+ crc.UpdateUInt64(h.NextHeaderOffset);
+ crc.UpdateUInt64(h.NextHeaderSize);
+ crc.UpdateUInt32(h.NextHeaderCRC);
+ crc.UpdateUInt64(h.ArchiveStartOffset);
+ crc.UpdateUInt64(h.AdditionalStartBlockSize);
+ RINOK(WriteDirectUInt32(crc.GetDigest()));
+ RINOK(WriteDirectUInt64(h.NextHeaderOffset));
+ RINOK(WriteDirectUInt64(h.NextHeaderSize));
+ RINOK(WriteDirectUInt32(h.NextHeaderCRC));
+ RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
+ return WriteDirectUInt64(h.AdditionalStartBlockSize);
+}
+#endif
+
+HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
+{
+ Close();
+ #ifdef _7Z_VOL
+ // endMarker = false;
+ _endMarker = endMarker;
+ #endif
+ SeqStream = stream;
+ if (!endMarker)
+ {
+ SeqStream.QueryInterface(IID_IOutStream, &Stream);
+ if (!Stream)
+ {
+ return E_NOTIMPL;
+ // endMarker = true;
+ }
+ }
+ #ifdef _7Z_VOL
+ if (endMarker)
+ {
+ /*
+ CStartHeader sh;
+ sh.NextHeaderOffset = (UInt32)(Int32)-1;
+ sh.NextHeaderSize = (UInt32)(Int32)-1;
+ sh.NextHeaderCRC = 0;
+ WriteStartHeader(sh);
+ */
+ }
+ else
+ #endif
+ {
+ if (!Stream)
+ return E_FAIL;
+ RINOK(WriteSignature());
+ RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
+ }
+ return S_OK;
+}
+
+void COutArchive::Close()
+{
+ SeqStream.Release();
+ Stream.Release();
+}
+
+HRESULT COutArchive::SkipPrefixArchiveHeader()
+{
+ #ifdef _7Z_VOL
+ if (_endMarker)
+ return S_OK;
+ #endif
+ Byte buf[24];
+ memset(buf, 0, 24);
+ return WriteDirect(buf, 24);
+}
+
+UInt64 COutArchive::GetPos() const
+{
+ if (_countMode)
+ return _countSize;
+ if (_writeToStream)
+ return _outByte.GetProcessedSize();
+ return _outByte2.GetPos();
+}
+
+void COutArchive::WriteBytes(const void *data, size_t size)
+{
+ if (_countMode)
+ _countSize += size;
+ else if (_writeToStream)
+ {
+ _outByte.WriteBytes(data, size);
+ _crc = CrcUpdate(_crc, data, size);
+ }
+ else
+ _outByte2.WriteBytes(data, size);
+}
+
+void COutArchive::WriteByte(Byte b)
+{
+ if (_countMode)
+ _countSize++;
+ else if (_writeToStream)
+ {
+ _outByte.WriteByte(b);
+ _crc = CRC_UPDATE_BYTE(_crc, b);
+ }
+ else
+ _outByte2.WriteByte(b);
+}
+
+void COutArchive::WriteUInt32(UInt32 value)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ WriteByte((Byte)value);
+ value >>= 8;
+ }
+}
+
+void COutArchive::WriteUInt64(UInt64 value)
+{
+ for (int i = 0; i < 8; i++)
+ {
+ WriteByte((Byte)value);
+ value >>= 8;
+ }
+}
+
+void COutArchive::WriteNumber(UInt64 value)
+{
+ Byte firstByte = 0;
+ Byte mask = 0x80;
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ if (value < ((UInt64(1) << ( 7 * (i + 1)))))
+ {
+ firstByte |= Byte(value >> (8 * i));
+ break;
+ }
+ firstByte |= mask;
+ mask >>= 1;
+ }
+ WriteByte(firstByte);
+ for (; i > 0; i--)
+ {
+ WriteByte((Byte)value);
+ value >>= 8;
+ }
+}
+
+static UInt32 GetBigNumberSize(UInt64 value)
+{
+ int i;
+ for (i = 1; i < 9; i++)
+ if (value < (((UInt64)1 << (i * 7))))
+ break;
+ return i;
+}
+
+#ifdef _7Z_VOL
+UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
+{
+ UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
+ if (nameLength != 0)
+ {
+ nameLength = (nameLength + 1) * 2;
+ result += nameLength + GetBigNumberSize(nameLength) + 2;
+ }
+ if (props)
+ {
+ result += 20;
+ }
+ if (result >= 128)
+ result++;
+ result += kSignatureSize + 2 + kFinishHeaderSize;
+ return result;
+}
+
+UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
+{
+ UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
+ int testSize;
+ if (volSize > headersSizeBase)
+ testSize = volSize - headersSizeBase;
+ else
+ testSize = 1;
+ UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
+ UInt64 pureSize = 1;
+ if (volSize > headersSize)
+ pureSize = volSize - headersSize;
+ return pureSize;
+}
+#endif
+
+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];
+ {
+ UInt64 id = coder.MethodID;
+ unsigned idSize;
+ for (idSize = 1; idSize < sizeof(id); idSize++)
+ if ((id >> (8 * idSize)) == 0)
+ break;
+ 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);
+
+ size_t propsSize = coder.Props.Size();
+ b |= ((propsSize != 0) ? 0x20 : 0);
+ temp[0] = b;
+ WriteBytes(temp, idSize + 1);
+ if (isComplex)
+ {
+ WriteNumber(coder.NumStreams);
+ WriteNumber(1); // NumOutStreams;
+ }
+ if (propsSize == 0)
+ continue;
+ WriteNumber(propsSize);
+ WriteBytes(coder.Props, propsSize);
+ }
+ }
+
+ for (i = 0; i < folder.Bonds.Size(); i++)
+ {
+ 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)
+{
+ Byte b = 0;
+ Byte mask = 0x80;
+ FOR_VECTOR (i, boolVector)
+ {
+ if (boolVector[i])
+ b |= mask;
+ mask >>= 1;
+ if (mask == 0)
+ {
+ WriteByte(b);
+ mask = 0x80;
+ b = 0;
+ }
+ }
+ if (mask != 0x80)
+ WriteByte(b);
+}
+
+static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }
+
+void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
+{
+ WriteByte(id);
+ WriteNumber(Bv_GetSizeInBytes(boolVector));
+ WriteBoolVector(boolVector);
+}
+
+unsigned BoolVector_CountSum(const CBoolVector &v);
+
+void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
+{
+ const unsigned numDefined = BoolVector_CountSum(digests.Defs);
+ if (numDefined == 0)
+ return;
+
+ WriteByte(NID::kCRC);
+ if (numDefined == digests.Defs.Size())
+ WriteByte(1);
+ else
+ {
+ WriteByte(0);
+ WriteBoolVector(digests.Defs);
+ }
+
+ for (unsigned i = 0; i < digests.Defs.Size(); i++)
+ if (digests.Defs[i])
+ WriteUInt32(digests.Vals[i]);
+}
+
+void COutArchive::WritePackInfo(
+ UInt64 dataOffset,
+ const CRecordVector<UInt64> &packSizes,
+ const CUInt32DefVector &packCRCs)
+{
+ if (packSizes.IsEmpty())
+ return;
+ WriteByte(NID::kPackInfo);
+ WriteNumber(dataOffset);
+ WriteNumber(packSizes.Size());
+ WriteByte(NID::kSize);
+ FOR_VECTOR (i, packSizes)
+ WriteNumber(packSizes[i]);
+
+ WriteHashDigests(packCRCs);
+
+ WriteByte(NID::kEnd);
+}
+
+void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)
+{
+ if (folders.IsEmpty())
+ return;
+
+ WriteByte(NID::kUnpackInfo);
+
+ WriteByte(NID::kFolder);
+ WriteNumber(folders.Size());
+ {
+ WriteByte(0);
+ FOR_VECTOR (i, folders)
+ WriteFolder(folders[i]);
+ }
+
+ WriteByte(NID::kCodersUnpackSize);
+ FOR_VECTOR (i, outFolders.CoderUnpackSizes)
+ WriteNumber(outFolders.CoderUnpackSizes[i]);
+
+ WriteHashDigests(outFolders.FolderUnpackCRCs);
+
+ WriteByte(NID::kEnd);
+}
+
+void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
+ const COutFolders &outFolders,
+ const CRecordVector<UInt64> &unpackSizes,
+ const CUInt32DefVector &digests)
+{
+ const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector;
+ WriteByte(NID::kSubStreamsInfo);
+
+ unsigned i;
+ for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
+ if (numUnpackStreamsInFolders[i] != 1)
+ {
+ WriteByte(NID::kNumUnpackStream);
+ for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
+ WriteNumber(numUnpackStreamsInFolders[i]);
+ break;
+ }
+
+ for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
+ if (numUnpackStreamsInFolders[i] > 1)
+ {
+ WriteByte(NID::kSize);
+ CNum index = 0;
+ for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
+ {
+ CNum num = numUnpackStreamsInFolders[i];
+ for (CNum j = 0; j < num; j++)
+ {
+ if (j + 1 != num)
+ WriteNumber(unpackSizes[index]);
+ index++;
+ }
+ }
+ break;
+ }
+
+ CUInt32DefVector digests2;
+
+ unsigned digestIndex = 0;
+ for (i = 0; i < folders.Size(); i++)
+ {
+ unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i];
+ if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i))
+ digestIndex++;
+ else
+ for (unsigned j = 0; j < numSubStreams; j++, digestIndex++)
+ {
+ digests2.Defs.Add(digests.Defs[digestIndex]);
+ digests2.Vals.Add(digests.Vals[digestIndex]);
+ }
+ }
+ WriteHashDigests(digests2);
+ WriteByte(NID::kEnd);
+}
+
+// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
+
+void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts)
+{
+ if (!_useAlign)
+ return;
+
+ const unsigned alignSize = (unsigned)1 << alignShifts;
+ pos += (unsigned)GetPos();
+ pos &= (alignSize - 1);
+ if (pos == 0)
+ return;
+ unsigned skip = alignSize - pos;
+ if (skip < 2)
+ skip += alignSize;
+ skip -= 2;
+ WriteByte(NID::kDummy);
+ WriteByte((Byte)skip);
+ for (unsigned i = 0; i < skip; i++)
+ WriteByte(0);
+}
+
+void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts)
+{
+ const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
+ const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2;
+ SkipToAligned(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSizeShifts);
+
+ WriteByte(type);
+ WriteNumber(dataSize);
+ if (numDefined == v.Size())
+ WriteByte(1);
+ else
+ {
+ WriteByte(0);
+ WriteBoolVector(v);
+ }
+ WriteByte(0); // 0 means no switching to external stream
+}
+
+void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
+{
+ const unsigned numDefined = BoolVector_CountSum(v.Defs);
+ if (numDefined == 0)
+ return;
+
+ WriteAlignedBools(v.Defs, numDefined, type, 3);
+
+ for (unsigned i = 0; i < v.Defs.Size(); i++)
+ if (v.Defs[i])
+ WriteUInt64(v.Vals[i]);
+}
+
+HRESULT COutArchive::EncodeStream(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CEncoder &encoder, const CByteBuffer &data,
+ CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
+{
+ CBufInStream *streamSpec = new CBufInStream;
+ CMyComPtr<ISequentialInStream> stream = streamSpec;
+ streamSpec->Init(data, data.Size());
+ outFolders.FolderUnpackCRCs.Defs.Add(true);
+ outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
+ // outFolders.NumUnpackStreamsVector.Add(1);
+ UInt64 dataSize64 = data.Size();
+ UInt64 unpackSize = data.Size();
+ RINOK(encoder.Encode(
+ EXTERNAL_CODECS_LOC_VARS
+ stream,
+ // NULL,
+ &dataSize64,
+ folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
+ return S_OK;
+}
+
+void COutArchive::WriteHeader(
+ const CArchiveDatabaseOut &db,
+ // const CHeaderOptions &headerOptions,
+ UInt64 &headerOffset)
+{
+ /*
+ bool thereIsSecure = (db.SecureBuf.Size() != 0);
+ */
+ _useAlign = true;
+
+ {
+ UInt64 packSize = 0;
+ FOR_VECTOR (i, db.PackSizes)
+ packSize += db.PackSizes[i];
+ headerOffset = packSize;
+ }
+
+
+ WriteByte(NID::kHeader);
+
+ // Archive Properties
+
+ if (db.Folders.Size() > 0)
+ {
+ WriteByte(NID::kMainStreamsInfo);
+ WritePackInfo(0, db.PackSizes, db.PackCRCs);
+ WriteUnpackInfo(db.Folders, (const COutFolders &)db);
+
+ CRecordVector<UInt64> unpackSizes;
+ CUInt32DefVector digests;
+ FOR_VECTOR (i, db.Files)
+ {
+ const CFileItem &file = db.Files[i];
+ if (!file.HasStream)
+ continue;
+ unpackSizes.Add(file.Size);
+ digests.Defs.Add(file.CrcDefined);
+ digests.Vals.Add(file.Crc);
+ }
+
+ WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests);
+ WriteByte(NID::kEnd);
+ }
+
+ if (db.Files.IsEmpty())
+ {
+ WriteByte(NID::kEnd);
+ return;
+ }
+
+ WriteByte(NID::kFilesInfo);
+ WriteNumber(db.Files.Size());
+
+ {
+ /* ---------- Empty Streams ---------- */
+ CBoolVector emptyStreamVector;
+ emptyStreamVector.ClearAndSetSize(db.Files.Size());
+ unsigned numEmptyStreams = 0;
+ {
+ FOR_VECTOR (i, db.Files)
+ if (db.Files[i].HasStream)
+ emptyStreamVector[i] = false;
+ else
+ {
+ emptyStreamVector[i] = true;
+ numEmptyStreams++;
+ }
+ }
+
+ if (numEmptyStreams != 0)
+ {
+ WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);
+
+ CBoolVector emptyFileVector, antiVector;
+ emptyFileVector.ClearAndSetSize(numEmptyStreams);
+ antiVector.ClearAndSetSize(numEmptyStreams);
+ bool thereAreEmptyFiles = false, thereAreAntiItems = false;
+ unsigned cur = 0;
+
+ FOR_VECTOR (i, db.Files)
+ {
+ const CFileItem &file = db.Files[i];
+ if (file.HasStream)
+ continue;
+ emptyFileVector[cur] = !file.IsDir;
+ if (!file.IsDir)
+ thereAreEmptyFiles = true;
+ bool isAnti = db.IsItemAnti(i);
+ antiVector[cur] = isAnti;
+ if (isAnti)
+ thereAreAntiItems = true;
+ cur++;
+ }
+
+ if (thereAreEmptyFiles)
+ WritePropBoolVector(NID::kEmptyFile, emptyFileVector);
+ if (thereAreAntiItems)
+ WritePropBoolVector(NID::kAnti, antiVector);
+ }
+ }
+
+
+ {
+ /* ---------- Names ---------- */
+
+ unsigned numDefined = 0;
+ size_t namesDataSize = 0;
+ FOR_VECTOR (i, db.Files)
+ {
+ const UString &name = db.Names[i];
+ if (!name.IsEmpty())
+ numDefined++;
+ namesDataSize += (name.Len() + 1) * 2;
+ }
+
+ if (numDefined > 0)
+ {
+ namesDataSize++;
+ SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
+
+ WriteByte(NID::kName);
+ WriteNumber(namesDataSize);
+ WriteByte(0);
+ FOR_VECTOR (i, db.Files)
+ {
+ const UString &name = db.Names[i];
+ for (unsigned t = 0; t <= name.Len(); t++)
+ {
+ wchar_t c = name[t];
+ WriteByte((Byte)c);
+ WriteByte((Byte)(c >> 8));
+ }
+ }
+ }
+ }
+
+ /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime);
+ /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime);
+ /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime);
+ WriteUInt64DefVector(db.StartPos, NID::kStartPos);
+
+ {
+ /* ---------- Write Attrib ---------- */
+ const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
+
+ if (numDefined != 0)
+ {
+ WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
+ FOR_VECTOR (i, db.Attrib.Defs)
+ {
+ if (db.Attrib.Defs[i])
+ WriteUInt32(db.Attrib.Vals[i]);
+ }
+ }
+ }
+
+ /*
+ {
+ // ---------- Write IsAux ----------
+ if (BoolVector_CountSum(db.IsAux) != 0)
+ WritePropBoolVector(NID::kIsAux, db.IsAux);
+ }
+
+ {
+ // ---------- Write Parent ----------
+ CBoolVector boolVector;
+ boolVector.Reserve(db.Files.Size());
+ unsigned numIsDir = 0;
+ unsigned numParentLinks = 0;
+ for (i = 0; i < db.Files.Size(); i++)
+ {
+ const CFileItem &file = db.Files[i];
+ bool defined = !file.IsAltStream;
+ boolVector.Add(defined);
+ if (defined)
+ numIsDir++;
+ if (file.Parent >= 0)
+ numParentLinks++;
+ }
+ if (numParentLinks > 0)
+ {
+ // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2);
+ const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);
+ const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;
+ SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2);
+
+ WriteByte(NID::kParent);
+ WriteNumber(dataSize);
+ if (numIsDir == boolVector.Size())
+ WriteByte(1);
+ else
+ {
+ WriteByte(0);
+ WriteBoolVector(boolVector);
+ }
+ for (i = 0; i < db.Files.Size(); i++)
+ {
+ const CFileItem &file = db.Files[i];
+ // if (file.Parent >= 0)
+ WriteUInt32(file.Parent);
+ }
+ }
+ }
+
+ if (thereIsSecure)
+ {
+ UInt64 secureDataSize = 1 + 4 +
+ db.SecureBuf.Size() +
+ db.SecureSizes.Size() * 4;
+ // secureDataSize += db.SecureIDs.Size() * 4;
+ for (i = 0; i < db.SecureIDs.Size(); i++)
+ secureDataSize += GetBigNumberSize(db.SecureIDs[i]);
+ SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2);
+ WriteByte(NID::kNtSecure);
+ WriteNumber(secureDataSize);
+ WriteByte(0);
+ WriteUInt32(db.SecureSizes.Size());
+ for (i = 0; i < db.SecureSizes.Size(); i++)
+ WriteUInt32(db.SecureSizes[i]);
+ WriteBytes(db.SecureBuf, db.SecureBuf.Size());
+ for (i = 0; i < db.SecureIDs.Size(); i++)
+ {
+ WriteNumber(db.SecureIDs[i]);
+ // WriteUInt32(db.SecureIDs[i]);
+ }
+ }
+ */
+
+ WriteByte(NID::kEnd); // for files
+ WriteByte(NID::kEnd); // for headers
+}
+
+HRESULT COutArchive::WriteDatabase(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const CArchiveDatabaseOut &db,
+ const CCompressionMethodMode *options,
+ const CHeaderOptions &headerOptions)
+{
+ if (!db.CheckNumFiles())
+ return E_FAIL;
+
+ UInt64 headerOffset;
+ UInt32 headerCRC;
+ UInt64 headerSize;
+ if (db.IsEmpty())
+ {
+ headerSize = 0;
+ headerOffset = 0;
+ headerCRC = CrcCalc(0, 0);
+ }
+ else
+ {
+ bool encodeHeaders = false;
+ if (options != 0)
+ if (options->IsEmpty())
+ options = 0;
+ if (options != 0)
+ if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
+ encodeHeaders = true;
+
+ _outByte.SetStream(SeqStream);
+ _outByte.Init();
+ _crc = CRC_INIT_VAL;
+ _countMode = encodeHeaders;
+ _writeToStream = true;
+ _countSize = 0;
+ WriteHeader(db, /* headerOptions, */ headerOffset);
+
+ if (encodeHeaders)
+ {
+ CByteBuffer buf(_countSize);
+ _outByte2.Init((Byte *)buf, _countSize);
+
+ _countMode = false;
+ _writeToStream = false;
+ WriteHeader(db, /* headerOptions, */ headerOffset);
+
+ if (_countSize != _outByte2.GetPos())
+ return E_FAIL;
+
+ CCompressionMethodMode encryptOptions;
+ encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
+ encryptOptions.Password = options->Password;
+ CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
+ CRecordVector<UInt64> packSizes;
+ CObjectVector<CFolder> folders;
+ COutFolders outFolders;
+
+ RINOK(EncodeStream(
+ EXTERNAL_CODECS_LOC_VARS
+ encoder, buf,
+ packSizes, folders, outFolders));
+
+ _writeToStream = true;
+
+ if (folders.Size() == 0)
+ throw 1;
+
+ WriteID(NID::kEncodedHeader);
+ WritePackInfo(headerOffset, packSizes, CUInt32DefVector());
+ WriteUnpackInfo(folders, outFolders);
+ WriteByte(NID::kEnd);
+ FOR_VECTOR (i, packSizes)
+ headerOffset += packSizes[i];
+ }
+ RINOK(_outByte.Flush());
+ headerCRC = CRC_GET_DIGEST(_crc);
+ headerSize = _outByte.GetProcessedSize();
+ }
+ #ifdef _7Z_VOL
+ if (_endMarker)
+ {
+ CFinishHeader h;
+ h.NextHeaderSize = headerSize;
+ h.NextHeaderCRC = headerCRC;
+ h.NextHeaderOffset =
+ UInt64(0) - (headerSize +
+ 4 + kFinishHeaderSize);
+ h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
+ h.AdditionalStartBlockSize = 0;
+ RINOK(WriteFinishHeader(h));
+ return WriteFinishSignature();
+ }
+ else
+ #endif
+ {
+ CStartHeader h;
+ h.NextHeaderSize = headerSize;
+ h.NextHeaderCRC = headerCRC;
+ h.NextHeaderOffset = headerOffset;
+ RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
+ return WriteStartHeader(h);
+ }
+}
+
+void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value)
+{
+ while (index >= Defs.Size())
+ Defs.Add(false);
+ Defs[index] = defined;
+ if (!defined)
+ return;
+ while (index >= Vals.Size())
+ Vals.Add(0);
+ Vals[index] = value;
+}
+
+void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)
+{
+ while (index >= Defs.Size())
+ Defs.Add(false);
+ Defs[index] = defined;
+ if (!defined)
+ return;
+ while (index >= Vals.Size())
+ Vals.Add(0);
+ Vals[index] = value;
+}
+
+void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name)
+{
+ unsigned index = Files.Size();
+ CTime.SetItem(index, file2.CTimeDefined, file2.CTime);
+ ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
+ MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
+ StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
+ Attrib.SetItem(index, file2.AttribDefined, file2.Attrib);
+ SetItem_Anti(index, file2.IsAnti);
+ // SetItem_Aux(index, file2.IsAux);
+ Names.Add(name);
+ Files.Add(file);
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.h
new file mode 100644
index 0000000000..12e965f861
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.h
@@ -0,0 +1,335 @@
+// 7zOut.h
+
+#ifndef __7Z_OUT_H
+#define __7Z_OUT_H
+
+#include "7zCompressionMode.h"
+#include "7zEncode.h"
+#include "7zHeader.h"
+#include "7zItem.h"
+
+#include "../../Common/OutBuffer.h"
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CWriteBufferLoc
+{
+ Byte *_data;
+ size_t _size;
+ size_t _pos;
+public:
+ CWriteBufferLoc(): _size(0), _pos(0) {}
+ void Init(Byte *data, size_t size)
+ {
+ _data = data;
+ _size = size;
+ _pos = 0;
+ }
+ void WriteBytes(const void *data, size_t size)
+ {
+ if (size == 0)
+ return;
+ if (size > _size - _pos)
+ throw 1;
+ memcpy(_data + _pos, data, size);
+ _pos += size;
+ }
+ void WriteByte(Byte b)
+ {
+ if (_size == _pos)
+ throw 1;
+ _data[_pos++] = b;
+ }
+ size_t GetPos() const { return _pos; }
+};
+
+
+struct CHeaderOptions
+{
+ bool CompressMainHeader;
+ /*
+ bool WriteCTime;
+ bool WriteATime;
+ bool WriteMTime;
+ */
+
+ CHeaderOptions():
+ CompressMainHeader(true)
+ /*
+ , WriteCTime(false)
+ , WriteATime(false)
+ , WriteMTime(true)
+ */
+ {}
+};
+
+
+struct CFileItem2
+{
+ UInt64 CTime;
+ UInt64 ATime;
+ UInt64 MTime;
+ UInt64 StartPos;
+ UInt32 Attrib;
+
+ bool CTimeDefined;
+ bool ATimeDefined;
+ bool MTimeDefined;
+ bool StartPosDefined;
+ bool AttribDefined;
+ bool IsAnti;
+ // bool IsAux;
+
+ /*
+ void Init()
+ {
+ CTimeDefined = false;
+ ATimeDefined = false;
+ MTimeDefined = false;
+ StartPosDefined = false;
+ AttribDefined = false;
+ IsAnti = false;
+ // IsAux = false;
+ }
+ */
+};
+
+
+struct COutFolders
+{
+ CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
+
+ CRecordVector<CNum> NumUnpackStreamsVector;
+ CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders
+
+ void OutFoldersClear()
+ {
+ FolderUnpackCRCs.Clear();
+ NumUnpackStreamsVector.Clear();
+ CoderUnpackSizes.Clear();
+ }
+
+ void OutFoldersReserveDown()
+ {
+ FolderUnpackCRCs.ReserveDown();
+ NumUnpackStreamsVector.ReserveDown();
+ CoderUnpackSizes.ReserveDown();
+ }
+};
+
+
+struct CArchiveDatabaseOut: public COutFolders
+{
+ CRecordVector<UInt64> PackSizes;
+ CUInt32DefVector PackCRCs;
+ CObjectVector<CFolder> Folders;
+
+ CRecordVector<CFileItem> Files;
+ UStringVector Names;
+ CUInt64DefVector CTime;
+ CUInt64DefVector ATime;
+ CUInt64DefVector MTime;
+ CUInt64DefVector StartPos;
+ CUInt32DefVector Attrib;
+ CBoolVector IsAnti;
+
+ /*
+ CBoolVector IsAux;
+
+ CByteBuffer SecureBuf;
+ CRecordVector<UInt32> SecureSizes;
+ CRecordVector<UInt32> SecureIDs;
+
+ void ClearSecure()
+ {
+ SecureBuf.Free();
+ SecureSizes.Clear();
+ SecureIDs.Clear();
+ }
+ */
+
+ void Clear()
+ {
+ OutFoldersClear();
+
+ PackSizes.Clear();
+ PackCRCs.Clear();
+ Folders.Clear();
+
+ Files.Clear();
+ Names.Clear();
+ CTime.Clear();
+ ATime.Clear();
+ MTime.Clear();
+ StartPos.Clear();
+ Attrib.Clear();
+ IsAnti.Clear();
+
+ /*
+ IsAux.Clear();
+ ClearSecure();
+ */
+ }
+
+ void ReserveDown()
+ {
+ OutFoldersReserveDown();
+
+ PackSizes.ReserveDown();
+ PackCRCs.ReserveDown();
+ Folders.ReserveDown();
+
+ Files.ReserveDown();
+ Names.ReserveDown();
+ CTime.ReserveDown();
+ ATime.ReserveDown();
+ MTime.ReserveDown();
+ StartPos.ReserveDown();
+ Attrib.ReserveDown();
+ IsAnti.ReserveDown();
+
+ /*
+ IsAux.ReserveDown();
+ */
+ }
+
+ bool IsEmpty() const
+ {
+ return (
+ PackSizes.IsEmpty() &&
+ NumUnpackStreamsVector.IsEmpty() &&
+ Folders.IsEmpty() &&
+ Files.IsEmpty());
+ }
+
+ bool CheckNumFiles() const
+ {
+ unsigned size = Files.Size();
+ return (
+ CTime.CheckSize(size)
+ && ATime.CheckSize(size)
+ && MTime.CheckSize(size)
+ && StartPos.CheckSize(size)
+ && Attrib.CheckSize(size)
+ && (size == IsAnti.Size() || IsAnti.Size() == 0));
+ }
+
+ bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
+ // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
+
+ void SetItem_Anti(unsigned index, bool isAnti)
+ {
+ while (index >= IsAnti.Size())
+ IsAnti.Add(false);
+ IsAnti[index] = isAnti;
+ }
+ /*
+ void SetItem_Aux(unsigned index, bool isAux)
+ {
+ while (index >= IsAux.Size())
+ IsAux.Add(false);
+ IsAux[index] = isAux;
+ }
+ */
+
+ void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);
+};
+
+
+class COutArchive
+{
+ UInt64 _prefixHeaderPos;
+
+ HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); }
+
+ UInt64 GetPos() const;
+ void WriteBytes(const void *data, size_t size);
+ void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }
+ void WriteByte(Byte b);
+ void WriteUInt32(UInt32 value);
+ void WriteUInt64(UInt64 value);
+ void WriteNumber(UInt64 value);
+ void WriteID(UInt64 value) { WriteNumber(value); }
+
+ void WriteFolder(const CFolder &folder);
+ HRESULT WriteFileHeader(const CFileItem &itemInfo);
+ void WriteBoolVector(const CBoolVector &boolVector);
+ void WritePropBoolVector(Byte id, const CBoolVector &boolVector);
+
+ void WriteHashDigests(const CUInt32DefVector &digests);
+
+ void WritePackInfo(
+ UInt64 dataOffset,
+ const CRecordVector<UInt64> &packSizes,
+ const CUInt32DefVector &packCRCs);
+
+ void WriteUnpackInfo(
+ const CObjectVector<CFolder> &folders,
+ const COutFolders &outFolders);
+
+ void WriteSubStreamsInfo(
+ const CObjectVector<CFolder> &folders,
+ const COutFolders &outFolders,
+ const CRecordVector<UInt64> &unpackSizes,
+ const CUInt32DefVector &digests);
+
+ void SkipToAligned(unsigned pos, unsigned alignShifts);
+ void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);
+ void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);
+
+ HRESULT EncodeStream(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CEncoder &encoder, const CByteBuffer &data,
+ CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders);
+ void WriteHeader(
+ const CArchiveDatabaseOut &db,
+ // const CHeaderOptions &headerOptions,
+ UInt64 &headerOffset);
+
+ bool _countMode;
+ bool _writeToStream;
+ size_t _countSize;
+ UInt32 _crc;
+ COutBuffer _outByte;
+ CWriteBufferLoc _outByte2;
+
+ #ifdef _7Z_VOL
+ bool _endMarker;
+ #endif
+
+ bool _useAlign;
+
+ HRESULT WriteSignature();
+ #ifdef _7Z_VOL
+ HRESULT WriteFinishSignature();
+ #endif
+ HRESULT WriteStartHeader(const CStartHeader &h);
+ #ifdef _7Z_VOL
+ HRESULT WriteFinishHeader(const CFinishHeader &h);
+ #endif
+ CMyComPtr<IOutStream> Stream;
+public:
+
+ COutArchive() { _outByte.Create(1 << 16); }
+ CMyComPtr<ISequentialOutStream> SeqStream;
+ HRESULT Create(ISequentialOutStream *stream, bool endMarker);
+ void Close();
+ HRESULT SkipPrefixArchiveHeader();
+ HRESULT WriteDatabase(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const CArchiveDatabaseOut &db,
+ const CCompressionMethodMode *options,
+ const CHeaderOptions &headerOptions);
+
+ #ifdef _7Z_VOL
+ static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);
+ static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);
+ #endif
+
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.cpp
new file mode 100644
index 0000000000..388ac766c6
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.cpp
@@ -0,0 +1,174 @@
+// 7zProperties.cpp
+
+#include "StdAfx.h"
+
+#include "7zProperties.h"
+#include "7zHeader.h"
+#include "7zHandler.h"
+
+// #define _MULTI_PACK
+
+namespace NArchive {
+namespace N7z {
+
+struct CPropMap
+{
+ UInt32 FilePropID;
+ CStatProp StatProp;
+};
+
+static const CPropMap kPropMap[] =
+{
+ { NID::kName, { NULL, kpidPath, VT_BSTR } },
+ { NID::kSize, { NULL, kpidSize, VT_UI8 } },
+ { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } },
+
+ #ifdef _MULTI_PACK
+ { 100, { "Pack0", kpidPackedSize0, VT_UI8 } },
+ { 101, { "Pack1", kpidPackedSize1, VT_UI8 } },
+ { 102, { "Pack2", kpidPackedSize2, VT_UI8 } },
+ { 103, { "Pack3", kpidPackedSize3, VT_UI8 } },
+ { 104, { "Pack4", kpidPackedSize4, VT_UI8 } },
+ #endif
+
+ { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },
+ { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
+ { NID::kATime, { NULL, kpidATime, VT_FILETIME } },
+ { NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },
+ { NID::kStartPos, { NULL, kpidPosition, VT_UI8 } },
+
+ { NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
+
+// { NID::kIsAux, { NULL, kpidIsAux, VT_BOOL } },
+ { NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }
+
+ #ifndef _SFX
+ ,
+ { 97, { NULL, kpidEncrypted, VT_BOOL } },
+ { 98, { NULL, kpidMethod, VT_BSTR } },
+ { 99, { NULL, kpidBlock, VT_UI4 } }
+ #endif
+};
+
+static void CopyOneItem(CRecordVector<UInt64> &src,
+ CRecordVector<UInt64> &dest, UInt32 item)
+{
+ FOR_VECTOR (i, src)
+ if (src[i] == item)
+ {
+ dest.Add(item);
+ src.Delete(i);
+ return;
+ }
+}
+
+static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
+{
+ FOR_VECTOR (i, src)
+ if (src[i] == item)
+ {
+ src.Delete(i);
+ return;
+ }
+}
+
+static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)
+{
+ FOR_VECTOR (i, dest)
+ if (dest[i] == item)
+ {
+ dest.Delete(i);
+ break;
+ }
+ dest.Insert(0, item);
+}
+
+#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id);
+
+void CHandler::FillPopIDs()
+{
+ _fileInfoPopIDs.Clear();
+
+ #ifdef _7Z_VOL
+ if (_volumes.Size() < 1)
+ return;
+ const CVolume &volume = _volumes.Front();
+ const CArchiveDatabaseEx &_db = volume.Database;
+ #endif
+
+ CRecordVector<UInt64> fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs;
+
+ RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
+ RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
+ /*
+ RemoveOneItem(fileInfoPopIDs, NID::kParent);
+ RemoveOneItem(fileInfoPopIDs, NID::kNtSecure);
+ */
+
+ COPY_ONE_ITEM(kName);
+ COPY_ONE_ITEM(kAnti);
+ COPY_ONE_ITEM(kSize);
+ COPY_ONE_ITEM(kPackInfo);
+ COPY_ONE_ITEM(kCTime);
+ COPY_ONE_ITEM(kMTime);
+ COPY_ONE_ITEM(kATime);
+ COPY_ONE_ITEM(kWinAttrib);
+ COPY_ONE_ITEM(kCRC);
+ COPY_ONE_ITEM(kComment);
+
+ _fileInfoPopIDs += fileInfoPopIDs;
+
+ #ifndef _SFX
+ _fileInfoPopIDs.Add(97);
+ _fileInfoPopIDs.Add(98);
+ _fileInfoPopIDs.Add(99);
+ #endif
+
+ #ifdef _MULTI_PACK
+ _fileInfoPopIDs.Add(100);
+ _fileInfoPopIDs.Add(101);
+ _fileInfoPopIDs.Add(102);
+ _fileInfoPopIDs.Add(103);
+ _fileInfoPopIDs.Add(104);
+ #endif
+
+ #ifndef _SFX
+ InsertToHead(_fileInfoPopIDs, NID::kMTime);
+ InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
+ InsertToHead(_fileInfoPopIDs, NID::kSize);
+ InsertToHead(_fileInfoPopIDs, NID::kName);
+ #endif
+}
+
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
+{
+ *numProps = _fileInfoPopIDs.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ if (index >= _fileInfoPopIDs.Size())
+ return E_INVALIDARG;
+ UInt64 id = _fileInfoPopIDs[index];
+ for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++)
+ {
+ const CPropMap &pr = kPropMap[i];
+ if (pr.FilePropID == id)
+ {
+ const CStatProp &st = pr.StatProp;
+ *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/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.h
new file mode 100644
index 0000000000..7b78130ef5
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.h
@@ -0,0 +1,22 @@
+// 7zProperties.h
+
+#ifndef __7Z_PROPERTIES_H
+#define __7Z_PROPERTIES_H
+
+#include "../../PropID.h"
+
+namespace NArchive {
+namespace N7z {
+
+enum
+{
+ kpidPackedSize0 = kpidUserDefined,
+ kpidPackedSize1,
+ kpidPackedSize2,
+ kpidPackedSize3,
+ kpidPackedSize4
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zRegister.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zRegister.cpp
new file mode 100644
index 0000000000..3e8cfb6645
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zRegister.cpp
@@ -0,0 +1,21 @@
+// 7zRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "7zHandler.h"
+
+namespace NArchive {
+namespace N7z {
+
+static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
+
+REGISTER_ARC_IO_DECREMENT_SIG(
+ "7z", "7z", NULL, 7,
+ k_Signature_Dec,
+ 0,
+ NArcInfoFlags::kFindSignature,
+ NULL);
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.cpp
new file mode 100644
index 0000000000..e9671a87e9
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.cpp
@@ -0,0 +1,22 @@
+// 7zSpecStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zSpecStream.h"
+
+STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return result;
+}
+
+STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+ if (!_getSubStreamSize)
+ return E_NOTIMPL;
+ return _getSubStreamSize->GetSubStreamSize(subStream, value);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.h
new file mode 100644
index 0000000000..09941287d6
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.h
@@ -0,0 +1,35 @@
+// 7zSpecStream.h
+
+#ifndef __7Z_SPEC_STREAM_H
+#define __7Z_SPEC_STREAM_H
+
+#include "../../../Common/MyCom.h"
+
+#include "../../ICoder.h"
+
+class CSequentialInStreamSizeCount2:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialInStream> _stream;
+ CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;
+ UInt64 _size;
+public:
+ void Init(ISequentialInStream *stream)
+ {
+ _size = 0;
+ _getSubStreamSize.Release();
+ _stream = stream;
+ _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
+ }
+ UInt64 GetSize() const { return _size; }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.cpp
new file mode 100644
index 0000000000..44de9ac4fc
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -0,0 +1,2497 @@
+// 7zUpdate.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/Wildcard.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "../Common/ItemNameUtils.h"
+
+#include "7zDecode.h"
+#include "7zEncode.h"
+#include "7zFolderInStream.h"
+#include "7zHandler.h"
+#include "7zOut.h"
+#include "7zUpdate.h"
+
+namespace NArchive {
+namespace N7z {
+
+
+#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_SPARC)
+ 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, bool extractFilter)
+{
+ CFilterMode2 m;
+ m.Id = 0;
+ m.Delta = 0;
+ m.Encrypted = f.IsEncrypted();
+
+ if (extractFilter)
+ {
+ 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)
+{
+ RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0));
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
+ streamSpec->SetStream(inStream);
+ streamSpec->Init(size);
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+ RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
+ return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
+}
+
+/*
+unsigned CUpdateItem::GetExtensionPos() const
+{
+ int slashPos = Name.ReverseFind_PathSepar();
+ int dotPos = Name.ReverseFind_Dot();
+ if (dotPos <= slashPos)
+ return Name.Len();
+ return dotPos + 1;
+}
+
+UString CUpdateItem::GetExtension() const
+{
+ return Name.Ptr(GetExtensionPos());
+}
+*/
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b))
+
+/*
+static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
+{
+ size_t c1 = a1.GetCapacity();
+ size_t c2 = a2.GetCapacity();
+ RINOZ_COMP(c1, c2);
+ for (size_t i = 0; i < c1; i++)
+ RINOZ_COMP(a1[i], a2[i]);
+ return 0;
+}
+
+static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
+{
+ RINOZ_COMP(c1.NumInStreams, c2.NumInStreams);
+ RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams);
+ RINOZ_COMP(c1.MethodID, c2.MethodID);
+ return CompareBuffers(c1.Props, c2.Props);
+}
+
+static int CompareBonds(const CBond &b1, const CBond &b2)
+{
+ RINOZ_COMP(b1.InIndex, b2.InIndex);
+ return MyCompare(b1.OutIndex, b2.OutIndex);
+}
+
+static int CompareFolders(const CFolder &f1, const CFolder &f2)
+{
+ int s1 = f1.Coders.Size();
+ int s2 = f2.Coders.Size();
+ RINOZ_COMP(s1, s2);
+ int i;
+ for (i = 0; i < s1; i++)
+ RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
+ s1 = f1.Bonds.Size();
+ s2 = f2.Bonds.Size();
+ RINOZ_COMP(s1, s2);
+ for (i = 0; i < s1; i++)
+ RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i]));
+ return 0;
+}
+*/
+
+/*
+static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
+{
+ return CompareFileNames(f1.Name, f2.Name);
+}
+*/
+
+struct CFolderRepack
+{
+ unsigned FolderIndex;
+ CNum NumCopyFiles;
+};
+
+/*
+static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *)
+{
+ 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]));
+
+ 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]]);
+}
+*/
+
+/*
+ we sort empty files and dirs in such order:
+ - Dir.NonAnti (name sorted)
+ - File.NonAnti (name sorted)
+ - File.Anti (name sorted)
+ - Dir.Anti (reverse name sorted)
+*/
+
+static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param)
+{
+ const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
+ const CUpdateItem &u1 = updateItems[*p1];
+ const CUpdateItem &u2 = updateItems[*p2];
+ // NonAnti < Anti
+ if (u1.IsAnti != u2.IsAnti)
+ return (u1.IsAnti ? 1 : -1);
+ if (u1.IsDir != u2.IsDir)
+ {
+ // Dir.NonAnti < File < Dir.Anti
+ if (u1.IsDir)
+ return (u1.IsAnti ? 1 : -1);
+ return (u2.IsAnti ? -1 : 1);
+ }
+ int n = CompareFileNames(u1.Name, u2.Name);
+ return (u1.IsDir && u1.IsAnti) ? -n : n;
+}
+
+static const char *g_Exts =
+ " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo"
+ " zip jar ear war msi"
+ " 3gp avi mov mpeg mpg mpe wmv"
+ " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
+ " swf"
+ " chm hxi hxs"
+ " gif jpeg jpg jp2 png tiff bmp ico psd psp"
+ " awg ps eps cgm dxf svg vrml wmf emf ai md"
+ " cad dwg pps key sxi"
+ " max 3ds"
+ " iso bin nrg mdf img pdi tar cpio xpi"
+ " vfd vhd vud vmc vsv"
+ " vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
+ " inl inc idl acf asa"
+ " h hpp hxx c cpp cxx m mm go swift"
+ " rc java cs rs pas bas vb cls ctl frm dlg def"
+ " f77 f f90 f95"
+ " asm s"
+ " sql manifest dep"
+ " mak clw csproj vcproj sln dsp dsw"
+ " class"
+ " bat cmd bash sh"
+ " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
+ " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs"
+ " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"
+ " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"
+ " abw afp cwk lwp wpd wps wpt wrf wri"
+ " abf afm bdf fon mgf otf pcf pfa snf ttf"
+ " dbf mdb nsf ntf wdb db fdb gdb"
+ " exe dll ocx vbx sfx sys tlb awx com obj lib out o so"
+ " pdb pch idb ncb opt";
+
+static unsigned GetExtIndex(const char *ext)
+{
+ unsigned extIndex = 1;
+ const char *p = g_Exts;
+ for (;;)
+ {
+ char c = *p++;
+ if (c == 0)
+ return extIndex;
+ if (c == ' ')
+ continue;
+ unsigned pos = 0;
+ for (;;)
+ {
+ char c2 = ext[pos++];
+ if (c2 == 0 && (c == 0 || c == ' '))
+ return extIndex;
+ if (c != c2)
+ break;
+ c = *p++;
+ }
+ extIndex++;
+ for (;;)
+ {
+ if (c == 0)
+ return extIndex;
+ if (c == ' ')
+ break;
+ c = *p++;
+ }
+ }
+}
+
+struct CRefItem
+{
+ const CUpdateItem *UpdateItem;
+ UInt32 Index;
+ unsigned ExtensionPos;
+ unsigned NamePos;
+ unsigned ExtensionIndex;
+
+ CRefItem() {};
+ CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType):
+ UpdateItem(&ui),
+ Index(index),
+ ExtensionPos(0),
+ NamePos(0),
+ ExtensionIndex(0)
+ {
+ if (sortByType)
+ {
+ int slashPos = ui.Name.ReverseFind_PathSepar();
+ NamePos = slashPos + 1;
+ int dotPos = ui.Name.ReverseFind_Dot();
+ if (dotPos <= slashPos)
+ ExtensionPos = ui.Name.Len();
+ else
+ {
+ ExtensionPos = dotPos + 1;
+ if (ExtensionPos != ui.Name.Len())
+ {
+ AString s;
+ for (unsigned pos = ExtensionPos;; pos++)
+ {
+ wchar_t c = ui.Name[pos];
+ if (c >= 0x80)
+ break;
+ if (c == 0)
+ {
+ ExtensionIndex = GetExtIndex(s);
+ break;
+ }
+ s += (char)MyCharLower_Ascii((char)c);
+ }
+ }
+ }
+ }
+ }
+};
+
+struct CSortParam
+{
+ // const CObjectVector<CTreeFolder> *TreeFolders;
+ bool SortByType;
+};
+
+/*
+ we sort files in such order:
+ - Dir.NonAnti (name sorted)
+ - alt streams
+ - Dirs
+ - Dir.Anti (reverse name sorted)
+*/
+
+
+static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)
+{
+ const CRefItem &a1 = *p1;
+ const CRefItem &a2 = *p2;
+ const CUpdateItem &u1 = *a1.UpdateItem;
+ const CUpdateItem &u2 = *a2.UpdateItem;
+
+ /*
+ if (u1.IsAltStream != u2.IsAltStream)
+ return u1.IsAltStream ? 1 : -1;
+ */
+
+ // Actually there are no dirs that time. They were stored in other steps
+ // So that code is unused?
+ if (u1.IsDir != u2.IsDir)
+ return u1.IsDir ? 1 : -1;
+ if (u1.IsDir)
+ {
+ if (u1.IsAnti != u2.IsAnti)
+ return (u1.IsAnti ? 1 : -1);
+ int n = CompareFileNames(u1.Name, u2.Name);
+ return -n;
+ }
+
+ // bool sortByType = *(bool *)param;
+ const CSortParam *sortParam = (const CSortParam *)param;
+ bool sortByType = sortParam->SortByType;
+ if (sortByType)
+ {
+ RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex);
+ RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos)));
+ RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos)));
+ if (!u1.MTimeDefined && u2.MTimeDefined) return 1;
+ if (u1.MTimeDefined && !u2.MTimeDefined) return -1;
+ if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime);
+ RINOZ_COMP(u1.Size, u2.Size);
+ }
+ /*
+ int par1 = a1.UpdateItem->ParentFolderIndex;
+ int par2 = a2.UpdateItem->ParentFolderIndex;
+ const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1];
+ const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2];
+
+ int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd;
+ int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd;
+ if (b1 < b2)
+ {
+ if (e1 <= b2)
+ return -1;
+ // p2 in p1
+ int par = par2;
+ for (;;)
+ {
+ const CTreeFolder &tf = (*sortParam->TreeFolders)[par];
+ par = tf.Parent;
+ if (par == par1)
+ {
+ RINOZ(CompareFileNames(u1.Name, tf.Name));
+ break;
+ }
+ }
+ }
+ else if (b2 < b1)
+ {
+ if (e2 <= b1)
+ return 1;
+ // p1 in p2
+ int par = par1;
+ for (;;)
+ {
+ const CTreeFolder &tf = (*sortParam->TreeFolders)[par];
+ par = tf.Parent;
+ if (par == par2)
+ {
+ RINOZ(CompareFileNames(tf.Name, u2.Name));
+ break;
+ }
+ }
+ }
+ */
+ // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex);
+ RINOK(CompareFileNames(u1.Name, u2.Name));
+ RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient);
+ RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive);
+ return 0;
+}
+
+struct CSolidGroup
+{
+ CRecordVector<UInt32> Indices;
+
+ CRecordVector<CFolderRepack> folderRefs;
+};
+
+static const char * const g_ExeExts[] =
+{
+ "dll"
+ , "exe"
+ , "ocx"
+ , "sfx"
+ , "sys"
+};
+
+static bool IsExeExt(const wchar_t *ext)
+{
+ 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;
+
+ 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.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 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);
+
+ m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20);
+ m.AddProp32(NCoderPropID::kNumFastBytes, 128);
+ m.AddProp32(NCoderPropID::kNumThreads, 1);
+ m.AddProp32(NCoderPropID::kLitPosBits, 2);
+ m.AddProp32(NCoderPropID::kLitContextBits, 0);
+ // 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);
+
+ 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 HRESULT MakeExeMethod(CCompressionMethodMode &mode,
+ const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter)
+{
+ if (mode.Filter_was_Inserted)
+ {
+ 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++;
+ }
+ }
+
+ HRESULT res;
+
+ if (bcj2Filter && Is86Filter(filterMode.Id))
+ {
+ GetMethodFull(k_BCJ2, 4, m);
+ res = AddBcj2Methods(mode);
+ }
+ else
+ {
+ 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);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+
+static void UpdateItem_To_FileItem2(const CUpdateItem &ui, CFileItem2 &file2)
+{
+ file2.Attrib = ui.Attrib; file2.AttribDefined = ui.AttribDefined;
+ file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined;
+ file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined;
+ file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined;
+ file2.IsAnti = ui.IsAnti;
+ // file2.IsAux = false;
+ file2.StartPosDefined = false;
+ // file2.StartPos = 0;
+}
+
+
+static void UpdateItem_To_FileItem(const CUpdateItem &ui,
+ CFileItem &file, CFileItem2 &file2)
+{
+ UpdateItem_To_FileItem2(ui, file2);
+
+ file.Size = ui.Size;
+ file.IsDir = ui.IsDir;
+ file.HasStream = ui.HasStream();
+ // file.IsAltStream = ui.IsAltStream;
+}
+
+
+
+class CRepackInStreamWithSizes:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialInStream> _stream;
+ // UInt64 _size;
+ const CBoolVector *_extractStatuses;
+ UInt32 _startIndex;
+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;
+
+ const CBoolVector *_extractStatuses;
+ UInt32 _startIndex;
+ unsigned _currentIndex;
+
+ HRESULT OpenFile();
+ HRESULT CloseFile();
+ HRESULT ProcessEmptyFiles();
+
+public:
+ const CDbEx *_db;
+ CMyComPtr<IArchiveUpdateCallbackFile> _opCallback;
+ CMyComPtr<IArchiveExtractCallbackMessage> _extractCallback;
+
+ HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses);
+ HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
+};
+
+HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses)
+{
+ _startIndex = startIndex;
+ _extractStatuses = extractStatuses;
+
+ _currentIndex = 0;
+ _fileIsOpen = false;
+
+ return ProcessEmptyFiles();
+}
+
+HRESULT CRepackStreamBase::OpenFile()
+{
+ 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);
+
+ _fileIsOpen = true;
+ _rem = fi.Size;
+ return S_OK;
+}
+
+const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002;
+
+HRESULT CRepackStreamBase::CloseFile()
+{
+ UInt32 arcIndex = _startIndex + _currentIndex;
+ const CFileItem &fi = _db->Files[arcIndex];
+ _fileIsOpen = false;
+ _currentIndex++;
+ if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc))
+ return S_OK;
+
+ if (_extractCallback)
+ {
+ RINOK(_extractCallback->ReportExtractResult(
+ NEventIndexType::kInArcIndex, arcIndex,
+ NExtract::NOperationResult::kCRCError));
+ }
+ // return S_FALSE;
+ return k_My_HRESULT_CRC_ERROR;
+}
+
+HRESULT CRepackStreamBase::ProcessEmptyFiles()
+{
+ while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
+ {
+ 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)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ if (_fileIsOpen)
+ {
+ 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 (_rem == 0)
+ {
+ RINOK(CloseFile());
+ RINOK(ProcessEmptyFiles());
+ }
+ RINOK(result);
+ if (cur == 0)
+ break;
+ continue;
+ }
+
+ 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
+ {
+ buf = _buf;
+ if (cur > kTempBufSize)
+ cur = kTempBufSize;
+ }
+
+ 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
+ #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
+
+ bool dataAfterEnd_Error;
+ HRESULT Result;
+ CMyComPtr<IInStream> InStream;
+
+ CFolderOutStream2 *FosSpec;
+ CMyComPtr<ISequentialOutStream> Fos;
+
+ UInt64 StartPos;
+ const CFolders *Folders;
+ int FolderIndex;
+
+ // bool send_UnpackSize;
+ // UInt64 UnpackSize;
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+ #endif
+
+ DECL_EXTERNAL_CODECS_LOC_VARS2;
+
+ #ifndef _7ZIP_ST
+ bool MtMode;
+ UInt32 NumThreads;
+ #endif
+
+
+ ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); }
+ virtual void Execute();
+
+ #endif
+};
+
+#ifndef _7ZIP_ST
+
+void CThreadDecoder::Execute()
+{
+ try
+ {
+ #ifndef _NO_CRYPTO
+ bool isEncrypted = false;
+ bool passwordIsDefined = false;
+ UString password;
+ #endif
+
+ dataAfterEnd_Error = false;
+
+ Result = Decoder.Decode(
+ EXTERNAL_CODECS_LOC_VARS
+ InStream,
+ StartPos,
+ *Folders, FolderIndex,
+
+ // send_UnpackSize ? &UnpackSize : NULL,
+ NULL, // unpackSize : FULL unpack
+
+ Fos,
+ NULL, // compressProgress
+
+ NULL // *inStreamMainRes
+ , dataAfterEnd_Error
+
+ _7Z_DECODER_CRYPRO_VARS
+ #ifndef _7ZIP_ST
+ , MtMode, NumThreads,
+ 0 // MemUsage
+ #endif
+
+ );
+ }
+ catch(...)
+ {
+ Result = E_FAIL;
+ }
+
+ /*
+ if (Result == S_OK)
+ Result = FosSpec->CheckFinishedState();
+ */
+ FosSpec->_stream.Release();
+}
+
+#endif
+
+#ifndef _NO_CRYPTO
+
+class CCryptoGetTextPassword:
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+public:
+ UString Password;
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+};
+
+STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)
+{
+ return StringToBstr(Password, password);
+}
+
+#endif
+
+
+static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2)
+{
+ file = inDb.Files[index];
+ file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);
+ file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime);
+ file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime);
+ file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos);
+ file2.AttribDefined = inDb.Attrib.GetItem(index, file2.Attrib);
+ file2.IsAnti = inDb.IsItemAnti(index);
+ // file2.IsAux = inDb.IsItemAux(index);
+}
+
+HRESULT Update(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ IInStream *inStream,
+ const CDbEx *db,
+ const CObjectVector<CUpdateItem> &updateItems,
+ // const CObjectVector<CTreeFolder> &treeFolders,
+ // const CUniqBlocks &secureBlocks,
+ COutArchive &archive,
+ CArchiveDatabaseOut &newDatabase,
+ ISequentialOutStream *seqOutStream,
+ IArchiveUpdateCallback *updateCallback,
+ const CUpdateOptions &options
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getDecoderPassword
+ #endif
+ )
+{
+ UInt64 numSolidFiles = options.NumSolidFiles;
+ 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();
+
+ /*
+ CMyComPtr<IOutStream> outStream;
+ RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
+ if (!outStream)
+ return E_NOTIMPL;
+ */
+
+ UInt64 startBlockSize = db ? db->ArcInfo.StartPosition: 0;
+ if (startBlockSize > 0 && !options.RemoveSfxBlock)
+ {
+ RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));
+ }
+
+ CIntArr fileIndexToUpdateIndexMap;
+ UInt64 complexity = 0;
+ UInt64 inSizeForReduce2 = 0;
+ bool needEncryptedRepack = false;
+
+ CRecordVector<CFilterMode2> filters;
+ CObjectVector<CSolidGroup> groups;
+ bool thereAreRepacks = false;
+
+ bool useFilters = options.UseFilters;
+ if (useFilters)
+ {
+ const CCompressionMethodMode &method = *options.Method;
+
+ FOR_VECTOR (i, method.Methods)
+ if (IsFilterMethod(method.Methods[i].Id))
+ {
+ useFilters = false;
+ break;
+ }
+ }
+
+ if (db)
+ {
+ fileIndexToUpdateIndexMap.Alloc(db->Files.Size());
+ unsigned i;
+
+ for (i = 0; i < db->Files.Size(); i++)
+ fileIndexToUpdateIndexMap[i] = -1;
+
+ for (i = 0; i < updateItems.Size(); i++)
+ {
+ int index = updateItems[i].IndexInArchive;
+ if (index != -1)
+ fileIndexToUpdateIndexMap[(unsigned)index] = 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];
+ if (file.HasStream)
+ {
+ indexInFolder++;
+ int updateIndex = fileIndexToUpdateIndexMap[fi];
+ if (updateIndex >= 0 && !updateItems[updateIndex].NewData)
+ {
+ numCopyItems++;
+ repackSize += file.Size;
+ }
+ }
+ }
+
+ if (numCopyItems == 0)
+ continue;
+
+ CFolderRepack rep;
+ rep.FolderIndex = i;
+ rep.NumCopyFiles = numCopyItems;
+ CFolderEx f;
+ db->ParseFolderEx(i, f);
+
+ const bool isEncrypted = f.IsEncrypted();
+ const bool needCopy = (numCopyItems == numUnpackStreams);
+ const bool extractFilter = (useFilters || needCopy);
+
+ unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter);
+
+ while (groupIndex >= groups.Size())
+ groups.AddNew();
+
+ groups[groupIndex].folderRefs.Add(rep);
+
+ if (needCopy)
+ complexity += db->GetFolderFullPackSize(i);
+ else
+ {
+ thereAreRepacks = true;
+ complexity += repackSize;
+ if (inSizeForReduce2 < repackSize)
+ inSizeForReduce2 = repackSize;
+ if (isEncrypted)
+ needEncryptedRepack = true;
+ }
+ }
+ }
+
+ UInt64 inSizeForReduce = 0;
+ {
+ bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0);
+ FOR_VECTOR (i, updateItems)
+ {
+ const CUpdateItem &ui = updateItems[i];
+ if (ui.NewData)
+ {
+ complexity += ui.Size;
+ if (isSolid)
+ inSizeForReduce += ui.Size;
+ else if (inSizeForReduce < ui.Size)
+ inSizeForReduce = ui.Size;
+ }
+ }
+ }
+
+ if (inSizeForReduce < inSizeForReduce2)
+ inSizeForReduce = inSizeForReduce2;
+
+ RINOK(updateCallback->SetTotal(complexity));
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ #ifndef _7ZIP_ST
+
+ CStreamBinder sb;
+ if (options.MultiThreadMixer)
+ {
+ RINOK(sb.CreateEvents());
+ }
+
+ #endif
+
+ CThreadDecoder threadDecoder(options.MultiThreadMixer);
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer && thereAreRepacks)
+ {
+ #ifdef EXTERNAL_CODECS
+ threadDecoder.__externalCodecs = __externalCodecs;
+ #endif
+ RINOK(threadDecoder.Create());
+ }
+ #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 ----------
+
+ const CCompressionMethodMode &method = *options.Method;
+
+ FOR_VECTOR (i, updateItems)
+ {
+ const CUpdateItem &ui = updateItems[i];
+ if (!ui.NewData || !ui.HasStream())
+ continue;
+
+ CFilterMode2 fm;
+ if (useFilters)
+ {
+ RINOK(analysis.GetFilterGroup(i, ui, fm));
+ }
+ 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;
+ else
+ {
+ if (!getDecoderPassword)
+ return E_NOTIMPL;
+ CMyComBSTR password;
+ RINOK(getDecoderPassword->CryptoGetTextPassword(&password));
+ if (password)
+ getPasswordSpec->Password = password;
+ }
+ }
+
+ #endif
+
+
+ // ---------- Compress ----------
+
+ RINOK(archive.Create(seqOutStream, false));
+ RINOK(archive.SkipPrefixArchiveHeader());
+
+ /*
+ CIntVector treeFolderToArcIndex;
+ treeFolderToArcIndex.Reserve(treeFolders.Size());
+ for (i = 0; i < treeFolders.Size(); i++)
+ treeFolderToArcIndex.Add(-1);
+ // ---------- Write Tree (only AUX dirs) ----------
+ for (i = 1; i < treeFolders.Size(); i++)
+ {
+ const CTreeFolder &treeFolder = treeFolders[i];
+ CFileItem file;
+ CFileItem2 file2;
+ file2.Init();
+ int secureID = 0;
+ if (treeFolder.UpdateItemIndex < 0)
+ {
+ // we can store virtual dir item wuthout attrib, but we want all items have attrib.
+ file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY);
+ file2.IsAux = true;
+ }
+ else
+ {
+ const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex];
+ // if item is not dir, then it's parent for alt streams.
+ // we will write such items later
+ if (!ui.IsDir)
+ continue;
+ secureID = ui.SecureIndex;
+ if (ui.NewProps)
+ UpdateItem_To_FileItem(ui, file, file2);
+ else
+ GetFile(*db, ui.IndexInArchive, file, file2);
+ }
+ file.Size = 0;
+ file.HasStream = false;
+ file.IsDir = true;
+ file.Parent = treeFolder.Parent;
+
+ treeFolderToArcIndex[i] = newDatabase.Files.Size();
+ newDatabase.AddFile(file, file2, treeFolder.Name);
+
+ if (totalSecureDataSize != 0)
+ newDatabase.SecureIDs.Add(secureID);
+ }
+ */
+
+ {
+ /* ---------- Write non-AUX dirs and Empty files ---------- */
+ CUIntVector emptyRefs;
+
+ unsigned i;
+
+ for (i = 0; i < updateItems.Size(); i++)
+ {
+ const CUpdateItem &ui = updateItems[i];
+ if (ui.NewData)
+ {
+ if (ui.HasStream())
+ continue;
+ }
+ else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)
+ continue;
+ /*
+ if (ui.TreeFolderIndex >= 0)
+ continue;
+ */
+ emptyRefs.Add(i);
+ }
+
+ emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
+
+ for (i = 0; i < emptyRefs.Size(); i++)
+ {
+ const CUpdateItem &ui = updateItems[emptyRefs[i]];
+ CFileItem file;
+ CFileItem2 file2;
+ UString name;
+ if (ui.NewProps)
+ {
+ UpdateItem_To_FileItem(ui, file, file2);
+ file.CrcDefined = false;
+ name = ui.Name;
+ }
+ else
+ {
+ GetFile(*db, ui.IndexInArchive, file, file2);
+ db->GetPath(ui.IndexInArchive, name);
+ }
+
+ /*
+ if (totalSecureDataSize != 0)
+ newDatabase.SecureIDs.Add(ui.SecureIndex);
+ file.Parent = ui.ParentFolderIndex;
+ */
+ newDatabase.AddFile(file, file2, name);
+ }
+ }
+
+ lps->ProgressOffset = 0;
+
+ {
+ // ---------- 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;
+ {
+ HRESULT res = MakeExeMethod(method, filterMode,
+ #ifdef _7ZIP_ST
+ false
+ #else
+ options.MaxFilter && options.MultiThreadMixer
+ #endif
+ );
+
+ RINOK(res);
+ }
+
+ if (filterMode.Encrypted)
+ {
+ if (!method.PasswordIsDefined)
+ {
+ #ifndef _NO_CRYPTO
+ if (getPasswordSpec)
+ method.Password = getPasswordSpec->Password;
+ #endif
+ method.PasswordIsDefined = true;
+ }
+ }
+ else
+ {
+ method.PasswordIsDefined = false;
+ method.Password.Empty();
+ }
+
+ CEncoder encoder(method);
+
+ // ---------- Repack and copy old solid blocks ----------
+
+ const CSolidGroup &group = groups[filterMode.GroupIndex];
+
+ FOR_VECTOR(folderRefIndex, group.folderRefs)
+ {
+ const CFolderRepack &rep = group.folderRefs[folderRefIndex];
+
+ unsigned folderIndex = rep.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));
+ lps->ProgressOffset += packSize;
+
+ CFolder &folder = newDatabase.Folders.AddNew();
+ db->ParseFolderInfo(folderIndex, folder);
+ CNum startIndex = db->FoStartPackStreamIndex[folderIndex];
+ 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]);
+ }
+
+ 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 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;
+ 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;
+ {
+ #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;
+ bool dataAfterEnd_Error = false;
+
+ 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
+ , dataAfterEnd_Error
+
+ _7Z_DECODER_CRYPRO_VARS
+ #ifndef _7ZIP_ST
+ , false // mtMode
+ , 1 // numThreads
+ , 0 // memUsage
+ #endif
+ );
+
+ 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
+ }
+
+ curUnpackSize = sizeToEncode;
+
+ HRESULT encodeRes = encoder.Encode(
+ EXTERNAL_CODECS_LOC_VARS
+ inStreamSizeCount,
+ // NULL,
+ &inSizeForReduce,
+ newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize,
+ archive.SeqStream, newDatabase.PackSizes, progress);
+
+ if (encodeRes == k_My_HRESULT_CRC_ERROR)
+ return E_FAIL;
+
+ #ifndef _7ZIP_ST
+ if (options.MultiThreadMixer)
+ {
+ // 16.00: hang was fixed : for case if decoding was not finished.
+ // We close CBinderInStream and it calls CStreamBinder::CloseRead()
+ inStreamSizeCount.Release();
+ sbInStream.Release();
+
+ threadDecoder.WaitExecuteFinish();
+
+ HRESULT decodeRes = threadDecoder.Result;
+ // if (res == k_My_HRESULT_CRC_ERROR)
+ if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error)
+ {
+ if (extractCallback)
+ {
+ RINOK(extractCallback->ReportExtractResult(
+ NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],
+ // NEventIndexType::kBlockIndex, (UInt32)folderIndex,
+ (decodeRes != S_OK ?
+ NExtract::NOperationResult::kDataError :
+ NExtract::NOperationResult::kDataAfterEnd)));
+ }
+ if (decodeRes != S_OK)
+ 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];
+ lps->InSize += curUnpackSize;
+ }
+
+ newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);
+
+ CNum indexInFolder = 0;
+ for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
+ {
+ if (db->Files[fi].HasStream)
+ {
+ indexInFolder++;
+ int updateIndex = fileIndexToUpdateIndexMap[fi];
+ if (updateIndex >= 0)
+ {
+ const CUpdateItem &ui = updateItems[updateIndex];
+ if (ui.NewData)
+ continue;
+
+ UString name;
+ CFileItem file;
+ CFileItem2 file2;
+ GetFile(*db, fi, file, file2);
+
+ if (ui.NewProps)
+ {
+ UpdateItem_To_FileItem2(ui, file2);
+ file.IsDir = ui.IsDir;
+ name = ui.Name;
+ }
+ else
+ db->GetPath(fi, name);
+
+ /*
+ file.Parent = ui.ParentFolderIndex;
+ if (ui.TreeFolderIndex >= 0)
+ treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();
+ if (totalSecureDataSize != 0)
+ newDatabase.SecureIDs.Add(ui.SecureIndex);
+ */
+ newDatabase.AddFile(file, file2, name);
+ }
+ }
+ }
+ }
+
+
+ // ---------- Compress files to new solid blocks ----------
+
+ unsigned numFiles = group.Indices.Size();
+ if (numFiles == 0)
+ continue;
+ CRecordVector<CRefItem> refItems;
+ refItems.ClearAndSetSize(numFiles);
+ // bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1
+ bool sortByType = options.UseTypeSorting;
+
+ unsigned i;
+
+ for (i = 0; i < numFiles; i++)
+ refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
+
+ CSortParam sortParam;
+ // sortParam.TreeFolders = &treeFolders;
+ sortParam.SortByType = sortByType;
+ refItems.Sort(CompareUpdateItems, (void *)&sortParam);
+
+ CObjArray<UInt32> indices(numFiles);
+
+ for (i = 0; i < numFiles; i++)
+ {
+ UInt32 index = refItems[i].Index;
+ indices[i] = index;
+ /*
+ const CUpdateItem &ui = updateItems[index];
+ CFileItem file;
+ if (ui.NewProps)
+ UpdateItem_To_FileItem(ui, file);
+ else
+ file = db.Files[ui.IndexInArchive];
+ if (file.IsAnti || file.IsDir)
+ return E_FAIL;
+ newDatabase.Files.Add(file);
+ */
+ }
+
+ for (i = 0; i < numFiles;)
+ {
+ UInt64 totalSize = 0;
+ 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;
+ if (totalSize > options.NumSolidBytes)
+ break;
+ if (options.SolidExtension)
+ {
+ 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 (!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);
+
+ unsigned startPackIndex = newDatabase.PackSizes.Size();
+ UInt64 curFolderUnpackSize = totalSize;
+ // curFolderUnpackSize = (UInt64)(Int64)-1;
+
+ RINOK(encoder.Encode(
+ EXTERNAL_CODECS_LOC_VARS
+ 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];
+
+ lps->InSize += curFolderUnpackSize;
+ // for ()
+ // newDatabase.PackCRCsDefined.Add(false);
+ // newDatabase.PackCRCs.Add(0);
+
+ CNum numUnpackStreams = 0;
+ UInt64 skippedSize = 0;
+
+ for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++)
+ {
+ const CUpdateItem &ui = updateItems[indices[i + subIndex]];
+ CFileItem file;
+ CFileItem2 file2;
+ UString name;
+ if (ui.NewProps)
+ {
+ UpdateItem_To_FileItem(ui, file, file2);
+ name = ui.Name;
+ }
+ else
+ {
+ GetFile(*db, ui.IndexInArchive, file, file2);
+ db->GetPath(ui.IndexInArchive, name);
+ }
+ if (file2.IsAnti || file.IsDir)
+ return E_FAIL;
+
+ /*
+ CFileItem &file = newDatabase.Files[
+ startFileIndexInDatabase + i + subIndex];
+ */
+ if (!inStreamSpec->Processed[subIndex])
+ {
+ skippedSize += ui.Size;
+ continue;
+ // file.Name += ".locked";
+ }
+
+ file.Crc = inStreamSpec->CRCs[subIndex];
+ file.Size = inStreamSpec->Sizes[subIndex];
+
+ // if (file.Size >= 0) // test purposes
+ if (file.Size != 0)
+ {
+ file.CrcDefined = true;
+ file.HasStream = true;
+ numUnpackStreams++;
+ }
+ else
+ {
+ file.CrcDefined = false;
+ file.HasStream = false;
+ }
+
+ /*
+ file.Parent = ui.ParentFolderIndex;
+ if (ui.TreeFolderIndex >= 0)
+ treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();
+ if (totalSecureDataSize != 0)
+ newDatabase.SecureIDs.Add(ui.SecureIndex);
+ */
+ 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));
+ }
+ }
+ }
+
+ RINOK(lps->SetCur());
+
+ /*
+ fileIndexToUpdateIndexMap.ClearAndFree();
+ groups.ClearAndFree();
+ */
+
+ /*
+ for (i = 0; i < newDatabase.Files.Size(); i++)
+ {
+ CFileItem &file = newDatabase.Files[i];
+ file.Parent = treeFolderToArcIndex[file.Parent];
+ }
+
+ if (totalSecureDataSize != 0)
+ {
+ newDatabase.SecureBuf.SetCapacity(totalSecureDataSize);
+ size_t pos = 0;
+ newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size());
+ for (i = 0; i < secureBlocks.Sorted.Size(); i++)
+ {
+ const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];
+ size_t size = buf.GetCapacity();
+ 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/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.h
new file mode 100644
index 0000000000..06a0b05fb0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.h
@@ -0,0 +1,139 @@
+// 7zUpdate.h
+
+#ifndef __7Z_UPDATE_H
+#define __7Z_UPDATE_H
+
+#include "../IArchive.h"
+
+// #include "../../Common/UniqBlocks.h"
+
+#include "7zCompressionMode.h"
+#include "7zIn.h"
+#include "7zOut.h"
+
+namespace NArchive {
+namespace N7z {
+
+/*
+struct CTreeFolder
+{
+ UString Name;
+ int Parent;
+ CIntVector SubFolders;
+ int UpdateItemIndex;
+ int SortIndex;
+ int SortIndexEnd;
+
+ CTreeFolder(): UpdateItemIndex(-1) {}
+};
+*/
+
+struct CUpdateItem
+{
+ int IndexInArchive;
+ int IndexInClient;
+
+ UInt64 CTime;
+ UInt64 ATime;
+ UInt64 MTime;
+
+ UInt64 Size;
+ UString Name;
+ /*
+ bool IsAltStream;
+ int ParentFolderIndex;
+ int TreeFolderIndex;
+ */
+
+ // that code is not used in 9.26
+ // int ParentSortIndex;
+ // int ParentSortIndexEnd;
+
+ UInt32 Attrib;
+
+ bool NewData;
+ bool NewProps;
+
+ bool IsAnti;
+ bool IsDir;
+
+ bool AttribDefined;
+ bool CTimeDefined;
+ bool ATimeDefined;
+ bool MTimeDefined;
+
+ // 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),
+ // IsAltStream(false),
+ IsAnti(false),
+ IsDir(false),
+ AttribDefined(false),
+ CTimeDefined(false),
+ ATimeDefined(false),
+ MTimeDefined(false)
+ // SecureIndex(0)
+ {}
+ void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }
+
+ // unsigned GetExtensionPos() const;
+ // UString GetExtension() const;
+};
+
+struct CUpdateOptions
+{
+ const CCompressionMethodMode *Method;
+ const CCompressionMethodMode *HeaderMethod;
+ bool UseFilters; // use additional filters for some files
+ bool MaxFilter; // use BCJ2 filter instead of BCJ
+ int AnalysisLevel;
+
+ CHeaderOptions HeaderOptions;
+
+ UInt64 NumSolidFiles;
+ UInt64 NumSolidBytes;
+ bool SolidExtension;
+
+ bool UseTypeSorting;
+
+ bool RemoveSfxBlock;
+ bool MultiThreadMixer;
+
+ CUpdateOptions():
+ Method(NULL),
+ HeaderMethod(NULL),
+ UseFilters(false),
+ MaxFilter(false),
+ AnalysisLevel(-1),
+ NumSolidFiles((UInt64)(Int64)(-1)),
+ NumSolidBytes((UInt64)(Int64)(-1)),
+ SolidExtension(false),
+ UseTypeSorting(true),
+ RemoveSfxBlock(false),
+ MultiThreadMixer(true)
+ {}
+};
+
+HRESULT Update(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ IInStream *inStream,
+ const CDbEx *db,
+ const CObjectVector<CUpdateItem> &updateItems,
+ // const CObjectVector<CTreeFolder> &treeFolders, // treeFolders[0] is root
+ // const CUniqBlocks &secureBlocks,
+ COutArchive &archive,
+ CArchiveDatabaseOut &newDatabase,
+ ISequentialOutStream *seqOutStream,
+ IArchiveUpdateCallback *updateCallback,
+ const CUpdateOptions &options
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getDecoderPassword
+ #endif
+ );
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Archive.def b/other-licenses/7zstub/src/CPP/7zip/Archive/Archive.def
new file mode 100644
index 0000000000..a3fe6ddaaf
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Archive.def
@@ -0,0 +1,12 @@
+EXPORTS
+ CreateObject PRIVATE
+
+ GetHandlerProperty PRIVATE
+ GetNumberOfFormats PRIVATE
+ GetHandlerProperty2 PRIVATE
+ GetIsArc PRIVATE
+
+ SetCodecs PRIVATE
+
+ SetLargePageMode PRIVATE
+ SetCaseSensitive PRIVATE
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Archive2.def b/other-licenses/7zstub/src/CPP/7zip/Archive/Archive2.def
new file mode 100644
index 0000000000..de744b5f74
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Archive2.def
@@ -0,0 +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
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/ArchiveExports.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/ArchiveExports.cpp
new file mode 100644
index 0000000000..94f2fff007
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/ArchiveExports.cpp
@@ -0,0 +1,151 @@
+// ArchiveExports.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/7zVersion.h"
+
+#include "../../Common/ComTry.h"
+
+#include "../../Windows/PropVariant.h"
+
+#include "../Common/RegisterArc.h"
+
+static const unsigned kNumArcsMax = 64;
+static unsigned g_NumArcs = 0;
+static unsigned g_DefaultArcIndex = 0;
+static const CArcInfo *g_Arcs[kNumArcsMax];
+
+void RegisterArc(const CArcInfo *arcInfo) throw()
+{
+ if (g_NumArcs < kNumArcsMax)
+ {
+ const char *p = arcInfo->Name;
+ if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
+ g_DefaultArcIndex = g_NumArcs;
+ g_Arcs[g_NumArcs++] = arcInfo;
+ }
+}
+
+DEFINE_GUID(CLSID_CArchiveHandler,
+ 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 SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)
+{
+ if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+}
+
+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
+{
+ return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
+}
+
+int FindFormatCalssId(const GUID *clsid)
+{
+ GUID cls = *clsid;
+ CLS_ARC_ID_ITEM(cls) = 0;
+ if (cls != CLSID_CArchiveHandler)
+ return -1;
+ Byte id = CLS_ARC_ID_ITEM(*clsid);
+ for (unsigned i = 0; i < g_NumArcs; i++)
+ if (g_Arcs[i]->Id == id)
+ return (int)i;
+ return -1;
+}
+
+STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
+{
+ COM_TRY_BEGIN
+ {
+ int needIn = (*iid == IID_IInArchive);
+ int needOut = (*iid == IID_IOutArchive);
+ if (!needIn && !needOut)
+ return E_NOINTERFACE;
+ int formatIndex = FindFormatCalssId(clsid);
+ if (formatIndex < 0)
+ return CLASS_E_CLASSNOTAVAILABLE;
+
+ const CArcInfo &arc = *g_Arcs[formatIndex];
+ if (needIn)
+ {
+ *outObject = arc.CreateInArchive();
+ ((IInArchive *)*outObject)->AddRef();
+ }
+ else
+ {
+ if (!arc.CreateOutArchive)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ *outObject = arc.CreateOutArchive();
+ ((IOutArchive *)*outObject)->AddRef();
+ }
+ }
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::PropVariant_Clear(value);
+ if (formatIndex >= g_NumArcs)
+ return E_INVALIDARG;
+ const CArcInfo &arc = *g_Arcs[formatIndex];
+ NWindows::NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case NArchive::NHandlerPropID::kName: prop = arc.Name; break;
+ case NArchive::NHandlerPropID::kClassID:
+ {
+ GUID clsId = CLSID_CArchiveHandler;
+ CLS_ARC_ID_ITEM(clsId) = arc.Id;
+ return SetPropGUID(clsId, value);
+ }
+ case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
+ case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break;
+ case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break;
+ case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break;
+ case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break;
+ case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break;
+ case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break;
+ case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break;
+ // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
+
+ case NArchive::NHandlerPropID::kSignature:
+ if (arc.SignatureSize != 0 && !arc.IsMultiSignature())
+ return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
+ break;
+ case NArchive::NHandlerPropID::kMultiSignature:
+ if (arc.SignatureSize != 0 && arc.IsMultiSignature())
+ return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);
+ break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
+}
+
+STDAPI GetNumberOfFormats(UINT32 *numFormats)
+{
+ *numFormats = g_NumArcs;
+ return S_OK;
+}
+
+STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)
+{
+ *isArc = NULL;
+ if (formatIndex >= g_NumArcs)
+ return E_INVALIDARG;
+ *isArc = g_Arcs[formatIndex]->IsArc;
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.cpp
new file mode 100644
index 0000000000..d4d9949502
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -0,0 +1,1124 @@
+// CoderMixer2.cpp
+
+#include "StdAfx.h"
+
+#include "CoderMixer2.h"
+
+#ifdef USE_MIXER_ST
+
+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;
+}
+
+
+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;
+}
+
+STDMETHODIMP COutStreamCalcSize::OutStreamFinish()
+{
+ HRESULT result = S_OK;
+ if (_stream)
+ {
+ CMyComPtr<IOutStreamFinish> outStreamFinish;
+ _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish);
+ if (outStreamFinish)
+ result = outStreamFinish->OutStreamFinish();
+ }
+ return result;
+}
+
+#endif
+
+
+
+
+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;
+}
+
+
+HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const
+{
+ if (Coder)
+ {
+ if (PackSizePointers.IsEmpty() || !PackSizePointers[0])
+ return S_OK;
+ CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
+ Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);
+ // if (!getInStreamProcessedSize) return E_FAIL;
+ if (getInStreamProcessedSize)
+ {
+ UInt64 processed;
+ RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed));
+ if (processed != (UInt64)(Int64)-1)
+ {
+ const UInt64 size = PackSizes[0];
+ if (processed < size && Finish)
+ dataAfterEnd_Error = true;
+ if (processed > size)
+ {
+ // InternalPackSizeError = true;
+ // return S_FALSE;
+ }
+ }
+ }
+ }
+ else if (Coder2)
+ {
+ CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2;
+ Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2);
+ FOR_VECTOR (i, PackSizePointers)
+ {
+ if (!PackSizePointers[i])
+ continue;
+ UInt64 processed;
+ RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed));
+ if (processed != (UInt64)(Int64)-1)
+ {
+ const UInt64 size = PackSizes[i];
+ if (processed < size && Finish)
+ dataAfterEnd_Error = true;
+ else if (processed > size)
+ {
+ // InternalPackSizeError = true;
+ // return S_FALSE;
+ }
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+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++)
+ {
+ 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();
+}
+
+bool CBindInfo::CalcMapsAndCheck()
+{
+ ClearMaps();
+
+ UInt32 numStreams = 0;
+
+ if (Coders.Size() == 0)
+ return false;
+ if (Coders.Size() - 1 != Bonds.Size())
+ return false;
+
+ FOR_VECTOR(i, Coders)
+ {
+ 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, bool finish)
+{
+ Finish = finish;
+
+ 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;
+
+ /*
+ 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;
+
+ 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)
+ {
+ if (_bi.UnpackCoder == streamIndex)
+ index = 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<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,
+ bool &dataAfterEnd_Error)
+{
+ // InternalPackSizeError = false;
+ dataAfterEnd_Error = false;
+
+ _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;
+
+ if (res != S_OK)
+ return res;
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */));
+ }
+
+ return S_OK;
+}
+
+
+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 CMixerST::GetBondStreamSize(unsigned bondIndex) const
+{
+ 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 = 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)
+ {
+ RINOK(_streamBinders.AddNew().CreateEvents());
+ }
+ 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 (;;)
+ {
+ 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 CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
+{
+ 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++)
+ {
+ 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)
+ {
+ 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,
+ bool &dataAfterEnd_Error)
+{
+ // InternalPackSizeError = false;
+ dataAfterEnd_Error = false;
+
+ Init(inStreams, outStreams);
+
+ unsigned i;
+ for (i = 0; i < _coders.Size(); i++)
+ if (i != MainCoderIndex)
+ {
+ 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;
+ }
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */));
+ }
+
+ return S_OK;
+}
+
+UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
+{
+ return _streamBinders[bondIndex].ProcessedSize;
+}
+
+#endif
+
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.h
new file mode 100644
index 0000000000..4bd6418351
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -0,0 +1,447 @@
+// CoderMixer2.h
+
+#ifndef __CODER_MIXER2_H
+#define __CODER_MIXER2_H
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyVector.h"
+
+#include "../../ICoder.h"
+
+#include "../../Common/CreateCoder.h"
+
+#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 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 NumStreams;
+};
+
+
+struct CBindInfo
+{
+ CRecordVector<CCoderStreamsInfo> Coders;
+ CRecordVector<CBond> Bonds;
+ CRecordVector<UInt32> PackStreams;
+ unsigned UnpackCoder;
+
+ unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }
+
+ int FindBond_for_PackStream(UInt32 packStream) const
+ {
+ FOR_VECTOR (i, Bonds)
+ if (Bonds[i].PackIndex == packStream)
+ return i;
+ return -1;
+ }
+
+ int FindBond_for_UnpackStream(UInt32 unpackStream) const
+ {
+ FOR_VECTOR (i, Bonds)
+ if (Bonds[i].UnpackIndex == unpackStream)
+ return i;
+ return -1;
+ }
+
+ bool SetUnpackCoder()
+ {
+ bool isOk = false;
+ FOR_VECTOR(i, Coders)
+ {
+ if (FindBond_for_UnpackStream(i) < 0)
+ {
+ if (isOk)
+ return false;
+ UnpackCoder = i;
+ isOk = true;
+ }
+ }
+ return isOk;
+ }
+
+ bool IsStream_in_PackStreams(UInt32 streamIndex) const
+ {
+ return FindStream_in_PackStreams(streamIndex) >= 0;
+ }
+
+ int FindStream_in_PackStreams(UInt32 streamIndex) const
+ {
+ FOR_VECTOR(i, PackStreams)
+ if (PackStreams[i] == streamIndex)
+ return i;
+ return -1;
+ }
+
+
+ // 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].NumStreams;
+ return streamIndex;
+ }
+
+ // ---------- Maps Section ----------
+
+ CRecordVector<UInt32> Coder_to_Stream;
+ CRecordVector<UInt32> Stream_to_Coder;
+
+ void ClearMaps();
+ bool CalcMapsAndCheck();
+
+ // ---------- End of Maps Section ----------
+
+ void Clear()
+ {
+ 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];
+ }
+};
+
+
+
+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;
+
+ bool Finish;
+
+ CCoder(): Finish(false) {}
+
+ void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish);
+
+ HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const;
+
+ IUnknown *GetUnknown() const
+ {
+ return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
+ }
+
+ HRESULT QueryInterface(REFGUID iid, void** pp) const
+ {
+ 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;
+
+ // bool InternalPackSizeError;
+
+ CMixer(bool encodeMode):
+ EncodeMode(encodeMode),
+ MainCoderIndex(0)
+ // , InternalPackSizeError(false)
+ {}
+
+ /*
+ Sequence of calling:
+
+ SetBindInfo();
+ for each coder
+ AddCoder();
+ SelectMainCoder();
+
+ for each file
+ {
+ ReInit()
+ for each coder
+ SetCoderInfo();
+ Code();
+ }
+ */
+
+ 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, bool finish) = 0;
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error) = 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);
+};
+
+
+
+
+#ifdef USE_MIXER_ST
+
+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 FinishStream(UInt32 streamIndex);
+ HRESULT FinishCoder(UInt32 coderIndex);
+
+public:
+ CObjectVector<CCoderST> _coders;
+
+ CObjectVector<CStBinderStream> _binderStreams;
+
+ 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, bool finish)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error);
+ 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()
+ {
+ 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 CMixerMT:
+ public IUnknown,
+ public CMixer,
+ public CMyUnknownImp
+{
+ CObjectVector<CStreamBinder> _streamBinders;
+
+ HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
+ HRESULT ReturnIfError(HRESULT code);
+
+public:
+ 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, bool finish)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
+ virtual HRESULT Code(
+ ISequentialInStream * const *inStreams,
+ ISequentialOutStream * const *outStreams,
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error);
+ virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
+
+ CMixerMT(bool encodeMode): CMixer(encodeMode) {}
+};
+
+#endif
+
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.cpp
new file mode 100644
index 0000000000..c7d45e7f9e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.cpp
@@ -0,0 +1,17 @@
+// DummyOutStream.cpp
+
+#include "StdAfx.h"
+
+#include "DummyOutStream.h"
+
+STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize = size;
+ HRESULT res = S_OK;
+ if (_stream)
+ res = _stream->Write(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.h
new file mode 100644
index 0000000000..30e84c55da
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.h
@@ -0,0 +1,25 @@
+// DummyOutStream.h
+
+#ifndef __DUMMY_OUT_STREAM_H
+#define __DUMMY_OUT_STREAM_H
+
+#include "../../../Common/MyCom.h"
+
+#include "../../IStream.h"
+
+class CDummyOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+public:
+ void SetStream(ISequentialOutStream *outStream) { _stream = outStream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init() { _size = 0; }
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ UInt64 GetSize() const { return _size; }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.cpp
new file mode 100644
index 0000000000..41762d9004
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -0,0 +1,232 @@
+// HandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/StringToInt.h"
+
+#include "../Common/ParseProperties.h"
+
+#include "HandlerOut.h"
+
+namespace NArchive {
+
+bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res)
+{
+ if (*s == 0)
+ {
+ switch (prop.vt)
+ {
+ case VT_UI4: res = prop.ulVal; return true;
+ case VT_UI8: res = prop.uhVal.QuadPart; return true;
+ case VT_BSTR:
+ s = prop.bstrVal;
+ break;
+ default: return false;
+ }
+ }
+ else if (prop.vt != VT_EMPTY)
+ return false;
+
+ const wchar_t *end;
+ UInt64 v = ConvertStringToUInt64(s, &end);
+ if (s == end)
+ return false;
+ wchar_t c = *end;
+ if (c == 0)
+ {
+ res = v;
+ return true;
+ }
+ if (end[1] != 0)
+ return false;
+
+ if (c == '%')
+ {
+ res = percentsBase / 100 * v;
+ return true;
+ }
+
+ unsigned numBits;
+ switch (MyCharLower_Ascii(c))
+ {
+ case 'b': numBits = 0; break;
+ case 'k': numBits = 10; break;
+ case 'm': numBits = 20; break;
+ case 'g': numBits = 30; break;
+ case 't': numBits = 40; break;
+ default: return false;
+ }
+ UInt64 val2 = v << numBits;
+ if ((val2 >> numBits) != v)
+ return false;
+ res = val2;
+ return true;
+}
+
+bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)
+{
+ hres = S_OK;
+
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
+ {
+ #ifndef _7ZIP_ST
+ hres = ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads);
+ #endif
+ return true;
+ }
+
+ if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
+ {
+ if (!ParseSizeString(name.Ptr(6), value, _memAvail, _memUsage))
+ hres = E_INVALIDARG;
+ return true;
+ }
+
+ return false;
+}
+
+
+#ifndef EXTRACT_ONLY
+
+static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
+{
+ if (m.FindProp(propID) < 0)
+ m.AddProp32(propID, value);
+}
+
+void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
+{
+ UInt32 level = _level;
+ if (level != (UInt32)(Int32)-1)
+ SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
+}
+
+#ifndef _7ZIP_ST
+void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads)
+{
+ SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
+}
+#endif
+
+void CMultiMethodProps::InitMulti()
+{
+ _level = (UInt32)(Int32)-1;
+ _analysisLevel = -1;
+ _crcSize = 4;
+ _autoFilter = true;
+}
+
+void CMultiMethodProps::Init()
+{
+ InitCommon();
+ InitMulti();
+ _methods.Clear();
+ _filterMethod.Clear();
+}
+
+
+HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
+{
+ UString name = nameSpec;
+ name.MakeLower_Ascii();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ if (name[0] == 'x')
+ {
+ name.Delete(0);
+ _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.IsPrefixedBy_Ascii_NoCase("crc"))
+ {
+ name.Delete(0, 3);
+ _crcSize = 4;
+ return ParsePropToUInt32(name, value, _crcSize);
+ }
+
+ {
+ HRESULT hres;
+ if (SetCommonProperty(name, value, hres))
+ return hres;
+ }
+
+ UInt32 number;
+ unsigned index = ParseStringToUInt32(name, number);
+ UString realName = name.Ptr(index);
+ if (index == 0)
+ {
+ if (name.IsEqualTo("f"))
+ {
+ HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
+ if (res == S_OK)
+ return res;
+ if (value.vt != VT_BSTR)
+ return E_INVALIDARG;
+ return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);
+ }
+ number = 0;
+ }
+ if (number > 64)
+ return E_FAIL;
+ for (int j = _methods.Size(); j <= (int)number; j++)
+ _methods.Add(COneMethodInfo());
+ return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
+}
+
+
+
+void CSingleMethodProps::Init()
+{
+ InitCommon();
+ InitSingle();
+ Clear();
+}
+
+
+HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
+{
+ Init();
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ UString name = names[i];
+ name.MakeLower_Ascii();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+ const PROPVARIANT &value = values[i];
+ if (name[0] == L'x')
+ {
+ UInt32 a = 9;
+ RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
+ _level = a;
+ AddProp_Level(a);
+ continue;
+ }
+ {
+ HRESULT hres;
+ if (SetCommonProperty(name, value, hres))
+ {
+ RINOK(hres)
+ continue;
+ }
+ }
+ RINOK(ParseMethodFromPROPVARIANT(names[i], value));
+ }
+
+ return S_OK;
+}
+
+#endif
+
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.h
new file mode 100644
index 0000000000..90b000ac8b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.h
@@ -0,0 +1,110 @@
+// HandlerOut.h
+
+#ifndef __HANDLER_OUT_H
+#define __HANDLER_OUT_H
+
+#include "../../../Windows/System.h"
+
+#include "../../Common/MethodProps.h"
+
+namespace NArchive {
+
+bool ParseSizeString(const wchar_t *name, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res);
+
+class CCommonMethodProps
+{
+protected:
+ void InitCommon()
+ {
+ #ifndef _7ZIP_ST
+ _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ #endif
+
+ UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28;
+ _memAvail = memAvail;
+ _memUsage = memAvail;
+ if (NWindows::NSystem::GetRamSize(memAvail))
+ {
+ _memAvail = memAvail;
+ _memUsage = memAvail / 32 * 17;
+ }
+ }
+
+public:
+ #ifndef _7ZIP_ST
+ UInt32 _numThreads;
+ UInt32 _numProcessors;
+ #endif
+
+ UInt64 _memUsage;
+ UInt64 _memAvail;
+
+ bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres);
+
+ CCommonMethodProps() { InitCommon(); }
+};
+
+
+#ifndef EXTRACT_ONLY
+
+class CMultiMethodProps: public CCommonMethodProps
+{
+ UInt32 _level;
+ int _analysisLevel;
+
+ void InitMulti();
+public:
+ UInt32 _crcSize;
+ CObjectVector<COneMethodInfo> _methods;
+ COneMethodInfo _filterMethod;
+ bool _autoFilter;
+
+
+ void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const;
+
+ #ifndef _7ZIP_ST
+ static void SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads);
+ #endif
+
+
+ unsigned GetNumEmptyMethods() const
+ {
+ unsigned i;
+ for (i = 0; i < _methods.Size(); i++)
+ if (!_methods[i].IsEmpty())
+ break;
+ return i;
+ }
+
+ int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
+ int GetAnalysisLevel() const { return _analysisLevel; }
+
+ void Init();
+ CMultiMethodProps() { InitMulti(); }
+
+ HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
+};
+
+
+class CSingleMethodProps: public COneMethodInfo, public CCommonMethodProps
+{
+ UInt32 _level;
+
+ void InitSingle()
+ {
+ _level = (UInt32)(Int32)-1;
+ }
+
+public:
+ void Init();
+ CSingleMethodProps() { InitSingle(); }
+
+ int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
+ HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
+};
+
+#endif
+
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
new file mode 100644
index 0000000000..cddc083d64
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
@@ -0,0 +1,46 @@
+// InStreamWithCRC.cpp
+
+#include "StdAfx.h"
+
+#include "InStreamWithCRC.h"
+
+STDMETHODIMP CSequentialInStreamWithCRC::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;
+ _crc = CrcUpdate(_crc, data, realProcessed);
+ if (processedSize)
+ *processedSize = realProcessed;
+ return result;
+}
+
+STDMETHODIMP CInStreamWithCRC::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;
+ */
+ _crc = CrcUpdate(_crc, data, realProcessed);
+ if (processedSize)
+ *processedSize = realProcessed;
+ return result;
+}
+
+STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ if (seekOrigin != STREAM_SEEK_SET || offset != 0)
+ return E_FAIL;
+ _size = 0;
+ _crc = CRC_INIT_VAL;
+ return _stream->Seek(offset, seekOrigin, newPosition);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.h
new file mode 100644
index 0000000000..1a4b2c907e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.h
@@ -0,0 +1,67 @@
+// InStreamWithCRC.h
+
+#ifndef __IN_STREAM_WITH_CRC_H
+#define __IN_STREAM_WITH_CRC_H
+
+#include "../../../../C/7zCrc.h"
+
+#include "../../../Common/MyCom.h"
+
+#include "../../IStream.h"
+
+class CSequentialInStreamWithCRC:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _size;
+ UInt32 _crc;
+ bool _wasFinished;
+public:
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ _wasFinished = false;
+ _crc = CRC_INIT_VAL;
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+ UInt64 GetSize() const { return _size; }
+ bool WasFinished() const { return _wasFinished; }
+};
+
+class CInStreamWithCRC:
+ public IInStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+private:
+ CMyComPtr<IInStream> _stream;
+ UInt64 _size;
+ UInt32 _crc;
+ // bool _wasFinished;
+public:
+ void SetStream(IInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ // _wasFinished = false;
+ _crc = CRC_INIT_VAL;
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+ UInt64 GetSize() const { return _size; }
+ // bool WasFinished() const { return _wasFinished; }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.cpp
new file mode 100644
index 0000000000..e0c35a9b02
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.cpp
@@ -0,0 +1,88 @@
+// Archive/Common/ItemNameUtils.cpp
+
+#include "StdAfx.h"
+
+#include "ItemNameUtils.h"
+
+namespace NArchive {
+namespace NItemName {
+
+static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR;
+static const wchar_t kUnixPathSepar = L'/';
+
+void ReplaceSlashes_OsToUnix
+#if WCHAR_PATH_SEPARATOR != L'/'
+ (UString &name)
+ {
+ name.Replace(kOsPathSepar, kUnixPathSepar);
+ }
+#else
+ (UString &) {}
+#endif
+
+
+UString GetOsPath(const UString &name)
+{
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ UString newName = name;
+ newName.Replace(kUnixPathSepar, kOsPathSepar);
+ return newName;
+ #else
+ return name;
+ #endif
+}
+
+
+UString GetOsPath_Remove_TailSlash(const UString &name)
+{
+ if (name.IsEmpty())
+ return UString();
+ UString newName = GetOsPath(name);
+ if (newName.Back() == kOsPathSepar)
+ newName.DeleteBack();
+ return newName;
+}
+
+
+void ReplaceToOsSlashes_Remove_TailSlash(UString &name)
+{
+ if (!name.IsEmpty())
+ {
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ name.Replace(kUnixPathSepar, kOsPathSepar);
+ #endif
+
+ if (name.Back() == kOsPathSepar)
+ name.DeleteBack();
+ }
+}
+
+
+bool HasTailSlash(const AString &name, UINT
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ codePage
+ #endif
+ )
+{
+ if (name.IsEmpty())
+ return false;
+ char c =
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0);
+ #else
+ name.Back();
+ #endif
+ return (c == '/');
+}
+
+
+#ifndef _WIN32
+UString WinPathToOsPath(const UString &name)
+{
+ UString newName = name;
+ newName.Replace(L'\\', WCHAR_PATH_SEPARATOR);
+ return newName;
+}
+#endif
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.h
new file mode 100644
index 0000000000..404fce4698
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.h
@@ -0,0 +1,28 @@
+// Archive/Common/ItemNameUtils.h
+
+#ifndef __ARCHIVE_ITEM_NAME_UTILS_H
+#define __ARCHIVE_ITEM_NAME_UTILS_H
+
+#include "../../../Common/MyString.h"
+
+namespace NArchive {
+namespace NItemName {
+
+void ReplaceSlashes_OsToUnix(UString &name);
+
+UString GetOsPath(const UString &name);
+UString GetOsPath_Remove_TailSlash(const UString &name);
+
+void ReplaceToOsSlashes_Remove_TailSlash(UString &name);
+
+bool HasTailSlash(const AString &name, UINT codePage);
+
+#ifdef _WIN32
+ inline UString WinPathToOsPath(const UString &name) { return name; }
+#else
+ UString WinPathToOsPath(const UString &name);
+#endif
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.cpp
new file mode 100644
index 0000000000..39d15217f2
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.cpp
@@ -0,0 +1,191 @@
+// MultiStream.cpp
+
+#include "StdAfx.h"
+
+#include "MultiStream.h"
+
+STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ if (_pos >= _totalLength)
+ return S_OK;
+
+ {
+ unsigned left = 0, mid = _streamIndex, right = Streams.Size();
+ for (;;)
+ {
+ CSubStreamInfo &m = Streams[mid];
+ if (_pos < m.GlobalOffset)
+ right = mid;
+ else if (_pos >= m.GlobalOffset + m.Size)
+ left = mid + 1;
+ else
+ {
+ _streamIndex = mid;
+ break;
+ }
+ mid = (left + right) / 2;
+ }
+ _streamIndex = mid;
+ }
+
+ CSubStreamInfo &s = Streams[_streamIndex];
+ UInt64 localPos = _pos - s.GlobalOffset;
+ if (localPos != s.LocalPos)
+ {
+ RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos));
+ }
+ UInt64 rem = s.Size - localPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ HRESULT result = s.Stream->Read(data, size, &size);
+ _pos += size;
+ s.LocalPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
+}
+
+STDMETHODIMP CMultiStream::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 += _totalLength; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _pos = offset;
+ if (newPosition)
+ *newPosition = offset;
+ return S_OK;
+}
+
+
+/*
+class COutVolumeStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ unsigned _volIndex;
+ UInt64 _volSize;
+ UInt64 _curPos;
+ CMyComPtr<ISequentialOutStream> _volumeStream;
+ COutArchive _archive;
+ CCRC _crc;
+
+public:
+ MY_UNKNOWN_IMP
+
+ CFileItem _file;
+ CUpdateOptions _options;
+ CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+ void Init(IArchiveUpdateCallback2 *volumeCallback,
+ const UString &name)
+ {
+ _file.Name = name;
+ _file.IsStartPosDefined = true;
+ _file.StartPos = 0;
+
+ VolumeCallback = volumeCallback;
+ _volIndex = 0;
+ _volSize = 0;
+ }
+
+ HRESULT Flush();
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+HRESULT COutVolumeStream::Flush()
+{
+ if (_volumeStream)
+ {
+ _file.UnPackSize = _curPos;
+ _file.FileCRC = _crc.GetDigest();
+ RINOK(WriteVolumeHeader(_archive, _file, _options));
+ _archive.Close();
+ _volumeStream.Release();
+ _file.StartPos += _file.UnPackSize;
+ }
+ return S_OK;
+}
+*/
+
+/*
+STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ while (size > 0)
+ {
+ if (_streamIndex >= Streams.Size())
+ {
+ CSubStreamInfo subStream;
+ RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
+ RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
+ subStream.Pos = 0;
+ Streams.Add(subStream);
+ continue;
+ }
+ CSubStreamInfo &subStream = Streams[_streamIndex];
+ if (_offsetPos >= subStream.Size)
+ {
+ _offsetPos -= subStream.Size;
+ _streamIndex++;
+ continue;
+ }
+ if (_offsetPos != subStream.Pos)
+ {
+ CMyComPtr<IOutStream> outStream;
+ RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
+ RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
+ subStream.Pos = _offsetPos;
+ }
+
+ UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
+ UInt32 realProcessed;
+ RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
+ data = (void *)((Byte *)data + realProcessed);
+ size -= realProcessed;
+ subStream.Pos += realProcessed;
+ _offsetPos += realProcessed;
+ _absPos += realProcessed;
+ if (_absPos > _length)
+ _length = _absPos;
+ if (processedSize)
+ *processedSize += realProcessed;
+ if (subStream.Pos == subStream.Size)
+ {
+ _streamIndex++;
+ _offsetPos = 0;
+ }
+ if (realProcessed != curSize && realProcessed == 0)
+ return E_FAIL;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ switch (seekOrigin)
+ {
+ case STREAM_SEEK_SET: break;
+ case STREAM_SEEK_CUR: offset += _absPos; break;
+ case STREAM_SEEK_END: offset += _length; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _absPos = offset;
+ _offsetPos = _absPos;
+ _streamIndex = 0;
+ if (newPosition)
+ *newPosition = offset;
+ return S_OK;
+}
+*/
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.h
new file mode 100644
index 0000000000..39e041def7
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.h
@@ -0,0 +1,89 @@
+// MultiStream.h
+
+#ifndef __MULTI_STREAM_H
+#define __MULTI_STREAM_H
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyVector.h"
+
+#include "../../IStream.h"
+
+class CMultiStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ UInt64 _pos;
+ UInt64 _totalLength;
+ unsigned _streamIndex;
+
+public:
+
+ struct CSubStreamInfo
+ {
+ CMyComPtr<IInStream> Stream;
+ UInt64 Size;
+ UInt64 GlobalOffset;
+ UInt64 LocalPos;
+
+ CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {}
+ };
+
+ CObjectVector<CSubStreamInfo> Streams;
+
+ HRESULT Init()
+ {
+ UInt64 total = 0;
+ FOR_VECTOR (i, Streams)
+ {
+ CSubStreamInfo &s = Streams[i];
+ s.GlobalOffset = total;
+ total += Streams[i].Size;
+ RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos));
+ }
+ _totalLength = total;
+ _pos = 0;
+ _streamIndex = 0;
+ return S_OK;
+ }
+
+ MY_UNKNOWN_IMP1(IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+/*
+class COutMultiStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+ unsigned _streamIndex; // required stream
+ UInt64 _offsetPos; // offset from start of _streamIndex index
+ UInt64 _absPos;
+ UInt64 _length;
+
+ struct CSubStreamInfo
+ {
+ CMyComPtr<ISequentialOutStream> Stream;
+ UInt64 Size;
+ UInt64 Pos;
+ };
+ CObjectVector<CSubStreamInfo> Streams;
+public:
+ CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+ void Init()
+ {
+ _streamIndex = 0;
+ _offsetPos = 0;
+ _absPos = 0;
+ _length = 0;
+ }
+
+ MY_UNKNOWN_IMP1(IOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+*/
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
new file mode 100644
index 0000000000..e0d3894b52
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
@@ -0,0 +1,18 @@
+// OutStreamWithCRC.cpp
+
+#include "StdAfx.h"
+
+#include "OutStreamWithCRC.h"
+
+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ if (_calculate)
+ _crc = CrcUpdate(_crc, data, size);
+ _size += size;
+ if (processedSize != NULL)
+ *processedSize = size;
+ return result;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.h
new file mode 100644
index 0000000000..0cc9a859f8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.h
@@ -0,0 +1,37 @@
+// OutStreamWithCRC.h
+
+#ifndef __OUT_STREAM_WITH_CRC_H
+#define __OUT_STREAM_WITH_CRC_H
+
+#include "../../../../C/7zCrc.h"
+
+#include "../../../Common/MyCom.h"
+
+#include "../../IStream.h"
+
+class COutStreamWithCRC:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+ UInt32 _crc;
+ bool _calculate;
+public:
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init(bool calculate = true)
+ {
+ _size = 0;
+ _calculate = calculate;
+ _crc = CRC_INIT_VAL;
+ }
+ void EnableCalc(bool calculate) { _calculate = calculate; }
+ void InitCRC() { _crc = CRC_INIT_VAL; }
+ UInt64 GetSize() const { return _size; }
+ UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.cpp
new file mode 100644
index 0000000000..0fe89b3d20
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.cpp
@@ -0,0 +1,3 @@
+// ParseProperties.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.h
new file mode 100644
index 0000000000..f4367a76f2
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.h
@@ -0,0 +1,6 @@
+// ParseProperties.h
+
+#ifndef __PARSE_PROPERTIES_H
+#define __PARSE_PROPERTIES_H
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Common/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Common/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/DllExports2.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/DllExports2.cpp
new file mode 100644
index 0000000000..c43e72acc3
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/DllExports2.cpp
@@ -0,0 +1,122 @@
+// DLLExports2.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/MyWindows.h"
+
+#include "../../Common/MyInitGuid.h"
+
+#if defined(_7ZIP_LARGE_PAGES)
+#include "../../../C/Alloc.h"
+#endif
+
+#include "../../Common/ComTry.h"
+
+#include "../../Windows/NtCheck.h"
+#include "../../Windows/PropVariant.h"
+
+#include "../ICoder.h"
+#include "../IPassword.h"
+
+#include "../Common/CreateCoder.h"
+
+#include "IArchive.h"
+
+HINSTANCE g_hInstance;
+
+#define NT_CHECK_FAIL_ACTION return FALSE;
+
+#ifdef _WIN32
+extern "C"
+BOOL WINAPI DllMain(
+ #ifdef UNDER_CE
+ HANDLE
+ #else
+ HINSTANCE
+ #endif
+ hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
+{
+ 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;
+}
+#endif
+
+DEFINE_GUID(CLSID_CArchiveHandler,
+ 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 *clsid, const GUID *iid, void **outObject);
+
+STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
+{
+ // COM_TRY_BEGIN
+ *outObject = 0;
+ if (*iid == IID_ICompressCoder ||
+ *iid == IID_ICompressCoder2 ||
+ *iid == IID_ICompressFilter)
+ return CreateCoder(clsid, iid, outObject);
+ if (*iid == IID_IHasher)
+ return CreateHasher(clsid, (IHasher **)outObject);
+ return CreateArchiver(clsid, iid, outObject);
+ // COM_TRY_END
+}
+
+STDAPI SetLargePageMode()
+{
+ #if defined(_7ZIP_LARGE_PAGES)
+ SetLargePageSize();
+ #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/other-licenses/7zstub/src/CPP/7zip/Archive/IArchive.h b/other-licenses/7zstub/src/CPP/7zip/Archive/IArchive.h
new file mode 100644
index 0000000000..96451a6bcd
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/IArchive.h
@@ -0,0 +1,608 @@
+// IArchive.h
+
+#ifndef __IARCHIVE_H
+#define __IARCHIVE_H
+
+#include "../IProgress.h"
+#include "../IStream.h"
+#include "../PropID.h"
+
+#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)
+#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
+
+namespace NFileTimeType
+{
+ enum EEnum
+ {
+ kWindows,
+ kUnix,
+ kDOS
+ };
+}
+
+namespace NArcInfoFlags
+{
+ const UInt32 kKeepName = 1 << 0; // keep name of file in archive name
+ const UInt32 kAltStreams = 1 << 1; // the handler supports alt streams
+ const UInt32 kNtSecure = 1 << 2; // the handler supports NT security
+ const UInt32 kFindSignature = 1 << 3; // the handler can find start of archive
+ const UInt32 kMultiSignature = 1 << 4; // there are several signatures
+ const UInt32 kUseGlobalOffset = 1 << 5; // the seek position of stream must be set as global offset
+ const UInt32 kStartOpen = 1 << 6; // call handler for each start position
+ const UInt32 kPureStartOpen = 1 << 7; // call handler only for start of file
+ const UInt32 kBackwardOpen = 1 << 8; // archive can be open backward
+ const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub)
+ const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links
+ const UInt32 kHardLinks = 1 << 11; // the handler supports hard links
+}
+
+namespace NArchive
+{
+ namespace NHandlerPropID
+ {
+ enum
+ {
+ kName = 0, // VT_BSTR
+ kClassID, // binary GUID in VT_BSTR
+ kExtension, // VT_BSTR
+ kAddExtension, // VT_BSTR
+ kUpdate, // VT_BOOL
+ kKeepName, // VT_BOOL
+ kSignature, // binary in VT_BSTR
+ kMultiSignature, // binary in VT_BSTR
+ kSignatureOffset, // VT_UI4
+ kAltStreams, // VT_BOOL
+ kNtSecure, // VT_BOOL
+ kFlags // VT_UI4
+ // kVersion // VT_UI4 ((VER_MAJOR << 8) | VER_MINOR)
+ };
+ }
+
+ namespace NExtract
+ {
+ namespace NAskMode
+ {
+ enum
+ {
+ kExtract = 0,
+ kTest,
+ kSkip
+ };
+ }
+
+ namespace NOperationResult
+ {
+ enum
+ {
+ kOK = 0,
+ kUnsupportedMethod,
+ kDataError,
+ kCRCError,
+ kUnavailable,
+ kUnexpectedEnd,
+ kDataAfterEnd,
+ kIsNotArc,
+ kHeadersError,
+ kWrongPassword
+ };
+ }
+ }
+
+ namespace NEventIndexType
+ {
+ enum
+ {
+ kNoIndex = 0,
+ kInArcIndex,
+ kBlockIndex,
+ kOutArcIndex
+ };
+ }
+
+ namespace NUpdate
+ {
+ namespace NOperationResult
+ {
+ enum
+ {
+ kOK = 0
+ , // kError
+ };
+ }
+ }
+}
+
+#define INTERFACE_IArchiveOpenCallback(x) \
+ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \
+ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \
+
+ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
+{
+ INTERFACE_IArchiveOpenCallback(PURE);
+};
+
+/*
+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 opRes) x; \
+
+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
+{
+ INTERFACE_IArchiveExtractCallback(PURE)
+};
+
+
+
+/*
+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; \
+
+ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)
+{
+ INTERFACE_IArchiveOpenVolumeCallback(PURE);
+};
+
+
+ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)
+{
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)
+{
+ STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;
+};
+
+
+/*
+IInArchive::Open
+ stream
+ if (kUseGlobalOffset), stream current position can be non 0.
+ if (!kUseGlobalOffset), stream current position is 0.
+ if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream
+ if (*maxCheckStartPosition == 0), the handler must check only current position as archive start
+
+IInArchive::Extract:
+ indices must be sorted
+ numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files"
+ testMode != 0 means "test files without writing to outStream"
+
+IInArchive::GetArchiveProperty:
+ kpidOffset - start offset of archive.
+ VT_EMPTY : means offset = 0.
+ VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed
+ kpidPhySize - size of archive. VT_EMPTY means unknown size.
+ kpidPhySize is allowed to be larger than file size. In that case it must show
+ supposed size.
+
+ kpidIsDeleted:
+ kpidIsAltStream:
+ kpidIsAux:
+ kpidINode:
+ must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty.
+
+
+Notes:
+ Don't call IInArchive functions for same IInArchive object from different threads simultaneously.
+ Some IInArchive handlers will work incorrectly in that case.
+*/
+
+#ifdef _MSC_VER
+ #define MY_NO_THROW_DECL_ONLY throw()
+#else
+ #define MY_NO_THROW_DECL_ONLY
+#endif
+
+#define INTERFACE_IInArchive(x) \
+ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) MY_NO_THROW_DECL_ONLY x; \
+ STDMETHOD(Close)() MY_NO_THROW_DECL_ONLY x; \
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) MY_NO_THROW_DECL_ONLY x; \
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY x; \
+ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \
+ 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; \
+
+ARCHIVE_INTERFACE(IInArchive, 0x60)
+{
+ INTERFACE_IInArchive(PURE)
+};
+
+namespace NParentType
+{
+ enum
+ {
+ kDir = 0,
+ kAltStream
+ };
+};
+
+namespace NPropDataType
+{
+ const UInt32 kMask_ZeroEnd = 1 << 4;
+ // const UInt32 kMask_BigEndian = 1 << 5;
+ const UInt32 kMask_Utf = 1 << 6;
+ const UInt32 kMask_Utf8 = kMask_Utf | 0;
+ const UInt32 kMask_Utf16 = kMask_Utf | 1;
+ // const UInt32 kMask_Utf32 = kMask_Utf | 2;
+
+ const UInt32 kNotDefined = 0;
+ const UInt32 kRaw = 1;
+
+ const UInt32 kUtf8z = kMask_Utf8 | kMask_ZeroEnd;
+ const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd;
+};
+
+// UTF string (pointer to wchar_t) with zero end and little-endian.
+#define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1))
+
+/*
+GetRawProp:
+ Result:
+ S_OK - even if property is not set
+*/
+
+#define INTERFACE_IArchiveGetRawProps(x) \
+ STDMETHOD(GetParent)(UInt32 index, UInt32 *parent, UInt32 *parentType) x; \
+ STDMETHOD(GetRawProp)(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \
+ STDMETHOD(GetNumRawProps)(UInt32 *numProps) x; \
+ STDMETHOD(GetRawPropInfo)(UInt32 index, BSTR *name, PROPID *propID) x;
+
+ARCHIVE_INTERFACE(IArchiveGetRawProps, 0x70)
+{
+ INTERFACE_IArchiveGetRawProps(PURE)
+};
+
+#define INTERFACE_IArchiveGetRootProps(x) \
+ STDMETHOD(GetRootProp)(PROPID propID, PROPVARIANT *value) x; \
+ STDMETHOD(GetRootRawProp)(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \
+
+ARCHIVE_INTERFACE(IArchiveGetRootProps, 0x71)
+{
+ INTERFACE_IArchiveGetRootProps(PURE)
+};
+
+ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61)
+{
+ STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;
+};
+
+/*
+ OpenForSize
+ Result:
+ S_FALSE - is not archive
+ ? - DATA error
+*/
+
+/*
+const UInt32 kOpenFlags_RealPhySize = 1 << 0;
+const UInt32 kOpenFlags_NoSeek = 1 << 1;
+// const UInt32 kOpenFlags_BeforeExtract = 1 << 2;
+*/
+
+/*
+Flags:
+ 0 - opens archive with IInStream, if IInStream interface is supported
+ - if phySize is not available, it doesn't try to make full parse to get phySize
+ kOpenFlags_NoSeek - ArcOpen2 function doesn't use IInStream interface, even if it's available
+ kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file
+
+ if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified,
+ the handler can return S_OK, but it doesn't check even Signature.
+ So next Extract can be called for that sequential stream.
+*/
+
+/*
+ARCHIVE_INTERFACE(IArchiveOpen2, 0x62)
+{
+ STDMETHOD(ArcOpen2)(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback) PURE;
+};
+*/
+
+// ---------- UPDATE ----------
+
+/*
+GetUpdateItemInfo outs:
+*newData *newProps
+ 0 0 - Copy data and properties from archive
+ 0 1 - Copy data from archive, request new properties
+ 1 0 - that combination is unused now
+ 1 1 - Request new data and new properties. It can be used even for folders
+
+ indexInArchive = -1 if there is no item in archive, or if it doesn't matter.
+
+
+GetStream out:
+ Result:
+ S_OK:
+ (*inStream == NULL) - only for directories
+ - the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file
+ (*inStream != NULL) - for any file, even for empty file or anti-file
+ S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason)
+ (*inStream == NULL)
+
+The order of calling for hard links:
+ - GetStream()
+ - GetProperty(kpidHardLink)
+
+SetOperationResult()
+ Int32 opRes (NExtract::NOperationResult::kOK)
+*/
+
+#define INTERFACE_IArchiveUpdateCallback(x) \
+ INTERFACE_IProgress(x); \
+ STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) x; \
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
+ STDMETHOD(SetOperationResult)(Int32 operationResult) x; \
+
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
+{
+ INTERFACE_IArchiveUpdateCallback(PURE);
+};
+
+#define INTERFACE_IArchiveUpdateCallback2(x) \
+ INTERFACE_IArchiveUpdateCallback(x) \
+ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \
+ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \
+
+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()
+-------------
+
+ outStream: output stream. (the handler) MUST support the case when
+ Seek position in outStream is not ZERO.
+ but the caller calls with empty outStream and seek position is ZERO??
+
+ archives with stub:
+
+ If archive is open and the handler and (Offset > 0), then the handler
+ knows about stub size.
+ UpdateItems():
+ 1) the handler MUST copy that stub to outStream
+ 2) the caller MUST NOT copy the stub to outStream, if
+ "rsfx" property is set with SetProperties
+
+ the handler must support the case where
+ ISequentialOutStream *outStream
+*/
+
+
+#define INTERFACE_IOutArchive(x) \
+ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
+ STDMETHOD(GetFileTimeType)(UInt32 *type) x;
+
+ARCHIVE_INTERFACE(IOutArchive, 0xA0)
+{
+ INTERFACE_IOutArchive(PURE)
+};
+
+
+/*
+ISetProperties::SetProperties()
+ PROPVARIANT values[i].vt:
+ VT_EMPTY
+ VT_BOOL
+ VT_UI4 - if 32-bit number
+ VT_UI8 - if 64-bit number
+ VT_BSTR
+*/
+
+ARCHIVE_INTERFACE(ISetProperties, 0x03)
+{
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE;
+};
+
+ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04)
+{
+ STDMETHOD(KeepModeForNextOpen)() PURE;
+};
+
+/* Exe handler: the handler for executable format (PE, ELF, Mach-O).
+ SFX archive: executable stub + some tail data.
+ before 9.31: exe handler didn't parse SFX archives as executable format.
+ for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */
+
+ARCHIVE_INTERFACE(IArchiveAllowTail, 0x05)
+{
+ STDMETHOD(AllowTail)(Int32 allowTail) PURE;
+};
+
+
+#define IMP_IInArchive_GetProp(k) \
+ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
+ { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
+ *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \
+
+
+struct CStatProp
+{
+ const char *Name;
+ UInt32 PropID;
+ VARTYPE vt;
+};
+
+namespace NWindows {
+namespace NCOM {
+// PropVariant.cpp
+BSTR AllocBstrFromAscii(const char *s) throw();
+}}
+
+#define IMP_IInArchive_GetProp_WITH_NAME(k) \
+ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
+ { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
+ const CStatProp &prop = k[index]; \
+ *propID = (PROPID)prop.PropID; *varType = prop.vt; \
+ *name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \
+
+#define IMP_IInArchive_Props \
+ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \
+ { *numProps = ARRAY_SIZE(kProps); return S_OK; } \
+ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)
+
+#define IMP_IInArchive_Props_WITH_NAME \
+ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \
+ { *numProps = ARRAY_SIZE(kProps); return S_OK; } \
+ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)
+
+
+#define IMP_IInArchive_ArcProps \
+ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \
+ { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \
+ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)
+
+#define IMP_IInArchive_ArcProps_WITH_NAME \
+ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \
+ { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \
+ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps)
+
+#define IMP_IInArchive_ArcProps_NO_Table \
+ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \
+ { *numProps = 0; return S_OK; } \
+ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \
+ { return E_NOTIMPL; } \
+
+#define IMP_IInArchive_ArcProps_NO \
+ IMP_IInArchive_ArcProps_NO_Table \
+ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \
+ { value->vt = VT_EMPTY; return S_OK; }
+
+
+
+#define k_IsArc_Res_NO 0
+#define k_IsArc_Res_YES 1
+#define k_IsArc_Res_NEED_MORE 2
+// #define k_IsArc_Res_YES_LOW_PROB 3
+
+#define API_FUNC_IsArc EXTERN_C UInt32 WINAPI
+#define API_FUNC_static_IsArc extern "C" { static UInt32 WINAPI
+
+extern "C"
+{
+ typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject);
+
+ typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size);
+ typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc);
+
+ typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats);
+ typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value);
+ typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value);
+
+ typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive);
+ typedef HRESULT (WINAPI *Func_SetLargePageMode)();
+
+ typedef IOutArchive * (*Func_CreateOutArchive)();
+ typedef IInArchive * (*Func_CreateInArchive)();
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/Icons/7z.ico b/other-licenses/7zstub/src/CPP/7zip/Archive/Icons/7z.ico
new file mode 100644
index 0000000000..319753a177
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/Icons/7z.ico
Binary files differ
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/LzmaHandler.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/LzmaHandler.cpp
new file mode 100644
index 0000000000..28079dfc67
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/LzmaHandler.cpp
@@ -0,0 +1,605 @@
+// LzmaHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "../../Common/ComTry.h"
+#include "../../Common/IntToString.h"
+
+#include "../../Windows/PropVariant.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"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NLzma {
+
+static bool CheckDicSize(const Byte *p)
+{
+ UInt32 dicSize = GetUi32(p);
+ if (dicSize == 1)
+ return true;
+ for (unsigned i = 0; i <= 30; i++)
+ if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i))
+ return true;
+ return (dicSize == 0xFFFFFFFF);
+}
+
+static const Byte kProps[] =
+{
+ kpidSize,
+ kpidPackSize,
+ kpidMethod
+};
+
+static const Byte kArcProps[] =
+{
+ kpidNumStreams,
+ kpidMethod
+};
+
+struct CHeader
+{
+ UInt64 Size;
+ Byte FilterID;
+ Byte LzmaProps[5];
+
+ Byte GetProp() const { return LzmaProps[0]; }
+ UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); }
+ bool HasSize() const { return (Size != (UInt64)(Int64)-1); }
+ bool Parse(const Byte *buf, bool isThereFilter);
+};
+
+bool CHeader::Parse(const Byte *buf, bool isThereFilter)
+{
+ FilterID = 0;
+ if (isThereFilter)
+ FilterID = buf[0];
+ const Byte *sig = buf + (isThereFilter ? 1 : 0);
+ for (int i = 0; i < 5; i++)
+ LzmaProps[i] = sig[i];
+ Size = GetUi64(sig + 5);
+ return
+ LzmaProps[0] < 5 * 5 * 9 &&
+ FilterID < 2 &&
+ (!HasSize() || Size < ((UInt64)1 << 56))
+ && CheckDicSize(LzmaProps + 1);
+}
+
+class CDecoder
+{
+ CMyComPtr<ISequentialOutStream> _bcjStream;
+ CFilterCoder *_filterCoder;
+ CMyComPtr<ICompressCoder> _lzmaDecoder;
+public:
+ NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
+
+ ~CDecoder();
+ HRESULT Create(bool filtered, ISequentialInStream *inStream);
+
+ HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
+
+ UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); }
+
+ void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); }
+
+ HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize)
+ { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }
+};
+
+HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
+{
+ if (!_lzmaDecoder)
+ {
+ _lzmaDecoderSpec = new NCompress::NLzma::CDecoder;
+ _lzmaDecoderSpec->FinishStream = true;
+ _lzmaDecoder = _lzmaDecoderSpec;
+ }
+
+ if (filteredMode)
+ {
+ if (!_bcjStream)
+ {
+ _filterCoder = new CFilterCoder(false);
+ CMyComPtr<ICompressCoder> coder = _filterCoder;
+ _filterCoder->Filter = new NCompress::NBcj::CCoder(false);
+ _bcjStream = _filterCoder;
+ }
+ }
+
+ return _lzmaDecoderSpec->SetInStream(inStream);
+}
+
+CDecoder::~CDecoder()
+{
+ ReleaseInStream();
+}
+
+HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
+ ICompressProgressInfo *progress)
+{
+ if (header.FilterID > 1)
+ return E_NOTIMPL;
+
+ {
+ CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
+ _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+ if (!setDecoderProperties)
+ return E_NOTIMPL;
+ RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));
+ }
+
+ bool filteredMode = (header.FilterID == 1);
+
+ if (filteredMode)
+ {
+ RINOK(_filterCoder->SetOutStream(outStream));
+ outStream = _bcjStream;
+ RINOK(_filterCoder->SetOutStreamSize(NULL));
+ }
+
+ const UInt64 *Size = header.HasSize() ? &header.Size : NULL;
+ HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress);
+
+ if (filteredMode)
+ {
+ {
+ HRESULT res2 = _filterCoder->OutStreamFinish();
+ if (res == S_OK)
+ res = res2;
+ }
+ HRESULT res2 = _filterCoder->ReleaseOutStream();
+ if (res == S_OK)
+ res = res2;
+ }
+
+ RINOK(res);
+
+ if (header.HasSize())
+ if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size)
+ return S_FALSE;
+
+ return S_OK;
+}
+
+
+class CHandler:
+ public IInArchive,
+ public IArchiveOpenSeq,
+ public CMyUnknownImp
+{
+ CHeader _header;
+ bool _lzma86;
+ CMyComPtr<IInStream> _stream;
+ CMyComPtr<ISequentialInStream> _seqStream;
+
+ bool _isArc;
+ bool _needSeekToStart;
+ bool _dataAfterEnd;
+ bool _needMoreInput;
+
+ bool _packSize_Defined;
+ bool _unpackSize_Defined;
+ bool _numStreams_Defined;
+
+ bool _unsupported;
+ bool _dataError;
+
+ UInt64 _packSize;
+ UInt64 _unpackSize;
+ UInt64 _numStreams;
+
+ void GetMethod(NCOM::CPropVariant &prop);
+
+public:
+ MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
+
+ INTERFACE_IInArchive(;)
+ STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+
+ CHandler(bool lzma86) { _lzma86 = lzma86; }
+
+ unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); }
+
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
+ case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;
+ case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;
+ case kpidMethod: GetMethod(prop); break;
+ case kpidErrorFlags:
+ {
+ UInt32 v = 0;
+ if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;
+ if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
+ if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
+ if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
+ if (_dataError) v |= kpv_ErrorFlags_DataError;
+ prop = v;
+ break;
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = 1;
+ return S_OK;
+}
+
+
+static void DictSizeToString(UInt32 val, char *s)
+{
+ for (unsigned i = 0; i <= 31; i++)
+ if (((UInt32)1 << i) == val)
+ {
+ ::ConvertUInt32ToString(i, s);
+ return;
+ }
+ char c = 'b';
+ if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
+ else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
+ ::ConvertUInt32ToString(val, s);
+ s += MyStringLen(s);
+ *s++ = c;
+ *s = 0;
+}
+
+static char *AddProp32(char *s, const char *name, UInt32 v)
+{
+ *s++ = ':';
+ s = MyStpCpy(s, name);
+ ::ConvertUInt32ToString(v, s);
+ return s + MyStringLen(s);
+}
+
+void CHandler::GetMethod(NCOM::CPropVariant &prop)
+{
+ if (!_stream)
+ return;
+
+ char sz[64];
+ char *s = sz;
+ if (_header.FilterID != 0)
+ s = MyStpCpy(s, "BCJ ");
+ s = MyStpCpy(s, "LZMA:");
+ DictSizeToString(_header.GetDicSize(), s);
+ s += strlen(s);
+
+ UInt32 d = _header.GetProp();
+ // if (d != 0x5D)
+ {
+ UInt32 lc = d % 9;
+ d /= 9;
+ UInt32 pb = d / 5;
+ UInt32 lp = d % 5;
+ if (lc != 3) s = AddProp32(s, "lc", lc);
+ if (lp != 0) s = AddProp32(s, "lp", lp);
+ if (pb != 2) s = AddProp32(s, "pb", pb);
+ }
+ prop = sz;
+}
+
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;
+ case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
+ case kpidMethod: GetMethod(prop); break;
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size)
+{
+ const UInt32 kHeaderSize = 1 + 4 + 8;
+ if (size < kHeaderSize)
+ return k_IsArc_Res_NEED_MORE;
+ if (p[0] >= 5 * 5 * 9)
+ return k_IsArc_Res_NO;
+ UInt64 unpackSize = GetUi64(p + 1 + 4);
+ if (unpackSize != (UInt64)(Int64)-1)
+ {
+ if (size >= ((UInt64)1 << 56))
+ return k_IsArc_Res_NO;
+ }
+ if (unpackSize != 0)
+ {
+ if (size < kHeaderSize + 2)
+ return k_IsArc_Res_NEED_MORE;
+ if (p[kHeaderSize] != 0)
+ return k_IsArc_Res_NO;
+ if (unpackSize != (UInt64)(Int64)-1)
+ {
+ if ((p[kHeaderSize + 1] & 0x80) != 0)
+ return k_IsArc_Res_NO;
+ }
+ }
+ if (!CheckDicSize(p + 1))
+ // return k_IsArc_Res_YES_LOW_PROB;
+ return k_IsArc_Res_NO;
+ return k_IsArc_Res_YES;
+}
+}
+
+API_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size)
+{
+ if (size < 1)
+ return k_IsArc_Res_NEED_MORE;
+ Byte filterID = p[0];
+ if (filterID != 0 && filterID != 1)
+ return k_IsArc_Res_NO;
+ return IsArc_Lzma(p + 1, size - 1);
+}
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)
+{
+ Close();
+
+ const UInt32 kBufSize = 1 + 5 + 8 + 2;
+ Byte buf[kBufSize];
+
+ RINOK(ReadStream_FALSE(inStream, buf, kBufSize));
+
+ if (!_header.Parse(buf, _lzma86))
+ return S_FALSE;
+ const Byte *start = buf + GetHeaderSize();
+ if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80
+ return S_FALSE;
+
+ RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));
+ if (_packSize >= 24 && _header.Size == 0 && _header.FilterID == 0 && _header.LzmaProps[0] == 0)
+ return S_FALSE;
+ _isArc = true;
+ _stream = inStream;
+ _seqStream = inStream;
+ _needSeekToStart = true;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+ Close();
+ _isArc = true;
+ _seqStream = stream;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _isArc = false;
+ _packSize_Defined = false;
+ _unpackSize_Defined = false;
+ _numStreams_Defined = false;
+
+ _dataAfterEnd = false;
+ _needMoreInput = false;
+ _unsupported = false;
+ _dataError = false;
+
+ _packSize = 0;
+
+ _needSeekToStart = false;
+
+ _stream.Release();
+ _seqStream.Release();
+ return S_OK;
+}
+
+class CCompressProgressInfoImp:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+ CMyComPtr<IArchiveOpenCallback> Callback;
+public:
+ UInt64 Offset;
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+ void Init(IArchiveOpenCallback *callback) { Callback = callback; }
+};
+
+STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ if (Callback)
+ {
+ const UInt64 files = 0;
+ const UInt64 val = Offset + *inSize;
+ return Callback->SetCompleted(&files, &val);
+ }
+ return S_OK;
+}
+
+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))
+ return E_INVALIDARG;
+
+ if (_packSize_Defined)
+ extractCallback->SetTotal(_packSize);
+
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+ RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+ if (!testMode && !realOutStream)
+ return S_OK;
+
+ extractCallback->PrepareOperation(askMode);
+
+ CDummyOutStream *outStreamSpec = new CDummyOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ outStreamSpec->SetStream(realOutStream);
+ outStreamSpec->Init();
+ realOutStream.Release();
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, true);
+
+ if (_needSeekToStart)
+ {
+ if (!_stream)
+ return E_FAIL;
+ RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+ else
+ _needSeekToStart = true;
+
+ CDecoder decoder;
+ HRESULT result = decoder.Create(_lzma86, _seqStream);
+ RINOK(result);
+
+ bool firstItem = true;
+
+ UInt64 packSize = 0;
+ UInt64 unpackSize = 0;
+ UInt64 numStreams = 0;
+
+ bool dataAfterEnd = false;
+
+ for (;;)
+ {
+ lps->InSize = packSize;
+ lps->OutSize = unpackSize;
+ RINOK(lps->SetCur());
+
+ const UInt32 kBufSize = 1 + 5 + 8;
+ Byte buf[kBufSize];
+ const UInt32 headerSize = GetHeaderSize();
+ UInt32 processed;
+ RINOK(decoder.ReadInput(buf, headerSize, &processed));
+ if (processed != headerSize)
+ {
+ if (processed != 0)
+ dataAfterEnd = true;
+ break;
+ }
+
+ CHeader st;
+ if (!st.Parse(buf, _lzma86))
+ {
+ dataAfterEnd = true;
+ break;
+ }
+ numStreams++;
+ firstItem = false;
+
+ result = decoder.Code(st, outStream, progress);
+
+ packSize = decoder.GetInputProcessedSize();
+ unpackSize = outStreamSpec->GetSize();
+
+ if (result == E_NOTIMPL)
+ {
+ _unsupported = true;
+ result = S_FALSE;
+ break;
+ }
+ if (result == S_FALSE)
+ break;
+ RINOK(result);
+ }
+
+ if (firstItem)
+ {
+ _isArc = false;
+ result = S_FALSE;
+ }
+ else if (result == S_OK || result == S_FALSE)
+ {
+ if (dataAfterEnd)
+ _dataAfterEnd = true;
+ else if (decoder._lzmaDecoderSpec->NeedsMoreInput())
+ _needMoreInput = true;
+
+ _packSize = packSize;
+ _unpackSize = unpackSize;
+ _numStreams = numStreams;
+
+ _packSize_Defined = true;
+ _unpackSize_Defined = true;
+ _numStreams_Defined = true;
+ }
+
+ Int32 opResult = NExtract::NOperationResult::kOK;
+
+ if (!_isArc)
+ opResult = NExtract::NOperationResult::kIsNotArc;
+ else if (_needMoreInput)
+ opResult = NExtract::NOperationResult::kUnexpectedEnd;
+ else if (_unsupported)
+ opResult = NExtract::NOperationResult::kUnsupportedMethod;
+ else if (_dataAfterEnd)
+ opResult = NExtract::NOperationResult::kDataAfterEnd;
+ else if (result == S_FALSE)
+ opResult = NExtract::NOperationResult::kDataError;
+ else if (result == S_OK)
+ opResult = NExtract::NOperationResult::kOK;
+ else
+ return result;
+
+ outStream.Release();
+ return extractCallback->SetOperationResult(opResult);
+
+ COM_TRY_END
+}
+
+namespace NLzmaAr {
+
+// 2, { 0x5D, 0x00 },
+
+REGISTER_ARC_I_CLS_NO_SIG(
+ CHandler(false),
+ "lzma", "lzma", 0, 0xA,
+ 0,
+ NArcInfoFlags::kStartOpen |
+ NArcInfoFlags::kKeepName,
+ IsArc_Lzma)
+
+}
+
+namespace NLzma86Ar {
+
+REGISTER_ARC_I_CLS_NO_SIG(
+ CHandler(true),
+ "lzma86", "lzma86", 0, 0xB,
+ 0,
+ NArcInfoFlags::kKeepName,
+ IsArc_Lzma86)
+
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/SplitHandler.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/SplitHandler.cpp
new file mode 100644
index 0000000000..ffb0e3343c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/SplitHandler.cpp
@@ -0,0 +1,359 @@
+// SplitHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/ComTry.h"
+#include "../../Common/MyString.h"
+
+#include "../../Windows/PropVariant.h"
+
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+
+#include "../Compress/CopyCoder.h"
+
+#include "Common/MultiStream.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NSplit {
+
+static const Byte kProps[] =
+{
+ kpidPath,
+ kpidSize
+};
+
+static const Byte kArcProps[] =
+{
+ kpidNumVolumes,
+ kpidTotalPhySize
+};
+
+class CHandler:
+ public IInArchive,
+ public IInArchiveGetStream,
+ public CMyUnknownImp
+{
+ CObjectVector<CMyComPtr<IInStream> > _streams;
+ CRecordVector<UInt64> _sizes;
+ UString _subName;
+ UInt64 _totalSize;
+
+ HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
+public:
+ MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+ INTERFACE_IInArchive(;)
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidMainSubfile: prop = (UInt32)0; break;
+ case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break;
+ case kpidTotalPhySize: prop = _totalSize; break;
+ case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+struct CSeqName
+{
+ UString _unchangedPart;
+ UString _changedPart;
+ bool _splitStyle;
+
+ bool GetNextName(UString &s)
+ {
+ {
+ unsigned i = _changedPart.Len();
+ for (;;)
+ {
+ wchar_t c = _changedPart[--i];
+
+ if (_splitStyle)
+ {
+ 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 == '9')
+ {
+ _changedPart.ReplaceOneCharAtPos(i, L'0');
+ if (i == 0)
+ {
+ _changedPart.InsertAtFront(L'1');
+ break;
+ }
+ continue;
+ }
+ }
+
+ c++;
+ _changedPart.ReplaceOneCharAtPos(i, c);
+ break;
+ }
+ }
+
+ s = _unchangedPart + _changedPart;
+ return true;
+ }
+};
+
+HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
+{
+ Close();
+ if (!callback)
+ return S_FALSE;
+
+ CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback;
+ callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback);
+ if (!volumeCallback)
+ return S_FALSE;
+
+ UString name;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(volumeCallback->GetProperty(kpidName, &prop));
+ if (prop.vt != VT_BSTR)
+ return S_FALSE;
+ name = prop.bstrVal;
+ }
+
+ int dotPos = name.ReverseFind_Dot();
+ const UString prefix = name.Left(dotPos + 1);
+ const UString ext = name.Ptr(dotPos + 1);
+ UString ext2 = ext;
+ ext2.MakeLower_Ascii();
+
+ CSeqName seqName;
+
+ unsigned numLetters = 2;
+ bool splitStyle = false;
+
+ if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa"))
+ {
+ splitStyle = true;
+ while (numLetters < ext2.Len())
+ {
+ if (ext2[ext2.Len() - numLetters - 1] != 'a')
+ break;
+ numLetters++;
+ }
+ }
+ else if (ext.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "01"))
+ {
+ while (numLetters < ext2.Len())
+ {
+ if (ext2[ext2.Len() - numLetters - 1] != '0')
+ break;
+ numLetters++;
+ }
+ if (numLetters != ext.Len())
+ return S_FALSE;
+ }
+ else
+ return S_FALSE;
+
+ seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters);
+ seqName._changedPart = ext.RightPtr(numLetters);
+ seqName._splitStyle = splitStyle;
+
+ if (prefix.Len() < 1)
+ _subName = "file";
+ else
+ _subName.SetFrom(prefix, prefix.Len() - 1);
+
+ UInt64 size;
+ {
+ /*
+ NCOM::CPropVariant prop;
+ RINOK(volumeCallback->GetProperty(kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ size = prop.uhVal.QuadPart;
+ */
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &size));
+ RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+
+ _totalSize += size;
+ _sizes.Add(size);
+ _streams.Add(stream);
+
+ {
+ const UInt64 numFiles = _streams.Size();
+ RINOK(callback->SetCompleted(&numFiles, NULL));
+ }
+
+ for (;;)
+ {
+ UString fullName;
+ if (!seqName.GetNextName(fullName))
+ break;
+ CMyComPtr<IInStream> nextStream;
+ HRESULT result = volumeCallback->GetStream(fullName, &nextStream);
+ if (result == S_FALSE)
+ break;
+ if (result != S_OK)
+ return result;
+ if (!nextStream)
+ break;
+ {
+ /*
+ NCOM::CPropVariant prop;
+ RINOK(volumeCallback->GetProperty(kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ size = prop.uhVal.QuadPart;
+ */
+ RINOK(nextStream->Seek(0, STREAM_SEEK_END, &size));
+ RINOK(nextStream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+ _totalSize += size;
+ _sizes.Add(size);
+ _streams.Add(nextStream);
+ {
+ const UInt64 numFiles = _streams.Size();
+ RINOK(callback->SetCompleted(&numFiles, NULL));
+ }
+ }
+
+ if (_streams.Size() == 1)
+ {
+ if (splitStyle)
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+ COM_TRY_BEGIN
+ HRESULT res = Open2(stream, callback);
+ if (res != S_OK)
+ Close();
+ return res;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _totalSize = 0;
+ _subName.Empty();
+ _streams.Clear();
+ _sizes.Clear();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _streams.IsEmpty() ? 0 : 1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidPath: prop = _subName; break;
+ case kpidSize:
+ case kpidPackSize:
+ prop = _totalSize;
+ break;
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+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))
+ return E_INVALIDARG;
+
+ UInt64 currentTotalSize = 0;
+ RINOK(extractCallback->SetTotal(_totalSize));
+ CMyComPtr<ISequentialOutStream> outStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+ RINOK(extractCallback->GetStream(0, &outStream, askMode));
+ if (!testMode && !outStream)
+ return S_OK;
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ FOR_VECTOR (i, _streams)
+ {
+ lps->InSize = lps->OutSize = currentTotalSize;
+ RINOK(lps->SetCur());
+ IInStream *inStream = _streams[i];
+ RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+ currentTotalSize += copyCoderSpec->TotalSize;
+ }
+ outStream.Release();
+ return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ COM_TRY_BEGIN
+ if (index != 0)
+ return E_INVALIDARG;
+ *stream = 0;
+ CMultiStream *streamSpec = new CMultiStream;
+ CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+ FOR_VECTOR (i, _streams)
+ {
+ CMultiStream::CSubStreamInfo subStreamInfo;
+ subStreamInfo.Stream = _streams[i];
+ subStreamInfo.Size = _sizes[i];
+ streamSpec->Streams.Add(subStreamInfo);
+ }
+ streamSpec->Init();
+ *stream = streamTemp.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+REGISTER_ARC_I_NO_SIG(
+ "Split", "001", 0, 0xEA,
+ 0,
+ 0,
+ NULL)
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Archive/StdAfx.h
new file mode 100644
index 0000000000..42a088f121
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.cpp b/other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.cpp
new file mode 100644
index 0000000000..74cbca9d59
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.cpp
@@ -0,0 +1,1308 @@
+// XzHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../../Common/ComTry.h"
+#include "../../Common/Defs.h"
+#include "../../Common/IntToString.h"
+#include "../../Common/MyBuffer.h"
+#include "../../Common/StringToInt.h"
+
+#include "../../Windows/PropVariant.h"
+#include "../../Windows/System.h"
+
+#include "../Common/CWrappers.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+#include "../Compress/XzDecoder.h"
+#include "../Compress/XzEncoder.h"
+
+#include "IArchive.h"
+
+#include "Common/HandlerOut.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NXz {
+
+#define k_LZMA2_Name "LZMA2"
+
+
+struct CBlockInfo
+{
+ unsigned StreamFlags;
+ UInt64 PackPos;
+ UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros
+ UInt64 UnpackPos;
+};
+
+
+class CHandler:
+ public IInArchive,
+ public IArchiveOpenSeq,
+ public IInArchiveGetStream,
+ public ISetProperties,
+
+ #ifndef EXTRACT_ONLY
+ public IOutArchive,
+ #endif
+
+ public CMyUnknownImp,
+
+ #ifndef EXTRACT_ONLY
+ public CMultiMethodProps
+ #else
+ public CCommonMethodProps
+ #endif
+{
+ CXzStatInfo _stat;
+ SRes MainDecodeSRes;
+
+ bool _isArc;
+ bool _needSeekToStart;
+ bool _phySize_Defined;
+ bool _firstBlockWasRead;
+
+ AString _methodsString;
+
+ #ifndef EXTRACT_ONLY
+
+ UInt32 _filterId;
+
+ UInt64 _numSolidBytes;
+
+ void InitXz()
+ {
+ _filterId = 0;
+ _numSolidBytes = XZ_PROPS__BLOCK_SIZE__AUTO;
+ }
+
+ #endif
+
+ void Init()
+ {
+ #ifndef EXTRACT_ONLY
+ InitXz();
+ CMultiMethodProps::Init();
+ #else
+ CCommonMethodProps::InitCommon();
+ #endif
+ }
+
+ HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
+
+ HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);
+
+ HRESULT Decode(NCompress::NXz::CDecoder &decoder,
+ ISequentialInStream *seqInStream,
+ ISequentialOutStream *outStream,
+ ICompressProgressInfo *progress)
+ {
+ #ifndef _7ZIP_ST
+ decoder._numThreads = _numThreads;
+ #endif
+ decoder._memUsage = _memUsage;
+
+ MainDecodeSRes = SZ_OK;
+
+ RINOK(decoder.Decode(seqInStream, outStream,
+ NULL, // *outSizeLimit
+ true, // finishStream
+ progress));
+
+ _stat = decoder.Stat;
+ MainDecodeSRes = decoder.MainDecodeSRes;
+
+ _phySize_Defined = true;
+ return S_OK;
+ }
+
+public:
+ MY_QUERYINTERFACE_BEGIN2(IInArchive)
+ MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
+ MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
+ MY_QUERYINTERFACE_ENTRY(ISetProperties)
+ #ifndef EXTRACT_ONLY
+ MY_QUERYINTERFACE_ENTRY(IOutArchive)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ INTERFACE_IInArchive(;)
+ STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
+
+ #ifndef EXTRACT_ONLY
+ INTERFACE_IOutArchive(;)
+ #endif
+
+ size_t _blocksArraySize;
+ CBlockInfo *_blocks;
+ UInt64 _maxBlocksSize;
+ CMyComPtr<IInStream> _stream;
+ CMyComPtr<ISequentialInStream> _seqStream;
+
+ CXzBlock _firstBlock;
+
+ CHandler();
+ ~CHandler();
+
+ HRESULT SeekToPackPos(UInt64 pos)
+ {
+ return _stream->Seek(pos, STREAM_SEEK_SET, NULL);
+ }
+};
+
+
+CHandler::CHandler():
+ _blocks(NULL),
+ _blocksArraySize(0)
+{
+ #ifndef EXTRACT_ONLY
+ InitXz();
+ #endif
+}
+
+CHandler::~CHandler()
+{
+ MyFree(_blocks);
+}
+
+
+static const Byte kProps[] =
+{
+ kpidSize,
+ kpidPackSize,
+ kpidMethod
+};
+
+static const Byte kArcProps[] =
+{
+ kpidMethod,
+ kpidNumStreams,
+ kpidNumBlocks,
+ kpidClusterSize,
+ kpidCharacts
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+static inline char GetHex(unsigned value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+static inline void AddHexToString(AString &s, Byte value)
+{
+ s += GetHex(value >> 4);
+ s += GetHex(value & 0xF);
+}
+
+static void Lzma2PropToString(AString &s, unsigned prop)
+{
+ char c = 0;
+ UInt32 size;
+ if ((prop & 1) == 0)
+ size = prop / 2 + 12;
+ else
+ {
+ c = 'k';
+ size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1);
+ if (prop > 17)
+ {
+ size >>= 10;
+ c = 'm';
+ }
+ }
+ s.Add_UInt32(size);
+ if (c != 0)
+ s += c;
+}
+
+struct CMethodNamePair
+{
+ UInt32 Id;
+ const char *Name;
+};
+
+static const CMethodNamePair g_NamePairs[] =
+{
+ { XZ_ID_Subblock, "SB" },
+ { XZ_ID_Delta, "Delta" },
+ { XZ_ID_X86, "BCJ" },
+ { XZ_ID_PPC, "PPC" },
+ { XZ_ID_IA64, "IA64" },
+ { XZ_ID_ARM, "ARM" },
+ { XZ_ID_ARMT, "ARMT" },
+ { XZ_ID_SPARC, "SPARC" },
+ { XZ_ID_LZMA2, "LZMA2" }
+};
+
+static void AddMethodString(AString &s, const CXzFilter &f)
+{
+ const char *p = NULL;
+ for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++)
+ if (g_NamePairs[i].Id == f.id)
+ {
+ p = g_NamePairs[i].Name;
+ break;
+ }
+ char temp[32];
+ if (!p)
+ {
+ ::ConvertUInt64ToString(f.id, temp);
+ p = temp;
+ }
+
+ s += p;
+
+ if (f.propsSize > 0)
+ {
+ s += ':';
+ if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)
+ Lzma2PropToString(s, f.props[0]);
+ else if (f.id == XZ_ID_Delta && f.propsSize == 1)
+ s.Add_UInt32((UInt32)f.props[0] + 1);
+ else
+ {
+ s += '[';
+ for (UInt32 bi = 0; bi < f.propsSize; bi++)
+ AddHexToString(s, f.props[bi]);
+ s += ']';
+ }
+ }
+}
+
+static const char * const kChecks[] =
+{
+ "NoCheck"
+ , "CRC32"
+ , NULL
+ , NULL
+ , "CRC64"
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , "SHA256"
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+};
+
+static void AddCheckString(AString &s, const CXzs &xzs)
+{
+ size_t i;
+ UInt32 mask = 0;
+ for (i = 0; i < xzs.num; i++)
+ mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags));
+ for (i = 0; i <= XZ_CHECK_MASK; i++)
+ if (((mask >> i) & 1) != 0)
+ {
+ s.Add_Space_if_NotEmpty();
+ if (kChecks[i])
+ s += kChecks[i];
+ else
+ {
+ s += "Check-";
+ s.Add_UInt32((UInt32)i);
+ }
+ }
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidPhySize: if (_phySize_Defined) prop = _stat.InSize; break;
+ case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break;
+ case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break;
+ case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
+ case kpidClusterSize: if (_stat.NumBlocks_Defined && _stat.NumBlocks > 1) prop = _maxBlocksSize; break;
+ case kpidCharacts:
+ if (_firstBlockWasRead)
+ {
+ AString s;
+ if (XzBlock_HasPackSize(&_firstBlock))
+ s.Add_OptSpaced("BlockPackSize");
+ if (XzBlock_HasUnpackSize(&_firstBlock))
+ s.Add_OptSpaced("BlockUnpackSize");
+ if (!s.IsEmpty())
+ prop = s;
+ }
+ break;
+
+
+ case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
+ case kpidErrorFlags:
+ {
+ UInt32 v = 0;
+ SRes sres = MainDecodeSRes; // _stat.DecodeRes2; //
+ if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
+ if (/*_stat.UnexpectedEnd */ sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd;
+ if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
+ if (/* _stat.HeadersError */ sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError;
+ if (/* _stat.Unsupported */ sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod;
+ if (/* _stat.DataError */ sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError;
+ if (/* _stat.CrcError */ sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError;
+ if (v != 0)
+ prop = v;
+ break;
+ }
+
+ case kpidMainSubfile:
+ {
+ // debug only, comment it:
+ // if (_blocks) prop = (UInt32)0;
+ break;
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
+ case kpidPackSize: if (_phySize_Defined) prop = _stat.InSize; break;
+ case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+
+struct COpenCallbackWrap
+{
+ ICompressProgress vt;
+ IArchiveOpenCallback *OpenCallback;
+ HRESULT Res;
+ COpenCallbackWrap(IArchiveOpenCallback *progress);
+};
+
+static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 /* outSize */)
+{
+ COpenCallbackWrap *p = CONTAINER_FROM_VTBL(pp, COpenCallbackWrap, vt);
+ if (p->OpenCallback)
+ p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);
+ return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
+}
+
+COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback)
+{
+ vt.Progress = OpenCallbackProgress;
+ OpenCallback = callback;
+ Res = SZ_OK;
+}
+
+
+struct CXzsCPP
+{
+ CXzs p;
+ CXzsCPP() { Xzs_Construct(&p); }
+ ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }
+};
+
+#define kInputBufSize ((size_t)1 << 10)
+
+struct CLookToRead2_CPP: public CLookToRead2
+{
+ CLookToRead2_CPP()
+ {
+ buf = NULL;
+ LookToRead2_CreateVTable(this,
+ True // Lookahead ?
+ );
+ }
+ void Alloc(size_t allocSize)
+ {
+ buf = (Byte *)MyAlloc(allocSize);
+ if (buf)
+ this->bufSize = allocSize;
+ }
+ ~CLookToRead2_CPP()
+ {
+ MyFree(buf);
+ }
+};
+
+
+static HRESULT SRes_to_Open_HRESULT(SRes res)
+{
+ switch (res)
+ {
+ case SZ_OK: return S_OK;
+ case SZ_ERROR_MEM: return E_OUTOFMEMORY;
+ case SZ_ERROR_PROGRESS: return E_ABORT;
+ /*
+ case SZ_ERROR_UNSUPPORTED:
+ case SZ_ERROR_CRC:
+ case SZ_ERROR_DATA:
+ case SZ_ERROR_ARCHIVE:
+ case SZ_ERROR_NO_ARCHIVE:
+ return S_FALSE;
+ */
+ }
+ return S_FALSE;
+}
+
+
+
+HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback)
+{
+ _needSeekToStart = true;
+
+ {
+ CXzStreamFlags st;
+ CSeqInStreamWrap inStreamWrap;
+
+ inStreamWrap.Init(inStream);
+ SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt);
+ if (res != SZ_OK)
+ return SRes_to_Open_HRESULT(res);
+
+ {
+ CXzBlock block;
+ Bool isIndex;
+ UInt32 headerSizeRes;
+ SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes);
+ if (res2 == SZ_OK && !isIndex)
+ {
+ _firstBlockWasRead = true;
+ _firstBlock = block;
+
+ unsigned numFilters = XzBlock_GetNumFilters(&block);
+ for (unsigned i = 0; i < numFilters; i++)
+ {
+ _methodsString.Add_Space_if_NotEmpty();
+ AddMethodString(_methodsString, block.filters[i]);
+ }
+ }
+ }
+ }
+
+ RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.InSize));
+ if (callback)
+ {
+ RINOK(callback->SetTotal(NULL, &_stat.InSize));
+ }
+
+ CSeekInStreamWrap inStreamImp;
+
+ inStreamImp.Init(inStream);
+
+ CLookToRead2_CPP lookStream;
+
+ lookStream.Alloc(kInputBufSize);
+
+ if (!lookStream.buf)
+ return E_OUTOFMEMORY;
+
+ lookStream.realStream = &inStreamImp.vt;
+ LookToRead2_Init(&lookStream);
+
+ COpenCallbackWrap openWrap(callback);
+
+ CXzsCPP xzs;
+ Int64 startPosition;
+ SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc);
+ if (res == SZ_ERROR_PROGRESS)
+ return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res;
+ /*
+ if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0)
+ res = SZ_OK;
+ */
+ if (res == SZ_OK && startPosition == 0)
+ {
+ _phySize_Defined = true;
+
+ _stat.OutSize = Xzs_GetUnpackSize(&xzs.p);
+ _stat.UnpackSize_Defined = true;
+
+ _stat.NumStreams = xzs.p.num;
+ _stat.NumStreams_Defined = true;
+
+ _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p);
+ _stat.NumBlocks_Defined = true;
+
+ AddCheckString(_methodsString, xzs.p);
+
+ const size_t numBlocks = (size_t)_stat.NumBlocks + 1;
+ const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo);
+
+ if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1)
+ {
+ _blocks = (CBlockInfo *)MyAlloc(bytesAlloc);
+ if (_blocks)
+ {
+ unsigned blockIndex = 0;
+ UInt64 unpackPos = 0;
+
+ for (size_t si = xzs.p.num; si != 0;)
+ {
+ si--;
+ const CXzStream &str = xzs.p.streams[si];
+ UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE;
+
+ for (size_t bi = 0; bi < str.numBlocks; bi++)
+ {
+ const CXzBlockSizes &bs = str.blocks[bi];
+ const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3);
+
+ if (bs.unpackSize != 0)
+ {
+ if (blockIndex >= _stat.NumBlocks)
+ return E_FAIL;
+
+ CBlockInfo &block = _blocks[blockIndex++];
+ block.StreamFlags = str.flags;
+ block.PackSize = bs.totalSize; // packSizeAligned;
+ block.PackPos = packPos;
+ block.UnpackPos = unpackPos;
+ }
+ packPos += packSizeAligned;
+ unpackPos += bs.unpackSize;
+ if (_maxBlocksSize < bs.unpackSize)
+ _maxBlocksSize = bs.unpackSize;
+ }
+ }
+
+ /*
+ if (blockIndex != _stat.NumBlocks)
+ {
+ // there are Empty blocks;
+ }
+ */
+ if (_stat.OutSize != unpackPos)
+ return E_FAIL;
+ CBlockInfo &block = _blocks[blockIndex++];
+ block.StreamFlags = 0;
+ block.PackSize = 0;
+ block.PackPos = 0;
+ block.UnpackPos = unpackPos;
+ _blocksArraySize = blockIndex;
+ }
+ }
+ }
+ else
+ {
+ res = SZ_OK;
+ }
+
+ RINOK(SRes_to_Open_HRESULT(res));
+ _stream = inStream;
+ _seqStream = inStream;
+ _isArc = true;
+ return S_OK;
+}
+
+
+
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+ COM_TRY_BEGIN
+ {
+ Close();
+ return Open2(inStream, callback);
+ }
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+ Close();
+ _seqStream = stream;
+ _isArc = true;
+ _needSeekToStart = false;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ XzStatInfo_Clear(&_stat);
+
+ _isArc = false;
+ _needSeekToStart = false;
+ _phySize_Defined = false;
+ _firstBlockWasRead = false;
+
+ _methodsString.Empty();
+ _stream.Release();
+ _seqStream.Release();
+
+ MyFree(_blocks);
+ _blocks = NULL;
+ _blocksArraySize = 0;
+ _maxBlocksSize = 0;
+
+ MainDecodeSRes = SZ_OK;
+
+ return S_OK;
+}
+
+
+struct CXzUnpackerCPP2
+{
+ Byte *InBuf;
+ // Byte *OutBuf;
+ CXzUnpacker p;
+
+ CXzUnpackerCPP2();
+ ~CXzUnpackerCPP2();
+};
+
+CXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL)
+ // , OutBuf(NULL)
+{
+ XzUnpacker_Construct(&p, &g_Alloc);
+}
+
+CXzUnpackerCPP2::~CXzUnpackerCPP2()
+{
+ XzUnpacker_Free(&p);
+ MidFree(InBuf);
+ // MidFree(OutBuf);
+}
+
+
+class CInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+public:
+ UInt64 _virtPos;
+ UInt64 Size;
+ UInt64 _cacheStartPos;
+ size_t _cacheSize;
+ CByteBuffer _cache;
+ // UInt64 _startPos;
+ CXzUnpackerCPP2 xz;
+
+ void InitAndSeek()
+ {
+ _virtPos = 0;
+ _cacheStartPos = 0;
+ _cacheSize = 0;
+ // _startPos = startPos;
+ }
+
+ CHandler *_handlerSpec;
+ CMyComPtr<IUnknown> _handler;
+
+ MY_UNKNOWN_IMP1(IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ ~CInStream();
+};
+
+
+CInStream::~CInStream()
+{
+ // _cache.Free();
+}
+
+
+size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos)
+{
+ size_t left = 0, right = numBlocks;
+ for (;;)
+ {
+ size_t mid = (left + right) / 2;
+ if (mid == left)
+ return left;
+ if (pos < blocks[mid].UnpackPos)
+ right = mid;
+ else
+ left = mid;
+ }
+}
+
+
+
+static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu,
+ ISequentialInStream *seqInStream,
+ unsigned streamFlags,
+ UInt64 packSize, // pure size from Index record, it doesn't include pad zeros
+ size_t unpackSize, Byte *dest
+ // , ICompressProgressInfo *progress
+ )
+{
+ const size_t kInBufSize = (size_t)1 << 16;
+
+ XzUnpacker_Init(&xzu.p);
+
+ if (!xzu.InBuf)
+ {
+ xzu.InBuf = (Byte *)MidAlloc(kInBufSize);
+ if (!xzu.InBuf)
+ return E_OUTOFMEMORY;
+ }
+
+ xzu.p.streamFlags = (UInt16)streamFlags;
+ XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p);
+
+ XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize);
+
+ const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
+ UInt64 packRem = packSizeAligned;
+
+ UInt32 inSize = 0;
+ SizeT inPos = 0;
+ SizeT outPos = 0;
+
+ HRESULT readRes = S_OK;
+
+ for (;;)
+ {
+ if (inPos == inSize && readRes == S_OK)
+ {
+ inPos = 0;
+ inSize = 0;
+ UInt32 rem = kInBufSize;
+ if (rem > packRem)
+ rem = (UInt32)packRem;
+ if (rem != 0)
+ readRes = seqInStream->Read(xzu.InBuf, rem, &inSize);
+ }
+
+ SizeT inLen = inSize - inPos;
+ SizeT outLen = unpackSize - outPos;
+
+ ECoderStatus status;
+
+ SRes res = XzUnpacker_Code(&xzu.p,
+ // dest + outPos,
+ NULL,
+ &outLen,
+ xzu.InBuf + inPos, &inLen,
+ (inLen == 0), // srcFinished
+ CODER_FINISH_END, &status);
+
+ // return E_OUTOFMEMORY;
+ // res = SZ_ERROR_CRC;
+
+ if (res != SZ_OK)
+ {
+ if (res == SZ_ERROR_CRC)
+ return S_FALSE;
+ return SResToHRESULT(res);
+ }
+
+ inPos += inLen;
+ outPos += outLen;
+
+ packRem -= inLen;
+
+ Bool blockFinished = XzUnpacker_IsBlockFinished(&xzu.p);
+
+ if ((inLen == 0 && outLen == 0) || blockFinished)
+ {
+ if (packRem != 0 || !blockFinished || unpackSize != outPos)
+ return S_FALSE;
+ if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize)
+ return S_FALSE;
+ return S_OK;
+ }
+ }
+}
+
+
+STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ COM_TRY_BEGIN
+
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+
+ {
+ if (_virtPos >= Size)
+ return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL;
+ {
+ UInt64 rem = Size - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ }
+
+ if (size == 0)
+ return S_OK;
+
+ if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize)
+ {
+ size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos);
+ const CBlockInfo &block = _handlerSpec->_blocks[bi];
+ const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos;
+ if (_cache.Size() < unpackSize)
+ return E_FAIL;
+
+ _cacheSize = 0;
+
+ RINOK(_handlerSpec->SeekToPackPos(block.PackPos));
+ RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize,
+ (size_t)unpackSize, _cache));
+ _cacheStartPos = block.UnpackPos;
+ _cacheSize = (size_t)unpackSize;
+ }
+
+ {
+ size_t offset = (size_t)(_virtPos - _cacheStartPos);
+ size_t rem = _cacheSize - offset;
+ if (size > rem)
+ size = (UInt32)rem;
+ memcpy(data, _cache + offset, size);
+ _virtPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ }
+
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CInStream::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 += 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 const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40;
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ COM_TRY_BEGIN
+
+ *stream = NULL;
+
+ if (index != 0)
+ return E_INVALIDARG;
+
+ if (!_stat.UnpackSize_Defined
+ || _maxBlocksSize == 0 // 18.02
+ || _maxBlocksSize > kMaxBlockSize_for_GetStream
+ || _maxBlocksSize != (size_t)_maxBlocksSize)
+ return S_FALSE;
+
+ UInt64 memSize;
+ if (!NSystem::GetRamSize(memSize))
+ memSize = (UInt64)(sizeof(size_t)) << 28;
+ {
+ if (_maxBlocksSize > memSize / 4)
+ return S_FALSE;
+ }
+
+ CInStream *spec = new CInStream;
+ CMyComPtr<ISequentialInStream> specStream = spec;
+ spec->_cache.Alloc((size_t)_maxBlocksSize);
+ spec->_handlerSpec = this;
+ spec->_handler = (IInArchive *)this;
+ spec->Size = _stat.OutSize;
+ spec->InitAndSeek();
+
+ *stream = specStream.Detach();
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder)
+{
+ Int32 opRes;
+ SRes sres = decoder.MainDecodeSRes; // decoder.Stat.DecodeRes2;
+ if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc)
+ opRes = NExtract::NOperationResult::kIsNotArc;
+ else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd)
+ opRes = NExtract::NOperationResult::kUnexpectedEnd;
+ else if (decoder.Stat.DataAfterEnd)
+ opRes = NExtract::NOperationResult::kDataAfterEnd;
+ else if (sres == SZ_ERROR_CRC) // (CrcError)
+ opRes = NExtract::NOperationResult::kCRCError;
+ else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported)
+ opRes = NExtract::NOperationResult::kUnsupportedMethod;
+ else if (sres == SZ_ERROR_ARCHIVE) // (HeadersError)
+ opRes = NExtract::NOperationResult::kDataError;
+ else if (sres == SZ_ERROR_DATA) // (DataError)
+ opRes = NExtract::NOperationResult::kDataError;
+ else if (sres != 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)
+{
+ COM_TRY_BEGIN
+ if (numItems == 0)
+ return S_OK;
+ if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
+ return E_INVALIDARG;
+
+ if (_phySize_Defined)
+ extractCallback->SetTotal(_stat.InSize);
+
+ UInt64 currentTotalPacked = 0;
+ RINOK(extractCallback->SetCompleted(&currentTotalPacked));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+
+ RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+
+ if (!testMode && !realOutStream)
+ return S_OK;
+
+ extractCallback->PrepareOperation(askMode);
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> lpsRef = lps;
+ lps->Init(extractCallback, true);
+
+ if (_needSeekToStart)
+ {
+ if (!_stream)
+ return E_FAIL;
+ RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+ else
+ _needSeekToStart = true;
+
+
+ NCompress::NXz::CDecoder decoder;
+
+ HRESULT hres = Decode(decoder, _seqStream, realOutStream, lpsRef);
+
+ if (!decoder.MainDecodeSRes_wasUsed)
+ return hres == S_OK ? E_FAIL : hres;
+
+ Int32 opRes = Get_Extract_OperationResult(decoder);
+ if (opRes == NExtract::NOperationResult::kOK
+ && hres != S_OK)
+ opRes = NExtract::NOperationResult::kDataError;
+
+ realOutStream.Release();
+ return extractCallback->SetOperationResult(opRes);
+ COM_TRY_END
+}
+
+
+
+#ifndef EXTRACT_ONLY
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
+{
+ *timeType = NFileTimeType::kUnix;
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ COM_TRY_BEGIN
+
+ if (numItems == 0)
+ {
+ CSeqOutStreamWrap seqOutStream;
+ seqOutStream.Init(outStream);
+ SRes res = Xz_EncodeEmpty(&seqOutStream.vt);
+ return SResToHRESULT(res);
+ }
+
+ if (numItems != 1)
+ return E_INVALIDARG;
+
+ Int32 newData, newProps;
+ UInt32 indexInArchive;
+ if (!updateCallback)
+ return E_FAIL;
+ RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
+
+ if (IntToBool(newProps))
+ {
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
+ if (prop.vt != VT_EMPTY)
+ if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
+ return E_INVALIDARG;
+ }
+ }
+
+ if (IntToBool(newData))
+ {
+ UInt64 size;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ size = prop.uhVal.QuadPart;
+ RINOK(updateCallback->SetTotal(size));
+ }
+
+ NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+ CXzProps &xzProps = encoderSpec->xzProps;
+ CLzma2EncProps &lzma2Props = xzProps.lzma2Props;
+
+ lzma2Props.lzmaProps.level = GetLevel();
+
+ xzProps.reduceSize = size;
+ /*
+ {
+ NCOM::CPropVariant prop = (UInt64)size;
+ RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop));
+ }
+ */
+
+ #ifndef _7ZIP_ST
+ xzProps.numTotalThreads = _numThreads;
+ #endif
+
+ xzProps.blockSize = _numSolidBytes;
+ if (_numSolidBytes == XZ_PROPS__BLOCK_SIZE__SOLID)
+ {
+ xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID;
+ }
+
+ RINOK(encoderSpec->SetCheckSize(_crcSize));
+
+ {
+ CXzFilterProps &filter = xzProps.filterProps;
+
+ if (_filterId == XZ_ID_Delta)
+ {
+ bool deltaDefined = false;
+ FOR_VECTOR (j, _filterMethod.Props)
+ {
+ const CProp &prop = _filterMethod.Props[j];
+ if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
+ {
+ UInt32 delta = (UInt32)prop.Value.ulVal;
+ if (delta < 1 || delta > 256)
+ return E_INVALIDARG;
+ filter.delta = delta;
+ deltaDefined = true;
+ }
+ else
+ return E_INVALIDARG;
+ }
+ if (!deltaDefined)
+ return E_INVALIDARG;
+ }
+ filter.id = _filterId;
+ }
+
+ FOR_VECTOR (i, _methods)
+ {
+ COneMethodInfo &m = _methods[i];
+
+ FOR_VECTOR (j, m.Props)
+ {
+ const CProp &prop = m.Props[j];
+ RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value));
+ }
+ }
+
+ CMyComPtr<ISequentialInStream> fileInStream;
+ RINOK(updateCallback->GetStream(0, &fileInStream));
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress);
+ }
+
+ 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.InSize));
+ RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(updateCallback, true);
+
+ return NCompress::CopyStream(_stream, outStream, progress);
+
+ COM_TRY_END
+}
+
+#endif
+
+
+HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
+{
+ UString name = nameSpec;
+ name.MakeLower_Ascii();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ #ifndef EXTRACT_ONLY
+
+ if (name[0] == L's')
+ {
+ const wchar_t *s = name.Ptr(1);
+ if (*s == 0)
+ {
+ bool useStr = false;
+ bool isSolid;
+ switch (value.vt)
+ {
+ case VT_EMPTY: isSolid = true; break;
+ case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;
+ case VT_BSTR:
+ if (!StringToBool(value.bstrVal, isSolid))
+ useStr = true;
+ break;
+ default: return E_INVALIDARG;
+ }
+ if (!useStr)
+ {
+ _numSolidBytes = (isSolid ? XZ_PROPS__BLOCK_SIZE__SOLID : XZ_PROPS__BLOCK_SIZE__AUTO);
+ return S_OK;
+ }
+ }
+ return ParseSizeString(s, value,
+ 0, // percentsBase
+ _numSolidBytes) ? S_OK: E_INVALIDARG;
+ }
+
+ return CMultiMethodProps::SetProperty(name, value);
+
+ #else
+
+ {
+ HRESULT hres;
+ if (SetCommonProperty(name, value, hres))
+ return hres;
+ }
+
+ return E_INVALIDARG;
+
+ #endif
+}
+
+
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
+{
+ COM_TRY_BEGIN
+
+ Init();
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ RINOK(SetProperty(names[i], values[i]));
+ }
+
+ #ifndef EXTRACT_ONLY
+
+ if (!_filterMethod.MethodName.IsEmpty())
+ {
+ unsigned k;
+ for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++)
+ {
+ const CMethodNamePair &pair = g_NamePairs[k];
+ if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name))
+ {
+ _filterId = pair.Id;
+ break;
+ }
+ }
+ if (k == ARRAY_SIZE(g_NamePairs))
+ return E_INVALIDARG;
+ }
+
+ _methods.DeleteFrontal(GetNumEmptyMethods());
+ if (_methods.Size() > 1)
+ return E_INVALIDARG;
+ if (_methods.Size() == 1)
+ {
+ AString &methodName = _methods[0].MethodName;
+ if (methodName.IsEmpty())
+ methodName = k_LZMA2_Name;
+ else if (
+ !methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name)
+ && !methodName.IsEqualTo_Ascii_NoCase("xz"))
+ return E_INVALIDARG;
+ }
+
+ #endif
+
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+REGISTER_ARC_IO(
+ "xz", "xz txz", "* .tar", 0xC,
+ XZ_SIG,
+ 0,
+ NArcInfoFlags::kKeepName,
+ NULL)
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.h b/other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.h
new file mode 100644
index 0000000000..18633fbc99
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.h
@@ -0,0 +1,11 @@
+// XzHandler.h
+
+#ifndef __XZ_HANDLER_H
+#define __XZ_HANDLER_H
+
+namespace NArchive {
+namespace NXz {
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Asm.mak b/other-licenses/7zstub/src/CPP/7zip/Asm.mak
new file mode 100644
index 0000000000..3ad238a8e9
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Asm.mak
@@ -0,0 +1,9 @@
+!IFDEF ASM_OBJS
+!IF "$(CPU)" == "ARM"
+$(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm
+ $(COMPL_ASM)
+!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM64"
+$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm
+ $(COMPL_ASM)
+!ENDIF
+!ENDIF
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsp b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsp
new file mode 100644
index 0000000000..6147e10568
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsp
@@ -0,0 +1,1901 @@
+# Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Alone - Win32 DebugU
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Alone.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application")
+!MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Alone - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /Gr /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAc /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Alone - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gr /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /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
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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\7zr.exe" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseU"
+# PROP BASE Intermediate_Dir "ReleaseU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseU"
+# PROP Intermediate_Dir "ReleaseU"
+# 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 /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /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
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98
+# SUBTRACT BASE LINK32 /pdb:none
+# 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 /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugU"
+# PROP BASE Intermediate_Dir "DebugU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugU"
+# PROP Intermediate_Dir "DebugU"
+# 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 /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /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
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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\7za.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\7zr.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Alone - Win32 Release"
+# Name "Alone - Win32 Debug"
+# Name "Alone - Win32 ReleaseU"
+# Name "Alone - Win32 DebugU"
+# Begin Group "Console"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ArError.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\BenchCon.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\BenchCon.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\CompressionMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ConsoleClose.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ConsoleClose.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\HashCon.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\HashCon.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\List.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\List.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\Main.cpp
+# ADD CPP /D "PROG_VARIANT_R"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\MainAr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+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\UpdateCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\UpdateCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\UserInputUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\UserInputUtils.h
+# End Source File
+# End Group
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\AutoPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Buffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ComTry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CrcReg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynamicBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ListFileUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ListFileUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyCom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyException.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyGuidDef.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyInitGuid.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyUnknown.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Sha256Reg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\XzCrc64Init.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\XzCrc64Reg.cpp
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Device.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ErrorMsg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ErrorMsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileLink.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileMapping.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileSystem.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileSystem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Handle.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryLock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryLock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConv.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Thread.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\TimeUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\TimeUtils.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# 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
+
+SOURCE=..\..\Common\FilePathAutoRename.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+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\InBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.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\LimitedStreams.cpp
+# End Source File
+# Begin Source File
+
+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\MethodId.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodId.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodProps.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodProps.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OffsetStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OffsetStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\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
+
+SOURCE=..\..\Common\StreamBinder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamObjects.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamObjects.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\UniqBlocks.cpp
+# End Source File
+# Begin Source File
+
+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 "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Coder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Coder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjRegister.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\Compress\ByteSwap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\ByteSwap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\CopyCoder.h
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\Compress\Lzma2Decoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma2Encoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma2Encoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma2Register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaDecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaEncoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaEncoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\XzDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\XzDecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\XzEncoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\XzEncoder.h
+# End Source File
+# End Group
+# Begin Group "Archive"
+
+# PROP Default_Filter ""
+# Begin Group "7z"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+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\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\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\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
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+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
+# Begin Source File
+
+SOURCE=..\..\Archive\LzmaHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\SplitHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\XzHandler.cpp
+# End Source File
+# End Group
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveCommandLine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Bench.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Bench.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\EnumDirItems.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\EnumDirItems.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Extract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Extract.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractingFilePath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\HashCalc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\HashCalc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Property.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\PropIDUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\PropIDUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\SetProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\SetProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\SortUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\SortUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\TempFiles.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\TempFiles.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Update.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Update.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateAction.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateAction.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdatePair.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdatePair.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateProduce.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateProduce.h
+# End Source File
+# End Group
+# Begin Group "7-zip"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\ICoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IMyUnknown.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IPassword.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IProgress.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\PropID.h
+# End Source File
+# End Group
+# Begin Group "C"
+
+# PROP Default_Filter ""
+# Begin Group "Xz"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sha256.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\Sha256.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Xz.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\Xz.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\XzCrc64.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\XzCrc64.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\XzCrc64Opt.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\XzDec.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\XzEnc.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\XzEnc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\XzIn.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
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrcOpt.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"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zStream.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Aes.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\Aes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\AesOpt.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\Alloc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+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
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bra.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Bra86.c
+# SUBTRACT CPP /YX /Yc /Yu
+# 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
+
+!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"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Alone - Win32 DebugU"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\CpuArch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Delta.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\Delta.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\IStream.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\Compress\Lz\LzHash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzHash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2Dec.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\Lzma2Dec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.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\Lzma2DecMt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2Enc.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\Lzma2Enc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\LzmaDec.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\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\MtCoder.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\MtCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\MtDec.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\MtDec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Types.h
+# End Source File
+# End Group
+# Begin Group "Crypto"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAesRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\MyAes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\MyAes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\RandGen.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\RandGen.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsw b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsw
new file mode 100644
index 0000000000..036aab454c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Alone"=.\Alone.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/makefile b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/makefile
new file mode 100644
index 0000000000..91ee1922dd
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/makefile
@@ -0,0 +1,158 @@
+PROG = 7zr.exe
+MY_CONSOLE = 1
+CFLAGS = $(CFLAGS) -DPROG_VARIANT_R
+
+!IFNDEF UNDER_CE
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE
+!ENDIF
+
+COMMON_OBJS = \
+ $O\CommandLineParser.obj \
+ $O\CRC.obj \
+ $O\CrcReg.obj \
+ $O\IntToString.obj \
+ $O\ListFileUtils.obj \
+ $O\NewHandler.obj \
+ $O\StdInStream.obj \
+ $O\StdOutStream.obj \
+ $O\MyString.obj \
+ $O\Sha256Reg.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\UTFConvert.obj \
+ $O\MyVector.obj \
+ $O\Wildcard.obj \
+ $O\XzCrc64Init.obj \
+ $O\XzCrc64Reg.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\ErrorMsg.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileLink.obj \
+ $O\FileName.obj \
+ $O\FileSystem.obj \
+ $O\MemoryLock.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConv.obj \
+ $O\Synchronization.obj \
+ $O\System.obj \
+ $O\TimeUtils.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\CreateCoder.obj \
+ $O\CWrappers.obj \
+ $O\FilePathAutoRename.obj \
+ $O\FileStreams.obj \
+ $O\InBuffer.obj \
+ $O\InOutTempBuffer.obj \
+ $O\FilterCoder.obj \
+ $O\LimitedStreams.obj \
+ $O\MethodId.obj \
+ $O\MethodProps.obj \
+ $O\OffsetStream.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\PropId.obj \
+ $O\StreamBinder.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+ $O\UniqBlocks.obj \
+ $O\VirtThread.obj \
+
+AR_OBJS = \
+ $O\LzmaHandler.obj \
+ $O\SplitHandler.obj \
+ $O\XzHandler.obj \
+
+AR_COMMON_OBJS = \
+ $O\CoderMixer2.obj \
+ $O\DummyOutStream.obj \
+ $O\HandlerOut.obj \
+ $O\InStreamWithCRC.obj \
+ $O\ItemNameUtils.obj \
+ $O\MultiStream.obj \
+ $O\OutStreamWithCRC.obj \
+ $O\ParseProperties.obj \
+
+
+7Z_OBJS = \
+ $O\7zCompressionMode.obj \
+ $O\7zDecode.obj \
+ $O\7zEncode.obj \
+ $O\7zExtract.obj \
+ $O\7zFolderInStream.obj \
+ $O\7zHandler.obj \
+ $O\7zHandlerOut.obj \
+ $O\7zHeader.obj \
+ $O\7zIn.obj \
+ $O\7zOut.obj \
+ $O\7zProperties.obj \
+ $O\7zRegister.obj \
+ $O\7zSpecStream.obj \
+ $O\7zUpdate.obj \
+
+COMPRESS_OBJS = \
+ $O\Bcj2Coder.obj \
+ $O\Bcj2Register.obj \
+ $O\BcjCoder.obj \
+ $O\BcjRegister.obj \
+ $O\BranchMisc.obj \
+ $O\BranchRegister.obj \
+ $O\ByteSwap.obj \
+ $O\CopyCoder.obj \
+ $O\CopyRegister.obj \
+ $O\DeltaFilter.obj \
+ $O\Lzma2Decoder.obj \
+ $O\Lzma2Encoder.obj \
+ $O\Lzma2Register.obj \
+ $O\LzmaDecoder.obj \
+ $O\LzmaEncoder.obj \
+ $O\LzmaRegister.obj \
+ $O\XzDecoder.obj \
+ $O\XzEncoder.obj \
+
+CRYPTO_OBJS = \
+ $O\7zAes.obj \
+ $O\7zAesRegister.obj \
+ $O\MyAes.obj \
+ $O\MyAesReg.obj \
+ $O\RandGen.obj \
+
+C_OBJS = \
+ $O\7zStream.obj \
+ $O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bcj2Enc.obj \
+ $O\Bra.obj \
+ $O\Bra86.obj \
+ $O\BraIA64.obj \
+ $O\CpuArch.obj \
+ $O\Delta.obj \
+ $O\LzFind.obj \
+ $O\LzFindMt.obj \
+ $O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
+ $O\Lzma2Enc.obj \
+ $O\LzmaDec.obj \
+ $O\LzmaEnc.obj \
+ $O\MtCoder.obj \
+ $O\MtDec.obj \
+ $O\Sha256.obj \
+ $O\Sort.obj \
+ $O\Threads.obj \
+ $O\Xz.obj \
+ $O\XzDec.obj \
+ $O\XzEnc.obj \
+ $O\XzIn.obj \
+
+!include "../../UI/Console/Console.mak"
+
+!include "../../Aes.mak"
+!include "../../Crc.mak"
+!include "../../Crc64.mak"
+!include "../../LzmaDec.mak"
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/resource.rc b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/resource.rc
new file mode 100644
index 0000000000..36d70e7d9c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/resource.rc
@@ -0,0 +1,7 @@
+#include "../../../../C/7zVersion.rc"
+
+MY_VERSION_INFO_APP("7-Zip Reduced Standalone Console", "7zr")
+
+#ifndef UNDER_CE
+1 24 MOVEABLE PURE "../../UI/Console/Console.manifest"
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/makefile b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/makefile
new file mode 100644
index 0000000000..3a7f981699
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/makefile
@@ -0,0 +1,96 @@
+PROG = 7zxr.dll
+DEF_FILE = ../../Archive/Archive2.def
+CFLAGS = $(CFLAGS) \
+ -DEXTRACT_ONLY \
+ -D_NO_CRYPTO
+
+COMMON_OBJS = \
+ $O\CRC.obj \
+ $O\CrcReg.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\MyString.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\MyVector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+ $O\Synchronization.obj \
+ $O\System.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\CreateCoder.obj \
+ $O\CWrappers.obj \
+ $O\InBuffer.obj \
+ $O\FilterCoder.obj \
+ $O\LimitedStreams.obj \
+ $O\MethodId.obj \
+ $O\MethodProps.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\PropId.obj \
+ $O\StreamBinder.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+ $O\VirtThread.obj \
+
+AR_OBJS = \
+ $O\ArchiveExports.obj \
+ $O\DllExports2.obj \
+
+AR_COMMON_OBJS = \
+ $O\CoderMixer2.obj \
+ $O\HandlerOut.obj \
+ $O\ItemNameUtils.obj \
+ $O\OutStreamWithCRC.obj \
+ $O\ParseProperties.obj \
+
+
+7Z_OBJS = \
+ $O\7zCompressionMode.obj \
+ $O\7zDecode.obj \
+ $O\7zExtract.obj \
+ $O\7zHandler.obj \
+ $O\7zHeader.obj \
+ $O\7zIn.obj \
+ $O\7zProperties.obj \
+ $O\7zRegister.obj \
+
+
+COMPRESS_OBJS = \
+ $O\CodecExports.obj \
+ $O\Bcj2Coder.obj \
+ $O\Bcj2Register.obj \
+ $O\BcjCoder.obj \
+ $O\BcjRegister.obj \
+ $O\BranchMisc.obj \
+ $O\BranchRegister.obj \
+ $O\ByteSwap.obj \
+ $O\CopyCoder.obj \
+ $O\CopyRegister.obj \
+ $O\DeltaFilter.obj \
+ $O\Lzma2Decoder.obj \
+ $O\Lzma2Register.obj \
+ $O\LzmaDecoder.obj \
+ $O\LzmaRegister.obj \
+
+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\Lzma2DecMt.obj \
+ $O\LzmaDec.obj \
+ $O\MtDec.obj \
+ $O\Threads.obj \
+
+!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/resource.rc b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/resource.rc
new file mode 100644
index 0000000000..dac02a6766
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/resource.rc
@@ -0,0 +1,5 @@
+#include "../../../../C/7zVersion.rc"
+
+MY_VERSION_INFO_DLL("7z Extracting Reduced Standalone Plugin", "7zxr")
+
+101 ICON "../../Archive/Icons/7z.ico"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/makefile b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/makefile
new file mode 100644
index 0000000000..6a9dfb9199
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/makefile
@@ -0,0 +1,116 @@
+PROG = 7zra.dll
+DEF_FILE = ../../Archive/Archive2.def
+CFLAGS = $(CFLAGS) \
+ -D_NO_CRYPTO
+
+COMMON_OBJS = \
+ $O\CRC.obj \
+ $O\CrcReg.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\MyString.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\MyVector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\PropVariant.obj \
+ $O\Synchronization.obj \
+ $O\System.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\CreateCoder.obj \
+ $O\CWrappers.obj \
+ $O\InBuffer.obj \
+ $O\InOutTempBuffer.obj \
+ $O\FilterCoder.obj \
+ $O\LimitedStreams.obj \
+ $O\MethodId.obj \
+ $O\MethodProps.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\PropId.obj \
+ $O\StreamBinder.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+ $O\UniqBlocks.obj \
+ $O\VirtThread.obj \
+
+AR_OBJS = \
+ $O\ArchiveExports.obj \
+ $O\DllExports2.obj \
+
+AR_COMMON_OBJS = \
+ $O\CoderMixer2.obj \
+ $O\HandlerOut.obj \
+ $O\InStreamWithCRC.obj \
+ $O\ItemNameUtils.obj \
+ $O\OutStreamWithCRC.obj \
+ $O\ParseProperties.obj \
+
+
+7Z_OBJS = \
+ $O\7zCompressionMode.obj \
+ $O\7zDecode.obj \
+ $O\7zEncode.obj \
+ $O\7zExtract.obj \
+ $O\7zFolderInStream.obj \
+ $O\7zHandler.obj \
+ $O\7zHandlerOut.obj \
+ $O\7zHeader.obj \
+ $O\7zIn.obj \
+ $O\7zOut.obj \
+ $O\7zProperties.obj \
+ $O\7zSpecStream.obj \
+ $O\7zUpdate.obj \
+ $O\7zRegister.obj \
+
+
+COMPRESS_OBJS = \
+ $O\CodecExports.obj \
+ $O\Bcj2Coder.obj \
+ $O\Bcj2Register.obj \
+ $O\BcjCoder.obj \
+ $O\BcjRegister.obj \
+ $O\BranchMisc.obj \
+ $O\BranchRegister.obj \
+ $O\ByteSwap.obj \
+ $O\CopyCoder.obj \
+ $O\CopyRegister.obj \
+ $O\DeltaFilter.obj \
+ $O\Lzma2Decoder.obj \
+ $O\Lzma2Encoder.obj \
+ $O\Lzma2Register.obj \
+ $O\LzmaDecoder.obj \
+ $O\LzmaEncoder.obj \
+ $O\LzmaRegister.obj \
+
+C_OBJS = \
+ $O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bcj2Enc.obj \
+ $O\Bra.obj \
+ $O\Bra86.obj \
+ $O\BraIA64.obj \
+ $O\CpuArch.obj \
+ $O\Delta.obj \
+ $O\LzFind.obj \
+ $O\LzFindMt.obj \
+ $O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
+ $O\Lzma2Enc.obj \
+ $O\LzmaDec.obj \
+ $O\LzmaEnc.obj \
+ $O\MtCoder.obj \
+ $O\MtDec.obj \
+ $O\Threads.obj \
+
+!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/resource.rc b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/resource.rc
new file mode 100644
index 0000000000..262125c122
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/resource.rc
@@ -0,0 +1,5 @@
+#include "../../../../C/7zVersion.rc"
+
+MY_VERSION_INFO_DLL("7z Reduced Standalone Plugin", "7zr")
+
+101 ICON "../../Archive/Icons/7z.ico"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
new file mode 100644
index 0000000000..f27333741f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -0,0 +1,799 @@
+// LzmaAlone.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "../../../../C/CpuArch.h"
+
+#if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE)
+#include <fcntl.h>
+#include <io.h>
+#define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY)
+#else
+#define MY_SET_BINARY_MODE(file)
+#endif
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../../C/7zVersion.h"
+#include "../../../../C/Alloc.h"
+#include "../../../../C/Lzma86.h"
+
+#include "../../../Windows/NtCheck.h"
+
+#ifndef _7ZIP_ST
+#include "../../../Windows/System.h"
+#endif
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Compress/LzmaDecoder.h"
+#include "../../Compress/LzmaEncoder.h"
+
+#include "../../UI/Console/BenchCon.h"
+#include "../../UI/Console/ConsoleClose.h"
+
+bool g_LargePagesMode = false;
+
+using namespace NCommandLineParser;
+
+static const unsigned kDictSizeLog = 24;
+
+#define kCopyrightString "\nLZMA " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
+
+static const char * const 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 * const kCantAllocate = "Can not allocate memory";
+static const char * const kReadError = "Read error";
+static const char * const kWriteError = "Write error";
+
+
+namespace NKey {
+enum Enum
+{
+ kHelp1 = 0,
+ kHelp2,
+ kMethod,
+ kLevel,
+ kAlgo,
+ kDict,
+ kFb,
+ kMc,
+ kLc,
+ kLp,
+ kPb,
+ kMatchFinder,
+ kMultiThread,
+ kEOS,
+ kStdIn,
+ kStdOut,
+ kFilter86
+};
+}
+
+static const CSwitchForm kSwitchForms[] =
+{
+ { "?", NSwitchType::kSimple, false },
+ { "H", NSwitchType::kSimple, false },
+ { "MM", NSwitchType::kString, false, 1 },
+ { "X", NSwitchType::kString, false, 1 },
+ { "A", NSwitchType::kString, false, 1 },
+ { "D", NSwitchType::kString, false, 1 },
+ { "FB", NSwitchType::kString, false, 1 },
+ { "MC", NSwitchType::kString, false, 1 },
+ { "LC", NSwitchType::kString, false, 1 },
+ { "LP", NSwitchType::kString, false, 1 },
+ { "PB", NSwitchType::kString, false, 1 },
+ { "MF", NSwitchType::kString, false, 1 },
+ { "MT", NSwitchType::kString, false, 0 },
+ { "EOS", NSwitchType::kSimple, false },
+ { "SI", NSwitchType::kSimple, false },
+ { "SO", NSwitchType::kSimple, false },
+ { "F86", NSwitchType::kChar, false, 0, "+" }
+};
+
+
+static void Convert_UString_to_AString(const UString &s, AString &temp)
+{
+ int codePage = CP_OEMCP;
+ /*
+ int g_CodePage = -1;
+ int codePage = g_CodePage;
+ if (codePage == -1)
+ codePage = CP_OEMCP;
+ if (codePage == CP_UTF8)
+ ConvertUnicodeToUTF8(s, temp);
+ else
+ */
+ UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
+}
+
+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 UString &s2)
+{
+ PrintError(s1);
+ AString a;
+ Convert_UString_to_AString(s2, a);
+ PrintErr_LF(a);
+}
+
+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()
+{
+ PrintTitle();
+ Print(kHelpString);
+}
+
+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 * const kBackSpaces =
+BACK_STR
+" "
+BACK_STR;
+
+
+void CProgressPrint::ClosePrint()
+{
+ Print(kBackSpaces);
+}
+
+STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ 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 IncorrectCommand()
+{
+ throw "Incorrect command";
+}
+
+static UInt32 GetNumber(const wchar_t *s)
+{
+ const wchar_t *end;
+ 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)
+ res = GetNumber(parser[index].PostStrings[0]);
+}
+
+
+static int Error_HRESULT(const char *s, HRESULT res)
+{
+ if (res == E_ABORT)
+ {
+ Print("\n\nBreak signaled\n");
+ return 255;
+ }
+
+ 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 = name;
+ prop.Value = val;
+}
+
+static int main2(int numArgs, const char *args[])
+{
+ NT_CHECK
+
+ if (numArgs == 1)
+ {
+ PrintHelp();
+ return 0;
+ }
+
+ /*
+ bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8);
+ if (unsupportedTypes)
+ throw "Unsupported base types. Edit Common/Types.h and recompile";
+ */
+
+ UStringVector commandStrings;
+ for (int i = 1; i < numArgs; i++)
+ commandStrings.Add(MultiByteToUnicodeString(args[i]));
+
+ CParser parser;
+ try
+ {
+ if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings))
+ {
+ PrintError2(parser.ErrorMessage, parser.ErrorLine);
+ return 1;
+ }
+ }
+ catch(...)
+ {
+ IncorrectCommand();
+ }
+
+ if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
+ {
+ PrintHelp();
+ return 0;
+ }
+
+ 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 >= params.Size())
+ IncorrectCommand();
+ const UString &command = params[paramIndex++];
+
+ CObjectVector<CProperty> props2;
+ bool dictDefined = false;
+ UInt32 dict = (UInt32)(Int32)-1;
+
+ if (parser[NKey::kDict].ThereIs)
+ {
+ UInt32 dictLog;
+ const UString &s = parser[NKey::kDict].PostStrings[0];
+ dictLog = GetNumber(s);
+ dict = 1 << dictLog;
+ dictDefined = true;
+ AddProp(props2, "d", s);
+ }
+
+ if (parser[NKey::kLevel].ThereIs)
+ {
+ const UString &s = parser[NKey::kLevel].PostStrings[0];
+ /* UInt32 level = */ GetNumber(s);
+ AddProp(props2, "x", s);
+ }
+
+ UString mf ("BT4");
+ if (parser[NKey::kMatchFinder].ThereIs)
+ mf = parser[NKey::kMatchFinder].PostStrings[0];
+
+ UInt32 numThreads = (UInt32)(Int32)-1;
+
+ #ifndef _7ZIP_ST
+
+ if (parser[NKey::kMultiThread].ThereIs)
+ {
+ const UString &s = parser[NKey::kMultiThread].PostStrings[0];
+ if (s.IsEmpty())
+ numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ else
+ numThreads = GetNumber(s);
+ AddProp(props2, "mt", s);
+ }
+
+ #endif
+
+
+ if (parser[NKey::kMethod].ThereIs)
+ {
+ const UString &s = parser[NKey::kMethod].PostStrings[0];
+ if (s.IsEmpty() || s[0] != '=')
+ IncorrectCommand();
+ AddProp(props2, "m", s.Ptr(1));
+ }
+
+ if (StringsAreEqualNoCase_Ascii(command, "b"))
+ {
+ 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 (StringsAreEqualNoCase_Ascii(command, "e"))
+ encodeMode = true;
+ else if (!StringsAreEqualNoCase_Ascii(command, "d"))
+ IncorrectCommand();
+
+ CMyComPtr<ISequentialInStream> inStream;
+ CInFileStream *inStreamSpec = NULL;
+
+ if (stdInMode)
+ {
+ inStream = new CStdInFileStream;
+ MY_SET_BINARY_MODE(stdin);
+ }
+ else
+ {
+ const UString &inputName = params[paramIndex++];
+ inStreamSpec = new CInFileStream;
+ inStream = inStreamSpec;
+ if (!inStreamSpec->Open(us2fs(inputName)))
+ {
+ PrintError2("can not open input file", inputName);
+ return 1;
+ }
+ }
+
+ CMyComPtr<ISequentialOutStream> outStream;
+ COutFileStream *outStreamSpec = NULL;
+
+ if (stdOutMode)
+ {
+ outStream = new CStdOutFileStream;
+ MY_SET_BINARY_MODE(stdout);
+ }
+ else
+ {
+ const UString &outputName = params[paramIndex++];
+ outStreamSpec = new COutFileStream;
+ outStream = outStreamSpec;
+ if (!outStreamSpec->Create(us2fs(outputName), true))
+ {
+ 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.
+ 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";
+
+ size_t inSize = (size_t)fileSize;
+
+ if (inSize != fileSize)
+ throw "File is too big";
+
+ Byte *inBuffer = NULL;
+
+ if (inSize != 0)
+ {
+ inBuffer = (Byte *)MyAlloc((size_t)inSize);
+ if (!inBuffer)
+ throw kCantAllocate;
+ }
+
+ if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK)
+ throw "Can not read";
+
+ Byte *outBuffer = NULL;
+ size_t outSize;
+
+ if (encodeMode)
+ {
+ // we allocate 105% of original size for output buffer
+ UInt64 outSize64 = fileSize / 20 * 21 + (1 << 16);
+
+ outSize = (size_t)outSize64;
+
+ if (outSize != outSize64)
+ throw "File is too big";
+
+ if (outSize != 0)
+ {
+ outBuffer = (Byte *)MyAlloc((size_t)outSize);
+ if (!outBuffer)
+ throw kCantAllocate;
+ }
+
+ int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize,
+ 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);
+
+ if (res != 0)
+ {
+ 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 "Unpack size is too big";
+ if (outSize != 0)
+ {
+ outBuffer = (Byte *)MyAlloc(outSize);
+ if (!outBuffer)
+ throw kCantAllocate;
+ }
+
+ int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize);
+
+ if (inSize != (size_t)fileSize)
+ throw "incorrect processed size";
+ if (res != 0)
+ {
+ PrintError_int("Decode error", (int)res);
+ return 1;
+ }
+ }
+
+ if (WriteStream(outStream, outBuffer, outSize) != S_OK)
+ throw kWriteError;
+
+ MyFree(outBuffer);
+ MyFree(inBuffer);
+ }
+ else
+ {
+
+ CProgressPrint *progressSpec = NULL;
+ CMyComPtr<ICompressProgressInfo> progress;
+
+ if (!stdOutMode)
+ {
+ progressSpec = new CProgressPrint;
+ progress = progressSpec;
+ }
+
+ if (encodeMode)
+ {
+ NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+ UInt32 pb = 2;
+ UInt32 lc = 3; // = 0; for 32-bit data
+ UInt32 lp = 0; // = 2; for 32-bit data
+ UInt32 algo = 1;
+ UInt32 fb = 128;
+ UInt32 mc = 16 + fb / 2;
+ bool mcDefined = false;
+
+ bool eos = parser[NKey::kEOS].ThereIs || stdInMode;
+
+ ParseUInt32(parser, NKey::kAlgo, algo);
+ ParseUInt32(parser, NKey::kFb, fb);
+ ParseUInt32(parser, NKey::kLc, lc);
+ ParseUInt32(parser, NKey::kLp, lp);
+ ParseUInt32(parser, NKey::kPb, pb);
+
+ mcDefined = parser[NKey::kMc].ThereIs;
+ if (mcDefined)
+ mc = GetNumber(parser[NKey::kMc].PostStrings[0]);
+
+ const PROPID propIDs[] =
+ {
+ NCoderPropID::kDictionarySize,
+ NCoderPropID::kPosStateBits,
+ NCoderPropID::kLitContextBits,
+ NCoderPropID::kLitPosBits,
+ NCoderPropID::kAlgorithm,
+ NCoderPropID::kNumFastBytes,
+ NCoderPropID::kMatchFinder,
+ NCoderPropID::kEndMarker,
+ NCoderPropID::kNumThreads,
+ NCoderPropID::kMatchFinderCycles,
+ };
+
+ const unsigned kNumPropsMax = ARRAY_SIZE(propIDs);
+
+ PROPVARIANT props[kNumPropsMax];
+ for (int p = 0; p < 6; p++)
+ props[p].vt = VT_UI4;
+
+ props[0].ulVal = (UInt32)dict;
+ props[1].ulVal = (UInt32)pb;
+ props[2].ulVal = (UInt32)lc;
+ props[3].ulVal = (UInt32)lp;
+ props[4].ulVal = (UInt32)algo;
+ props[5].ulVal = (UInt32)fb;
+
+ props[6].vt = VT_BSTR;
+ props[6].bstrVal = const_cast<BSTR>((const wchar_t *)mf);
+
+ props[7].vt = VT_BOOL;
+ props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;
+
+ props[8].vt = VT_UI4;
+ props[8].ulVal = (UInt32)numThreads;
+
+ // it must be last in property list
+ props[9].vt = VT_UI4;
+ props[9].ulVal = (UInt32)mc;
+
+ unsigned numProps = kNumPropsMax;
+ if (!mcDefined)
+ numProps--;
+
+ HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps);
+ if (res != S_OK)
+ return Error_HRESULT("incorrect encoder properties", res);
+
+ if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
+ throw kWriteError;
+
+ bool fileSizeWasUsed = true;
+ if (eos || stdInMode)
+ {
+ fileSize = (UInt64)(Int64)-1;
+ fileSizeWasUsed = false;
+ }
+
+ {
+ 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 unsigned kPropertiesSize = 5;
+ Byte header[kPropertiesSize + 8];
+
+ if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK)
+ throw kReadError;
+
+ if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK)
+ throw "SetDecoderProperties error";
+
+ UInt64 unpackSize = 0;
+ for (int i = 0; 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();
+
+ if (res != S_OK)
+ {
+ 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)
+ {
+ if (!stdOutMode)
+ Print_Size("Output size: ", outStreamSpec->ProcessedSize);
+ if (outStreamSpec->Close() != S_OK)
+ 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)
+ {
+ PrintError(s);
+ return 1;
+ }
+ catch(...)
+ {
+ PrintError("Unknown Error");
+ return 1;
+ }
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
new file mode 100644
index 0000000000..bdc0c3e395
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp
@@ -0,0 +1,477 @@
+# Microsoft Developer Studio Project File - Name="LzmaCon" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=LzmaCon - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "LzmaCon.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "LzmaCon.mak" CFG="LzmaCon - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "LzmaCon - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "LzmaCon - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "LzmaCon - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386 /out:"C:\Util\lzma.exe"
+
+!ELSEIF "$(CFG)" == "LzmaCon - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 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\lzma.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "LzmaCon - Win32 Release"
+# Name "LzmaCon - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaDecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaEncoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaEncoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaRegister.cpp
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Thread.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ComTry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CrcReg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyCom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyUnknown.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyWindows.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyWindows.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Types.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# 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\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+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\MethodProps.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodProps.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Bench.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Bench.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.h
+# End Source File
+# End Group
+# Begin Group "Console"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Console\BenchCon.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\BenchCon.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ConsoleClose.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ConsoleClose.h
+# End Source File
+# End Group
+# Begin Group "C"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrcOpt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.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
+
+SOURCE=..\..\..\..\C\Bra86.c
+# SUBTRACT CPP /YX /Yc /Yu
+# 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\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\LzHash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma86.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma86Dec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma86Enc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# 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\Threads.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\LzmaAlone.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw
new file mode 100644
index 0000000000..c6a6662760
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "LzmaCon"=.\LzmaCon.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile
new file mode 100644
index 0000000000..260976304e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile
@@ -0,0 +1,59 @@
+PROG = lzma.exe
+MY_CONSOLE = 1
+CFLAGS = $(CFLAGS)
+
+CURRENT_OBJS = \
+ $O\LzmaAlone.obj \
+
+COMPRESS_OBJS = \
+ $O\LzmaDecoder.obj \
+ $O\LzmaEncoder.obj \
+ $O\LzmaRegister.obj \
+
+COMMON_OBJS = \
+ $O\CommandLineParser.obj \
+ $O\CRC.obj \
+ $O\CrcReg.obj \
+ $O\IntToString.obj \
+ $O\MyString.obj \
+ $O\NewHandler.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\MyVector.obj
+
+WIN_OBJS = \
+ $O\FileIO.obj \
+ $O\PropVariant.obj \
+ $O\System.obj
+
+7ZIP_COMMON_OBJS = \
+ $O\CWrappers.obj \
+ $O\CreateCoder.obj \
+ $O\FileStreams.obj \
+ $O\FilterCoder.obj \
+ $O\MethodProps.obj \
+ $O\OutBuffer.obj \
+ $O\StreamUtils.obj \
+
+UI_COMMON_OBJS = \
+ $O\Bench.obj \
+
+CONSOLE_OBJS = \
+ $O\ConsoleClose.obj \
+ $O\BenchCon.obj \
+
+C_OBJS = \
+ $O\Alloc.obj \
+ $O\Bra86.obj \
+ $O\CpuArch.obj \
+ $O\LzFind.obj \
+ $O\LzFindMt.obj \
+ $O\Lzma86Dec.obj \
+ $O\Lzma86Enc.obj \
+ $O\LzmaDec.obj \
+ $O\LzmaEnc.obj \
+ $O\Threads.obj \
+
+!include "../../Crc.mak"
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile.gcc
new file mode 100644
index 0000000000..3fb5ec2081
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile.gcc
@@ -0,0 +1,195 @@
+PROG = lzma
+CXX = g++ -O2
+# -Wall -Werror -Wno-delete-non-virtual-dtor
+CXX_C = gcc -O2 -Wall -Werror
+
+ifdef SystemDrive
+IS_MINGW = 1
+endif
+
+ifdef IS_MINGW
+
+RM = del
+CFLAGS = -c
+LIB2 = -loleaut32 -luuid
+LDFLAGS = -s
+
+FILE_IO =FileIO
+FILE_IO_2 =Windows/$(FILE_IO)
+
+MT_FILES = \
+ LzFindMt.o \
+ Threads.o \
+
+else
+
+RM = rm -f
+CFLAGS = -c -D_7ZIP_ST
+
+FILE_IO =C_FileIO
+FILE_IO_2 =Common/$(FILE_IO)
+
+
+endif
+
+
+OBJS = \
+ $(MT_FILES) \
+ $(FILE_IO).o \
+ LzmaAlone.o \
+ Bench.o \
+ BenchCon.o \
+ ConsoleClose.o \
+ LzmaDecoder.o \
+ LzmaEncoder.o \
+ LzmaRegister.o \
+ CreateCoder.o \
+ CWrappers.o \
+ FileStreams.o \
+ FilterCoder.o \
+ MethodProps.o \
+ StreamUtils.o \
+ CommandLineParser.o \
+ CRC.o \
+ CrcReg.o \
+ IntToString.o \
+ MyString.o \
+ MyVector.o \
+ MyWindows.o \
+ StringConvert.o \
+ StringToInt.o \
+ PropVariant.o \
+ System.o \
+ 7zCrc.o \
+ 7zCrcOpt.o \
+ Alloc.o \
+ Bra86.o \
+ CpuArch.o \
+ LzFind.o \
+ LzmaDec.o \
+ LzmaEnc.o \
+ Lzma86Dec.o \
+ Lzma86Enc.o \
+
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB2)
+
+LzmaAlone.o: LzmaAlone.cpp
+ $(CXX) $(CFLAGS) LzmaAlone.cpp
+
+Bench.o: ../../UI/Common/Bench.cpp
+ $(CXX) $(CFLAGS) ../../UI/Common/Bench.cpp
+
+BenchCon.o: ../../UI/Console/BenchCon.cpp
+ $(CXX) $(CFLAGS) ../../UI/Console/BenchCon.cpp
+
+ConsoleClose.o: ../../UI/Console/ConsoleClose.cpp
+ $(CXX) $(CFLAGS) ../../UI/Console/ConsoleClose.cpp
+
+LzmaDecoder.o: ../../Compress/LzmaDecoder.cpp
+ $(CXX) $(CFLAGS) ../../Compress/LzmaDecoder.cpp
+
+LzmaEncoder.o: ../../Compress/LzmaEncoder.cpp
+ $(CXX) $(CFLAGS) ../../Compress/LzmaEncoder.cpp
+
+LzmaRegister.o: ../../Compress/LzmaRegister.cpp
+ $(CXX) $(CFLAGS) ../../Compress/LzmaRegister.cpp
+
+CreateCoder.o: ../../Common/CreateCoder.cpp
+ $(CXX) $(CFLAGS) ../../Common/CreateCoder.cpp
+
+CWrappers.o: ../../Common/CWrappers.cpp
+ $(CXX) $(CFLAGS) ../../Common/CWrappers.cpp
+
+FileStreams.o: ../../Common/FileStreams.cpp
+ $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp
+
+FilterCoder.o: ../../Common/FilterCoder.cpp
+ $(CXX) $(CFLAGS) ../../Common/FilterCoder.cpp
+
+MethodProps.o: ../../Common/MethodProps.cpp
+ $(CXX) $(CFLAGS) ../../Common/MethodProps.cpp
+
+StreamUtils.o: ../../Common/StreamUtils.cpp
+ $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp
+
+$(FILE_IO).o: ../../../$(FILE_IO_2).cpp
+ $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp
+
+
+CommandLineParser.o: ../../../Common/CommandLineParser.cpp
+ $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp
+
+CRC.o: ../../../Common/CRC.cpp
+ $(CXX) $(CFLAGS) ../../../Common/CRC.cpp
+
+CrcReg.o: ../../../Common/CrcReg.cpp
+ $(CXX) $(CFLAGS) ../../../Common/CrcReg.cpp
+
+IntToString.o: ../../../Common/IntToString.cpp
+ $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp
+
+MyString.o: ../../../Common/MyString.cpp
+ $(CXX) $(CFLAGS) ../../../Common/MyString.cpp
+
+MyVector.o: ../../../Common/MyVector.cpp
+ $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp
+
+MyWindows.o: ../../../Common/MyWindows.cpp
+ $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
+
+StringConvert.o: ../../../Common/StringConvert.cpp
+ $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp
+
+StringToInt.o: ../../../Common/StringToInt.cpp
+ $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp
+
+PropVariant.o: ../../../Windows/PropVariant.cpp
+ $(CXX) $(CFLAGS) ../../../Windows/PropVariant.cpp
+
+System.o: ../../../Windows/System.cpp
+ $(CXX) $(CFLAGS) ../../../Windows/System.cpp
+
+7zCrc.o: ../../../../C/7zCrc.c
+ $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c
+
+7zCrcOpt.o: ../../../../C/7zCrcOpt.c
+ $(CXX_C) $(CFLAGS) ../../../../C/7zCrcOpt.c
+
+Alloc.o: ../../../../C/Alloc.c
+ $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c
+
+Bra86.o: ../../../../C/Bra86.c
+ $(CXX_C) $(CFLAGS) ../../../../C/Bra86.c
+
+CpuArch.o: ../../../../C/CpuArch.c
+ $(CXX_C) $(CFLAGS) ../../../../C/CpuArch.c
+
+LzFind.o: ../../../../C/LzFind.c
+ $(CXX_C) $(CFLAGS) ../../../../C/LzFind.c
+
+ifdef MT_FILES
+LzFindMt.o: ../../../../C/LzFindMt.c
+ $(CXX_C) $(CFLAGS) ../../../../C/LzFindMt.c
+
+Threads.o: ../../../../C/Threads.c
+ $(CXX_C) $(CFLAGS) ../../../../C/Threads.c
+endif
+
+LzmaDec.o: ../../../../C/LzmaDec.c
+ $(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c
+
+LzmaEnc.o: ../../../../C/LzmaEnc.c
+ $(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c
+
+Lzma86Dec.o: ../../../../C/Lzma86Dec.c
+ $(CXX_C) $(CFLAGS) ../../../../C/Lzma86Dec.c
+
+Lzma86Enc.o: ../../../../C/Lzma86Enc.c
+ $(CXX_C) $(CFLAGS) ../../../../C/Lzma86Enc.c
+
+clean:
+ -$(RM) $(PROG) $(OBJS)
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/resource.rc b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/resource.rc
new file mode 100644
index 0000000000..9b54fa80a8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_APP("LZMA", "lzma")
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp
new file mode 100644
index 0000000000..67e8dfc799
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp
@@ -0,0 +1,715 @@
+/* LzmaSpec.cpp -- LZMA Reference Decoder
+2015-06-14 : Igor Pavlov : Public domain */
+
+// This code implements LZMA file decoding according to LZMA specification.
+// This code is not optimized for speed.
+
+#include <stdio.h>
+
+#ifdef _MSC_VER
+ #pragma warning(disable : 4710) // function not inlined
+ #pragma warning(disable : 4996) // This function or variable may be unsafe
+#endif
+
+typedef unsigned char Byte;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+ typedef unsigned long UInt32;
+#else
+ typedef unsigned int UInt32;
+#endif
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 UInt64;
+#else
+ typedef unsigned long long int UInt64;
+#endif
+
+
+struct CInputStream
+{
+ FILE *File;
+ UInt64 Processed;
+
+ void Init() { Processed = 0; }
+
+ Byte ReadByte()
+ {
+ int c = getc(File);
+ if (c < 0)
+ throw "Unexpected end of file";
+ Processed++;
+ return (Byte)c;
+ }
+};
+
+
+struct COutStream
+{
+ FILE *File;
+ UInt64 Processed;
+
+ void Init() { Processed = 0; }
+
+ void WriteByte(Byte b)
+ {
+ if (putc(b, File) == EOF)
+ throw "File writing error";
+ Processed++;
+ }
+};
+
+
+class COutWindow
+{
+ Byte *Buf;
+ UInt32 Pos;
+ UInt32 Size;
+ bool IsFull;
+
+public:
+ unsigned TotalPos;
+ COutStream OutStream;
+
+ COutWindow(): Buf(NULL) {}
+ ~COutWindow() { delete []Buf; }
+
+ void Create(UInt32 dictSize)
+ {
+ Buf = new Byte[dictSize];
+ Pos = 0;
+ Size = dictSize;
+ IsFull = false;
+ TotalPos = 0;
+ }
+
+ void PutByte(Byte b)
+ {
+ TotalPos++;
+ Buf[Pos++] = b;
+ if (Pos == Size)
+ {
+ Pos = 0;
+ IsFull = true;
+ }
+ OutStream.WriteByte(b);
+ }
+
+ Byte GetByte(UInt32 dist) const
+ {
+ return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos];
+ }
+
+ void CopyMatch(UInt32 dist, unsigned len)
+ {
+ for (; len > 0; len--)
+ PutByte(GetByte(dist));
+ }
+
+ bool CheckDistance(UInt32 dist) const
+ {
+ return dist <= Pos || IsFull;
+ }
+
+ bool IsEmpty() const
+ {
+ return Pos == 0 && !IsFull;
+ }
+};
+
+
+#define kNumBitModelTotalBits 11
+#define kNumMoveBits 5
+
+typedef UInt16 CProb;
+
+#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2)
+
+#define INIT_PROBS(p) \
+ { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; }
+
+class CRangeDecoder
+{
+ UInt32 Range;
+ UInt32 Code;
+
+ void Normalize();
+
+public:
+
+ CInputStream *InStream;
+ bool Corrupted;
+
+ bool Init();
+ bool IsFinishedOK() const { return Code == 0; }
+
+ UInt32 DecodeDirectBits(unsigned numBits);
+ unsigned DecodeBit(CProb *prob);
+};
+
+bool CRangeDecoder::Init()
+{
+ Corrupted = false;
+ Range = 0xFFFFFFFF;
+ Code = 0;
+
+ Byte b = InStream->ReadByte();
+
+ for (int i = 0; i < 4; i++)
+ Code = (Code << 8) | InStream->ReadByte();
+
+ if (b != 0 || Code == Range)
+ Corrupted = true;
+ return b == 0;
+}
+
+#define kTopValue ((UInt32)1 << 24)
+
+void CRangeDecoder::Normalize()
+{
+ if (Range < kTopValue)
+ {
+ Range <<= 8;
+ Code = (Code << 8) | InStream->ReadByte();
+ }
+}
+
+UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits)
+{
+ UInt32 res = 0;
+ do
+ {
+ Range >>= 1;
+ Code -= Range;
+ UInt32 t = 0 - ((UInt32)Code >> 31);
+ Code += Range & t;
+
+ if (Code == Range)
+ Corrupted = true;
+
+ Normalize();
+ res <<= 1;
+ res += t + 1;
+ }
+ while (--numBits);
+ return res;
+}
+
+unsigned CRangeDecoder::DecodeBit(CProb *prob)
+{
+ unsigned v = *prob;
+ UInt32 bound = (Range >> kNumBitModelTotalBits) * v;
+ unsigned symbol;
+ if (Code < bound)
+ {
+ v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits;
+ Range = bound;
+ symbol = 0;
+ }
+ else
+ {
+ v -= v >> kNumMoveBits;
+ Code -= bound;
+ Range -= bound;
+ symbol = 1;
+ }
+ *prob = (CProb)v;
+ Normalize();
+ return symbol;
+}
+
+
+unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc)
+{
+ unsigned m = 1;
+ unsigned symbol = 0;
+ for (unsigned i = 0; i < numBits; i++)
+ {
+ unsigned bit = rc->DecodeBit(&probs[m]);
+ m <<= 1;
+ m += bit;
+ symbol |= (bit << i);
+ }
+ return symbol;
+}
+
+template <unsigned NumBits>
+class CBitTreeDecoder
+{
+ CProb Probs[(unsigned)1 << NumBits];
+
+public:
+
+ void Init()
+ {
+ INIT_PROBS(Probs);
+ }
+
+ unsigned Decode(CRangeDecoder *rc)
+ {
+ unsigned m = 1;
+ for (unsigned i = 0; i < NumBits; i++)
+ m = (m << 1) + rc->DecodeBit(&Probs[m]);
+ return m - ((unsigned)1 << NumBits);
+ }
+
+ unsigned ReverseDecode(CRangeDecoder *rc)
+ {
+ return BitTreeReverseDecode(Probs, NumBits, rc);
+ }
+};
+
+#define kNumPosBitsMax 4
+
+#define kNumStates 12
+#define kNumLenToPosStates 4
+#define kNumAlignBits 4
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+#define kMatchMinLen 2
+
+class CLenDecoder
+{
+ CProb Choice;
+ CProb Choice2;
+ CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax];
+ CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax];
+ CBitTreeDecoder<8> HighCoder;
+
+public:
+
+ void Init()
+ {
+ Choice = PROB_INIT_VAL;
+ Choice2 = PROB_INIT_VAL;
+ HighCoder.Init();
+ for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++)
+ {
+ LowCoder[i].Init();
+ MidCoder[i].Init();
+ }
+ }
+
+ unsigned Decode(CRangeDecoder *rc, unsigned posState)
+ {
+ if (rc->DecodeBit(&Choice) == 0)
+ return LowCoder[posState].Decode(rc);
+ if (rc->DecodeBit(&Choice2) == 0)
+ return 8 + MidCoder[posState].Decode(rc);
+ return 16 + HighCoder.Decode(rc);
+ }
+};
+
+unsigned UpdateState_Literal(unsigned state)
+{
+ if (state < 4) return 0;
+ else if (state < 10) return state - 3;
+ else return state - 6;
+}
+unsigned UpdateState_Match (unsigned state) { return state < 7 ? 7 : 10; }
+unsigned UpdateState_Rep (unsigned state) { return state < 7 ? 8 : 11; }
+unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; }
+
+#define LZMA_DIC_MIN (1 << 12)
+
+class CLzmaDecoder
+{
+public:
+ CRangeDecoder RangeDec;
+ COutWindow OutWindow;
+
+ bool markerIsMandatory;
+ unsigned lc, pb, lp;
+ UInt32 dictSize;
+ UInt32 dictSizeInProperties;
+
+ void DecodeProperties(const Byte *properties)
+ {
+ unsigned d = properties[0];
+ if (d >= (9 * 5 * 5))
+ throw "Incorrect LZMA properties";
+ lc = d % 9;
+ d /= 9;
+ pb = d / 5;
+ lp = d % 5;
+ dictSizeInProperties = 0;
+ for (int i = 0; i < 4; i++)
+ dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i);
+ dictSize = dictSizeInProperties;
+ if (dictSize < LZMA_DIC_MIN)
+ dictSize = LZMA_DIC_MIN;
+ }
+
+ CLzmaDecoder(): LitProbs(NULL) {}
+ ~CLzmaDecoder() { delete []LitProbs; }
+
+ void Create()
+ {
+ OutWindow.Create(dictSize);
+ CreateLiterals();
+ }
+
+ int Decode(bool unpackSizeDefined, UInt64 unpackSize);
+
+private:
+
+ CProb *LitProbs;
+
+ void CreateLiterals()
+ {
+ LitProbs = new CProb[(UInt32)0x300 << (lc + lp)];
+ }
+
+ void InitLiterals()
+ {
+ UInt32 num = (UInt32)0x300 << (lc + lp);
+ for (UInt32 i = 0; i < num; i++)
+ LitProbs[i] = PROB_INIT_VAL;
+ }
+
+ void DecodeLiteral(unsigned state, UInt32 rep0)
+ {
+ unsigned prevByte = 0;
+ if (!OutWindow.IsEmpty())
+ prevByte = OutWindow.GetByte(1);
+
+ unsigned symbol = 1;
+ unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc));
+ CProb *probs = &LitProbs[(UInt32)0x300 * litState];
+
+ if (state >= 7)
+ {
+ unsigned matchByte = OutWindow.GetByte(rep0 + 1);
+ do
+ {
+ unsigned matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]);
+ symbol = (symbol << 1) | bit;
+ if (matchBit != bit)
+ break;
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]);
+ OutWindow.PutByte((Byte)(symbol - 0x100));
+ }
+
+ CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates];
+ CBitTreeDecoder<kNumAlignBits> AlignDecoder;
+ CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex];
+
+ void InitDist()
+ {
+ for (unsigned i = 0; i < kNumLenToPosStates; i++)
+ PosSlotDecoder[i].Init();
+ AlignDecoder.Init();
+ INIT_PROBS(PosDecoders);
+ }
+
+ unsigned DecodeDistance(unsigned len)
+ {
+ unsigned lenState = len;
+ if (lenState > kNumLenToPosStates - 1)
+ lenState = kNumLenToPosStates - 1;
+
+ unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec);
+ if (posSlot < 4)
+ return posSlot;
+
+ unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1);
+ UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec);
+ else
+ {
+ dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits;
+ dist += AlignDecoder.ReverseDecode(&RangeDec);
+ }
+ return dist;
+ }
+
+ CProb IsMatch[kNumStates << kNumPosBitsMax];
+ CProb IsRep[kNumStates];
+ CProb IsRepG0[kNumStates];
+ CProb IsRepG1[kNumStates];
+ CProb IsRepG2[kNumStates];
+ CProb IsRep0Long[kNumStates << kNumPosBitsMax];
+
+ CLenDecoder LenDecoder;
+ CLenDecoder RepLenDecoder;
+
+ void Init()
+ {
+ InitLiterals();
+ InitDist();
+
+ INIT_PROBS(IsMatch);
+ INIT_PROBS(IsRep);
+ INIT_PROBS(IsRepG0);
+ INIT_PROBS(IsRepG1);
+ INIT_PROBS(IsRepG2);
+ INIT_PROBS(IsRep0Long);
+
+ LenDecoder.Init();
+ RepLenDecoder.Init();
+ }
+};
+
+
+#define LZMA_RES_ERROR 0
+#define LZMA_RES_FINISHED_WITH_MARKER 1
+#define LZMA_RES_FINISHED_WITHOUT_MARKER 2
+
+int CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize)
+{
+ if (!RangeDec.Init())
+ return LZMA_RES_ERROR;
+
+ Init();
+
+ UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
+ unsigned state = 0;
+
+ for (;;)
+ {
+ if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory)
+ if (RangeDec.IsFinishedOK())
+ return LZMA_RES_FINISHED_WITHOUT_MARKER;
+
+ unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1);
+
+ if (RangeDec.DecodeBit(&IsMatch[(state << kNumPosBitsMax) + posState]) == 0)
+ {
+ if (unpackSizeDefined && unpackSize == 0)
+ return LZMA_RES_ERROR;
+ DecodeLiteral(state, rep0);
+ state = UpdateState_Literal(state);
+ unpackSize--;
+ continue;
+ }
+
+ unsigned len;
+
+ if (RangeDec.DecodeBit(&IsRep[state]) != 0)
+ {
+ if (unpackSizeDefined && unpackSize == 0)
+ return LZMA_RES_ERROR;
+ if (OutWindow.IsEmpty())
+ return LZMA_RES_ERROR;
+ if (RangeDec.DecodeBit(&IsRepG0[state]) == 0)
+ {
+ if (RangeDec.DecodeBit(&IsRep0Long[(state << kNumPosBitsMax) + posState]) == 0)
+ {
+ state = UpdateState_ShortRep(state);
+ OutWindow.PutByte(OutWindow.GetByte(rep0 + 1));
+ unpackSize--;
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 dist;
+ if (RangeDec.DecodeBit(&IsRepG1[state]) == 0)
+ dist = rep1;
+ else
+ {
+ if (RangeDec.DecodeBit(&IsRepG2[state]) == 0)
+ dist = rep2;
+ else
+ {
+ dist = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = dist;
+ }
+ len = RepLenDecoder.Decode(&RangeDec, posState);
+ state = UpdateState_Rep(state);
+ }
+ else
+ {
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ len = LenDecoder.Decode(&RangeDec, posState);
+ state = UpdateState_Match(state);
+ rep0 = DecodeDistance(len);
+ if (rep0 == 0xFFFFFFFF)
+ return RangeDec.IsFinishedOK() ?
+ LZMA_RES_FINISHED_WITH_MARKER :
+ LZMA_RES_ERROR;
+
+ if (unpackSizeDefined && unpackSize == 0)
+ return LZMA_RES_ERROR;
+ if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0))
+ return LZMA_RES_ERROR;
+ }
+ len += kMatchMinLen;
+ bool isError = false;
+ if (unpackSizeDefined && unpackSize < len)
+ {
+ len = (unsigned)unpackSize;
+ isError = true;
+ }
+ OutWindow.CopyMatch(rep0 + 1, len);
+ unpackSize -= len;
+ if (isError)
+ return LZMA_RES_ERROR;
+ }
+}
+
+static void Print(const char *s)
+{
+ fputs(s, stdout);
+}
+
+static void PrintError(const char *s)
+{
+ fputs(s, stderr);
+}
+
+
+#define CONVERT_INT_TO_STR(charType, tempSize) \
+
+void ConvertUInt64ToString(UInt64 val, char *s)
+{
+ char temp[32];
+ unsigned i = 0;
+ while (val >= 10)
+ {
+ temp[i++] = (char)('0' + (unsigned)(val % 10));
+ val /= 10;
+ }
+ *s++ = (char)('0' + (unsigned)val);
+ while (i != 0)
+ {
+ i--;
+ *s++ = temp[i];
+ }
+ *s = 0;
+}
+
+void PrintUInt64(const char *title, UInt64 v)
+{
+ Print(title);
+ Print(" : ");
+ char s[32];
+ ConvertUInt64ToString(v, s);
+ Print(s);
+ Print(" bytes \n");
+}
+
+int main2(int numArgs, const char *args[])
+{
+ Print("\nLZMA Reference Decoder 15.00 : Igor Pavlov : Public domain : 2015-04-16\n");
+ if (numArgs == 1)
+ Print("\nUse: lzmaSpec a.lzma outFile");
+
+ if (numArgs != 3)
+ throw "you must specify two parameters";
+
+ CInputStream inStream;
+ inStream.File = fopen(args[1], "rb");
+ inStream.Init();
+ if (inStream.File == 0)
+ throw "Can't open input file";
+
+ CLzmaDecoder lzmaDecoder;
+ lzmaDecoder.OutWindow.OutStream.File = fopen(args[2], "wb+");
+ lzmaDecoder.OutWindow.OutStream.Init();
+ if (inStream.File == 0)
+ throw "Can't open output file";
+
+ Byte header[13];
+ int i;
+ for (i = 0; i < 13; i++)
+ header[i] = inStream.ReadByte();
+
+ lzmaDecoder.DecodeProperties(header);
+
+ printf("\nlc=%d, lp=%d, pb=%d", lzmaDecoder.lc, lzmaDecoder.lp, lzmaDecoder.pb);
+ printf("\nDictionary Size in properties = %u", lzmaDecoder.dictSizeInProperties);
+ printf("\nDictionary Size for decoding = %u", lzmaDecoder.dictSize);
+
+ UInt64 unpackSize = 0;
+ bool unpackSizeDefined = false;
+ for (i = 0; i < 8; i++)
+ {
+ Byte b = header[5 + i];
+ if (b != 0xFF)
+ unpackSizeDefined = true;
+ unpackSize |= (UInt64)b << (8 * i);
+ }
+
+ lzmaDecoder.markerIsMandatory = !unpackSizeDefined;
+
+ Print("\n");
+ if (unpackSizeDefined)
+ PrintUInt64("Uncompressed Size", unpackSize);
+ else
+ Print("End marker is expected\n");
+ lzmaDecoder.RangeDec.InStream = &inStream;
+
+ Print("\n");
+
+ lzmaDecoder.Create();
+
+ int res = lzmaDecoder.Decode(unpackSizeDefined, unpackSize);
+
+ PrintUInt64("Read ", inStream.Processed);
+ PrintUInt64("Written ", lzmaDecoder.OutWindow.OutStream.Processed);
+
+ if (res == LZMA_RES_ERROR)
+ throw "LZMA decoding error";
+ else if (res == LZMA_RES_FINISHED_WITHOUT_MARKER)
+ Print("Finished without end marker");
+ else if (res == LZMA_RES_FINISHED_WITH_MARKER)
+ {
+ if (unpackSizeDefined)
+ {
+ if (lzmaDecoder.OutWindow.OutStream.Processed != unpackSize)
+ throw "Finished with end marker before than specified size";
+ Print("Warning: ");
+ }
+ Print("Finished with end marker");
+ }
+ else
+ throw "Internal Error";
+
+ Print("\n");
+
+ if (lzmaDecoder.RangeDec.Corrupted)
+ {
+ Print("\nWarning: LZMA stream is corrupted\n");
+ }
+
+ return 0;
+}
+
+
+int
+ #ifdef _MSC_VER
+ __cdecl
+ #endif
+main(int numArgs, const char *args[])
+{
+ try { return main2(numArgs, args); }
+ catch (const char *s)
+ {
+ PrintError("\nError:\n");
+ PrintError(s);
+ PrintError("\n");
+ return 1;
+ }
+ catch(...)
+ {
+ PrintError("\nError\n");
+ return 1;
+ }
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/7z.ico b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/7z.ico
new file mode 100644
index 0000000000..47ffb781e0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/7z.ico
Binary files differ
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
new file mode 100644
index 0000000000..87753191ff
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsp
@@ -0,0 +1,912 @@
+# Microsoft Developer Studio Project File - Name="SFXCon" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=SFXCon - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "SFXCon.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "SFXCon.mak" CFG="SFXCon - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SFXCon - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "SFXCon - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "SFXCon - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386 /out:"C:\Util\7zCon.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "SFXCon - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 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\7zCon.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "SFXCon - Win32 Release"
+# Name "SFXCon - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# 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\HandlerOut.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
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
+# End Source File
+# End Group
+# Begin Group "Console"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ConsoleClose.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ConsoleClose.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\List.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\List.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\MainAr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\UI\Console\UserInputUtils.h
+# End Source File
+# End Group
+# Begin Group "7z"
+
+# PROP Default_Filter ""
+# 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\7zExtract.cpp
+# 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\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\7zRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\SplitHandler.cpp
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Coder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjRegister.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\Compress\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\Compress\Lzma2Decoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma2Register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\PpmdDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\PpmdRegister.cpp
+# End Source File
+# End Group
+# Begin Group "Crypto"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAesRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\MyAes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\MyAes.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ErrorMsg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ErrorMsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConv.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# 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
+
+SOURCE=..\..\Common\FilePathAutoRename.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+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\InBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LimitedStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LimitedStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LockedStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LockedStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OffsetStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OffsetStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\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
+
+SOURCE=..\..\Common\StreamBinder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamObjects.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamObjects.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.h
+# End Source File
+# End Group
+# Begin Group "UI"
+
+# PROP Default_Filter ""
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExitCode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Extract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Extract.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractingFilePath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\PropIDUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\PropIDUtils.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "C"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrcOpt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Aes.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Aes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\AesOpt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\..\..\C\Bra86.c
+# SUBTRACT CPP /YX /Yc /Yu
+# 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\DllSecur.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\DllSecur.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2Dec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2Dec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.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\MtDec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\MtDec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Ppmd7.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Ppmd7.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Ppmd7Dec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sha256.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sha256.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\7z.ico
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\IArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SfxCon.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsw b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsw
new file mode 100644
index 0000000000..bfbc2b7f00
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "SFXCon"=.\SFXCon.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
new file mode 100644
index 0000000000..9b34a08190
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
@@ -0,0 +1,482 @@
+// Main.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/MyWindows.h"
+
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/MyException.h"
+
+#ifdef _WIN32
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/FileDir.h"
+#endif
+#include "../../../Windows/FileName.h"
+
+#include "../../UI/Common/ExitCode.h"
+#include "../../UI/Common/Extract.h"
+
+#include "../../UI/Console/ExtractCallbackConsole.h"
+#include "../../UI/Console/List.h"
+#include "../../UI/Console/OpenCallbackConsole.h"
+
+#include "../../MyVersion.h"
+
+#include "../../../../C/DllSecur.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+using namespace NCommandLineParser;
+
+#ifdef _WIN32
+HINSTANCE g_hInstance = 0;
+#endif
+int g_CodePage = -1;
+extern CStdOutStream *g_StdStream;
+
+static const char * const kCopyrightString =
+"\n7-Zip SFX " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n";
+
+static const int kNumSwitches = 6;
+
+namespace NKey {
+enum Enum
+{
+ kHelp1 = 0,
+ kHelp2,
+ kDisablePercents,
+ kYes,
+ kPassword,
+ kOutputDir
+};
+
+}
+
+namespace NRecursedType {
+enum EEnum
+{
+ kRecursed,
+ kWildcardOnlyRecursed,
+ kNonRecursed
+};
+}
+/*
+static const char kRecursedIDChar = 'R';
+
+namespace NRecursedPostCharIndex {
+ enum EEnum
+ {
+ kWildcardRecursionOnly = 0,
+ kNoRecursion = 1
+ };
+}
+
+static const char kFileListID = '@';
+static const char kImmediateNameID = '!';
+
+static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
+static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
+*/
+static const CSwitchForm kSwitchForms[kNumSwitches] =
+{
+ { "?", NSwitchType::kSimple },
+ { "H", NSwitchType::kSimple },
+ { "BD", NSwitchType::kSimple },
+ { "Y", NSwitchType::kSimple },
+ { "P", NSwitchType::kString, false, 1 },
+ { "O", NSwitchType::kString, false, 1 },
+};
+
+static const int kNumCommandForms = 3;
+
+static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] =
+{
+ NRecursedType::kRecursed
+};
+
+// static const bool kTestExtractRecursedDefault = true;
+// static const bool kAddRecursedDefault = false;
+
+static const char * const kUniversalWildcard = "*";
+static const int kCommandIndex = 0;
+
+static const char * const kHelpString =
+ "\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\n"
+ "\n"
+ "<Commands>\n"
+ // " l: List contents of archive\n"
+ " t: Test integrity of archive\n"
+ " x: eXtract files with full pathname (default)\n"
+ "<Switches>\n"
+ // " -bd Disable percentage indicator\n"
+ " -o{Directory}: set Output directory\n"
+ " -p{Password}: set Password\n"
+ " -y: assume Yes on all queries\n";
+
+
+// ---------------------------
+// exception messages
+
+static const char * const kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError
+// static const char * const kIncorrectListFile = "Incorrect wildcard in listfile";
+static const char * const kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line";
+
+// static const CSysString kFileIsNotArchiveMessageBefore = "File \"";
+// static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive";
+
+// static const char * const kProcessArchiveMessage = " archive: ";
+
+static const char * const kCantFindSFX = " cannot find sfx";
+
+namespace NCommandType
+{
+ enum EEnum
+ {
+ kTest = 0,
+ kFullExtract,
+ kList
+ };
+}
+
+static const char *g_Commands = "txl";
+
+struct CArchiveCommand
+{
+ NCommandType::EEnum CommandType;
+
+ NRecursedType::EEnum DefaultRecursedType() const;
+};
+
+bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)
+{
+ UString s = commandString;
+ s.MakeLower_Ascii();
+ if (s.Len() != 1)
+ return false;
+ if (s[0] >= 0x80)
+ return false;
+ int index = FindCharPosInString(g_Commands, (char)s[0]);
+ if (index < 0)
+ return false;
+ command.CommandType = (NCommandType::EEnum)index;
+ return true;
+}
+
+NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const
+{
+ return kCommandRecursedDefault[CommandType];
+}
+
+void PrintHelp(void)
+{
+ g_StdOut << kHelpString;
+}
+
+static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code)
+{
+ g_StdOut << message << endl;
+ throw code;
+}
+
+static void PrintHelpAndExit() // yyy
+{
+ PrintHelp();
+ ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
+}
+
+// ------------------------------------------------------------------
+// filenames functions
+
+static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,
+ const UString &name, bool include, NRecursedType::EEnum type)
+{
+ /*
+ if (!IsWildcardFilePathLegal(name))
+ return false;
+ */
+ bool isWildcard = DoesNameContainWildcard(name);
+ bool recursed = false;
+
+ switch (type)
+ {
+ case NRecursedType::kWildcardOnlyRecursed:
+ recursed = isWildcard;
+ break;
+ case NRecursedType::kRecursed:
+ recursed = true;
+ break;
+ case NRecursedType::kNonRecursed:
+ recursed = false;
+ break;
+ }
+ wildcardCensor.AddPreItem(include, name, recursed, true);
+ return true;
+}
+
+void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor,
+ const UString &name, bool include, NRecursedType::EEnum type)
+{
+ if (!AddNameToCensor(wildcardCensor, name, include, type))
+ ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError);
+}
+
+
+#ifndef _WIN32
+static void GetArguments(int numArgs, const char *args[], UStringVector &parts)
+{
+ parts.Clear();
+ for (int i = 0; i < numArgs; i++)
+ {
+ UString s = MultiByteToUnicodeString(args[i]);
+ parts.Add(s);
+ }
+}
+#endif
+
+int Main2(
+ #ifndef _WIN32
+ int numArgs, const char *args[]
+ #endif
+)
+{
+ #ifdef _WIN32
+ // do we need load Security DLLs for console program?
+ LoadSecurityDlls();
+ #endif
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ SetFileApisToOEM();
+ #endif
+
+ g_StdOut << kCopyrightString;
+
+ UStringVector commandStrings;
+ #ifdef _WIN32
+ NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
+ #else
+ GetArguments(numArgs, args, commandStrings);
+ #endif
+
+ #ifdef _WIN32
+
+ FString arcPath;
+ {
+ FString path;
+ NDLL::MyGetModuleFileName(path);
+ if (!MyGetFullPathName(path, arcPath))
+ {
+ g_StdOut << "GetFullPathName Error";
+ return NExitCode::kFatalError;
+ }
+ }
+
+ #else
+
+ UString arcPath = commandStrings.Front();
+
+ #endif
+
+ #ifndef UNDER_CE
+ if (commandStrings.Size() > 0)
+ commandStrings.Delete(0);
+ #endif
+
+ NCommandLineParser::CParser parser;
+
+ try
+ {
+ if (!parser.ParseStrings(kSwitchForms, kNumSwitches, commandStrings))
+ {
+ g_StdOut << "Command line error:" << endl
+ << parser.ErrorMessage << endl
+ << parser.ErrorLine << endl;
+ return NExitCode::kUserError;
+ }
+ }
+ catch(...)
+ {
+ PrintHelpAndExit();
+ }
+
+ if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
+ {
+ PrintHelp();
+ return 0;
+ }
+
+ const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
+
+ unsigned curCommandIndex = 0;
+
+ CArchiveCommand command;
+ if (nonSwitchStrings.IsEmpty())
+ command.CommandType = NCommandType::kFullExtract;
+ else
+ {
+ const UString &cmd = nonSwitchStrings[curCommandIndex];
+ if (!ParseArchiveCommand(cmd, command))
+ {
+ g_StdOut << "ERROR: Unknown command:" << endl << cmd << endl;
+ return NExitCode::kUserError;
+ }
+ curCommandIndex = 1;
+ }
+
+
+ NRecursedType::EEnum recursedType;
+ recursedType = command.DefaultRecursedType();
+
+ NWildcard::CCensor wildcardCensor;
+
+ {
+ if (nonSwitchStrings.Size() == curCommandIndex)
+ AddCommandLineWildcardToCensor(wildcardCensor, (UString)kUniversalWildcard, true, recursedType);
+ for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++)
+ {
+ const UString &s = nonSwitchStrings[curCommandIndex];
+ if (s.IsEmpty())
+ throw "Empty file path";
+ AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType);
+ }
+ }
+
+ bool yesToAll = parser[NKey::kYes].ThereIs;
+
+ // NExtractMode::EEnum extractMode;
+ // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode);
+
+ bool passwordEnabled = parser[NKey::kPassword].ThereIs;
+
+ UString password;
+ if (passwordEnabled)
+ password = parser[NKey::kPassword].PostStrings[0];
+
+ if (!NFind::DoesFileExist(arcPath))
+ throw kCantFindSFX;
+
+ FString outputDir;
+ if (parser[NKey::kOutputDir].ThereIs)
+ {
+ outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);
+ NName::NormalizeDirPathPrefix(outputDir);
+ }
+
+
+ wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath);
+
+ {
+ UStringVector v1, v2;
+ v1.Add(fs2us(arcPath));
+ v2.Add(fs2us(arcPath));
+ const NWildcard::CCensorNode &wildcardCensorHead =
+ wildcardCensor.Pairs.Front().Head;
+
+ CCodecs *codecs = new CCodecs;
+ CMyComPtr<
+ #ifdef EXTERNAL_CODECS
+ ICompressCodecsInfo
+ #else
+ IUnknown
+ #endif
+ > compressCodecsInfo = codecs;
+ {
+ HRESULT result = codecs->Load();
+ if (result != S_OK)
+ throw CSystemException(result);
+ }
+
+ if (command.CommandType != NCommandType::kList)
+ {
+ CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
+ CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
+ ecs->Init(g_StdStream, &g_StdErr, g_StdStream);
+
+ #ifndef _NO_CRYPTO
+ ecs->PasswordIsDefined = passwordEnabled;
+ ecs->Password = password;
+ #endif
+
+ /*
+ COpenCallbackConsole openCallback;
+ openCallback.Init(g_StdStream, g_StdStream);
+
+ #ifndef _NO_CRYPTO
+ openCallback.PasswordIsDefined = passwordEnabled;
+ openCallback.Password = password;
+ #endif
+ */
+
+ CExtractOptions eo;
+ eo.StdOutMode = false;
+ eo.YesToAll = yesToAll;
+ eo.TestMode = command.CommandType == NCommandType::kTest;
+ eo.PathMode = NExtract::NPathMode::kFullPaths;
+ eo.OverwriteMode = yesToAll ?
+ NExtract::NOverwriteMode::kOverwrite :
+ NExtract::NOverwriteMode::kAsk;
+ eo.OutputDir = outputDir;
+
+ UString errorMessage;
+ CDecompressStat stat;
+ HRESULT result = Extract(
+ codecs, CObjectVector<COpenType>(), CIntVector(),
+ v1, v2,
+ wildcardCensorHead,
+ eo, ecs, ecs,
+ // NULL, // hash
+ errorMessage, stat);
+ if (!errorMessage.IsEmpty())
+ {
+ (*g_StdStream) << endl << "Error: " << errorMessage;;
+ if (result == S_OK)
+ result = E_FAIL;
+ }
+
+ if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
+ {
+ if (ecs->NumArcsWithError != 0)
+ (*g_StdStream) << endl << "Archive Errors" << endl;
+ if (ecs->NumFileErrors != 0)
+ (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl;
+ return NExitCode::kFatalError;
+ }
+ if (result != S_OK)
+ throw CSystemException(result);
+ }
+ else
+ {
+ throw CSystemException(E_NOTIMPL);
+
+ /*
+ UInt64 numErrors = 0;
+ UInt64 numWarnings = 0;
+ HRESULT result = ListArchives(
+ codecs, CObjectVector<COpenType>(), CIntVector(),
+ false, // stdInMode
+ v1, v2,
+ true, // processAltStreams
+ false, // showAltStreams
+ wildcardCensorHead,
+ true, // enableHeaders
+ false, // techMode
+ #ifndef _NO_CRYPTO
+ passwordEnabled, password,
+ #endif
+ numErrors, numWarnings);
+ if (numErrors > 0)
+ {
+ g_StdOut << endl << "Errors: " << numErrors;
+ return NExitCode::kFatalError;
+ }
+ if (result != S_OK)
+ throw CSystemException(result);
+ */
+ }
+ }
+ return 0;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/makefile b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/makefile
new file mode 100644
index 0000000000..30e8a388b4
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/makefile
@@ -0,0 +1,135 @@
+PROG = 7zCon.sfx
+MY_CONSOLE = 1
+MY_FIXED = 1
+
+CFLAGS = $(CFLAGS) \
+ -DEXTRACT_ONLY \
+ -DNO_READ_FROM_CODER \
+ -D_SFX \
+ -D_CONSOLE \
+
+CURRENT_OBJS = \
+ $O\SfxCon.obj \
+
+CONSOLE_OBJS = \
+ $O\ConsoleClose.obj \
+ $O\ExtractCallbackConsole.obj \
+ $O\List.obj \
+ $O\MainAr.obj \
+ $O\OpenCallbackConsole.obj \
+ $O\PercentPrinter.obj \
+ $O\UserInputUtils.obj \
+
+COMMON_OBJS = \
+ $O\CommandLineParser.obj \
+ $O\CRC.obj \
+ $O\IntToString.obj \
+ $O\MyString.obj \
+ $O\MyVector.obj \
+ $O\NewHandler.obj \
+ $O\StdInStream.obj \
+ $O\StdOutStream.obj \
+ $O\StringConvert.obj \
+ $O\Wildcard.obj \
+ $O\UTFConvert.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\ErrorMsg.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConv.obj \
+ $O\Synchronization.obj \
+ $O\System.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\CreateCoder.obj \
+ $O\CWrappers.obj \
+ $O\FilePathAutoRename.obj \
+ $O\FileStreams.obj \
+ $O\InBuffer.obj \
+ $O\FilterCoder.obj \
+ $O\LimitedStreams.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\PropId.obj \
+ $O\StreamBinder.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+ $O\VirtThread.obj \
+
+UI_COMMON_OBJS = \
+ $O\ArchiveExtractCallback.obj \
+ $O\ArchiveOpenCallback.obj \
+ $O\DefaultName.obj \
+ $O\LoadCodecs.obj \
+ $O\Extract.obj \
+ $O\ExtractingFilePath.obj \
+ $O\OpenArchive.obj \
+ $O\PropIDUtils.obj \
+
+AR_OBJS = \
+ $O\SplitHandler.obj \
+
+AR_COMMON_OBJS = \
+ $O\CoderMixer2.obj \
+ $O\ItemNameUtils.obj \
+ $O\MultiStream.obj \
+ $O\OutStreamWithCRC.obj \
+
+
+7Z_OBJS = \
+ $O\7zDecode.obj \
+ $O\7zExtract.obj \
+ $O\7zHandler.obj \
+ $O\7zIn.obj \
+ $O\7zRegister.obj \
+
+COMPRESS_OBJS = \
+ $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 \
+ $O\LzmaRegister.obj \
+ $O\PpmdDecoder.obj \
+ $O\PpmdRegister.obj \
+
+CRYPTO_OBJS = \
+ $O\7zAes.obj \
+ $O\7zAesRegister.obj \
+ $O\MyAes.obj \
+
+C_OBJS = \
+ $O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bra.obj \
+ $O\Bra86.obj \
+ $O\BraIA64.obj \
+ $O\CpuArch.obj \
+ $O\Delta.obj \
+ $O\DllSecur.obj \
+ $O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
+ $O\LzmaDec.obj \
+ $O\MtDec.obj \
+ $O\Ppmd7.obj \
+ $O\Ppmd7Dec.obj \
+ $O\Sha256.obj \
+ $O\Threads.obj \
+
+!include "../../Aes.mak"
+!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/resource.rc b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/resource.rc
new file mode 100644
index 0000000000..97882cd3cb
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx")
+
+101 ICON "7z.ico" \ No newline at end of file
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
new file mode 100644
index 0000000000..d35a24fec0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp
@@ -0,0 +1,246 @@
+// ExtractCallbackSfx.h
+
+#include "StdAfx.h"
+
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
+
+#include "ExtractCallbackSfx.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+static LPCSTR const kCantDeleteFile = "Can not delete output file";
+static LPCSTR const kCantOpenFile = "Can not open output file";
+static LPCSTR const kUnsupportedMethod = "Unsupported Method";
+
+void CExtractCallbackImp::Init(IInArchive *archiveHandler,
+ const FString &directoryPath,
+ const UString &itemDefaultName,
+ const FILETIME &defaultMTime,
+ UInt32 defaultAttributes)
+{
+ _message.Empty();
+ _isCorrupt = false;
+ _itemDefaultName = itemDefaultName;
+ _defaultMTime = defaultMTime;
+ _defaultAttributes = defaultAttributes;
+ _archiveHandler = archiveHandler;
+ _directoryPath = directoryPath;
+ NName::NormalizeDirPathPrefix(_directoryPath);
+}
+
+HRESULT CExtractCallbackImp::Open_CheckBreak()
+{
+ #ifndef _NO_PROGRESS
+ return ProgressDialog.Sync.ProcessStopAndPause();
+ #else
+ return S_OK;
+ #endif
+}
+
+HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
+{
+ return S_OK;
+}
+
+HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
+{
+ #ifndef _NO_PROGRESS
+ return ProgressDialog.Sync.ProcessStopAndPause();
+ #else
+ return S_OK;
+ #endif
+}
+
+HRESULT CExtractCallbackImp::Open_Finished()
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size)
+{
+ #ifndef _NO_PROGRESS
+ ProgressDialog.Sync.SetProgress(size, 0);
+ #endif
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue)
+{
+ #ifndef _NO_PROGRESS
+ RINOK(ProgressDialog.Sync.ProcessStopAndPause());
+ if (completeValue != NULL)
+ ProgressDialog.Sync.SetPos(*completeValue);
+ #endif
+ return S_OK;
+}
+
+void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
+{
+ FString fullPath = _directoryPath;
+ FOR_VECTOR (i, dirPathParts)
+ {
+ fullPath += us2fs(dirPathParts[i]);
+ CreateDir(fullPath);
+ fullPath.Add_PathSepar();
+ }
+}
+
+STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index,
+ ISequentialOutStream **outStream, Int32 askExtractMode)
+{
+ #ifndef _NO_PROGRESS
+ if (ProgressDialog.Sync.GetStopped())
+ return E_ABORT;
+ #endif
+ _outFileStream.Release();
+
+ UString fullPath;
+ {
+ 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;
+ }
+
+ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
+ if (prop.vt == VT_EMPTY)
+ _processedFileInfo.Attributes = _defaultAttributes;
+ else
+ {
+ if (prop.vt != VT_UI4)
+ return E_FAIL;
+ _processedFileInfo.Attributes = prop.ulVal;
+ }
+
+ RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop));
+ _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal);
+
+ bool isAnti = false;
+ {
+ NCOM::CPropVariant propTemp;
+ RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp));
+ if (propTemp.vt == VT_BOOL)
+ isAnti = VARIANT_BOOLToBool(propTemp.boolVal);
+ }
+
+ RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));
+ switch (prop.vt)
+ {
+ case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;
+ case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;
+ default: return E_FAIL;
+ }
+
+ UStringVector pathParts;
+ SplitPathToParts(fullPath, pathParts);
+ if (pathParts.IsEmpty())
+ return E_FAIL;
+
+ UString processedPath = fullPath;
+
+ if (!_processedFileInfo.IsDir)
+ pathParts.DeleteBack();
+ if (!pathParts.IsEmpty())
+ {
+ if (!isAnti)
+ CreateComplexDirectory(pathParts);
+ }
+
+ FString fullProcessedPath = _directoryPath + us2fs(processedPath);
+
+ if (_processedFileInfo.IsDir)
+ {
+ _diskFilePath = fullProcessedPath;
+
+ if (isAnti)
+ RemoveDir(_diskFilePath);
+ else
+ SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);
+ return S_OK;
+ }
+
+ NFind::CFileInfo fileInfo;
+ if (fileInfo.Find(fullProcessedPath))
+ {
+ if (!DeleteFileAlways(fullProcessedPath))
+ {
+ _message = kCantDeleteFile;
+ return E_FAIL;
+ }
+ }
+
+ if (!isAnti)
+ {
+ _outFileStreamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
+ if (!_outFileStreamSpec->Create(fullProcessedPath, true))
+ {
+ _message = kCantOpenFile;
+ return E_FAIL;
+ }
+ _outFileStream = outStreamLoc;
+ *outStream = outStreamLoc.Detach();
+ }
+ _diskFilePath = fullProcessedPath;
+ }
+ else
+ {
+ *outStream = NULL;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode)
+{
+ _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult)
+{
+ switch (resultEOperationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kOK:
+ break;
+
+ default:
+ {
+ _outFileStream.Release();
+ switch (resultEOperationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
+ _message = kUnsupportedMethod;
+ break;
+ default:
+ _isCorrupt = true;
+ }
+ return E_FAIL;
+ }
+ }
+ if (_outFileStream != NULL)
+ {
+ _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
+ RINOK(_outFileStreamSpec->Close());
+ }
+ _outFileStream.Release();
+ if (_extractMode)
+ SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes);
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h
new file mode 100644
index 0000000000..b7f04e0ec0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h
@@ -0,0 +1,86 @@
+// ExtractCallbackSfx.h
+
+#ifndef __EXTRACT_CALLBACK_SFX_H
+#define __EXTRACT_CALLBACK_SFX_H
+
+#include "resource.h"
+
+#include "../../../Windows/ResourceString.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../ICoder.h"
+
+#include "../../UI/FileManager/LangUtils.h"
+
+#ifndef _NO_PROGRESS
+#include "../../UI/FileManager/ProgressDialog.h"
+#endif
+#include "../../UI/Common/ArchiveOpenCallback.h"
+
+class CExtractCallbackImp:
+ public IArchiveExtractCallback,
+ public IOpenCallbackUI,
+ public CMyUnknownImp
+{
+public:
+
+ MY_UNKNOWN_IMP
+
+ INTERFACE_IArchiveExtractCallback(;)
+ INTERFACE_IOpenCallbackUI(;)
+
+private:
+ CMyComPtr<IInArchive> _archiveHandler;
+ FString _directoryPath;
+ UString _filePath;
+ FString _diskFilePath;
+
+ bool _extractMode;
+ struct CProcessedFileInfo
+ {
+ FILETIME MTime;
+ bool IsDir;
+ UInt32 Attributes;
+ } _processedFileInfo;
+
+ COutFileStream *_outFileStreamSpec;
+ CMyComPtr<ISequentialOutStream> _outFileStream;
+
+ UString _itemDefaultName;
+ FILETIME _defaultMTime;
+ UInt32 _defaultAttributes;
+
+ void CreateComplexDirectory(const UStringVector &dirPathParts);
+public:
+ #ifndef _NO_PROGRESS
+ CProgressDialog ProgressDialog;
+ #endif
+
+ bool _isCorrupt;
+ UString _message;
+
+ void Init(IInArchive *archiveHandler,
+ const FString &directoryPath,
+ const UString &itemDefaultName,
+ const FILETIME &defaultMTime,
+ UInt32 defaultAttributes);
+
+ #ifndef _NO_PROGRESS
+ HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread)
+ {
+ ProgressDialog.Create(title, thread, 0);
+ {
+ ProgressDialog.SetText(LangString(IDS_PROGRESS_EXTRACTING));
+ }
+
+ ProgressDialog.Show(SW_SHOWNORMAL);
+ return S_OK;
+ }
+ virtual ~CExtractCallbackImp() { ProgressDialog.Destroy(); }
+ #endif
+
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
new file mode 100644
index 0000000000..194e376143
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp
@@ -0,0 +1,137 @@
+// ExtractEngine.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/Thread.h"
+
+#include "../../UI/Common/OpenArchive.h"
+
+#include "../../UI/FileManager/FormatUtils.h"
+#include "../../UI/FileManager/LangUtils.h"
+
+#include "ExtractCallbackSfx.h"
+#include "ExtractEngine.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+static LPCSTR const kCantFindArchive = "Can not find archive file";
+static LPCSTR const kCantOpenArchive = "Can not open the file as archive";
+
+struct CThreadExtracting
+{
+ CCodecs *Codecs;
+ FString FileName;
+ FString DestFolder;
+
+ CExtractCallbackImp *ExtractCallbackSpec;
+ CMyComPtr<IArchiveExtractCallback> ExtractCallback;
+
+ CArchiveLink ArchiveLink;
+ HRESULT Result;
+ UString ErrorMessage;
+
+ void Process2()
+ {
+ NFind::CFileInfo fi;
+ if (!fi.Find(FileName))
+ {
+ ErrorMessage = kCantFindArchive;
+ Result = E_FAIL;
+ return;
+ }
+
+ CObjectVector<COpenType> incl;
+ CIntVector excl;
+ COpenOptions options;
+ options.codecs = Codecs;
+ options.types = &incl;
+ options.excludedFormats = &excl;
+ options.filePath = fs2us(FileName);
+
+ Result = ArchiveLink.Open2(options, ExtractCallbackSpec);
+ if (Result != S_OK)
+ {
+ ErrorMessage = kCantOpenArchive;
+ return;
+ }
+
+ FString dirPath = DestFolder;
+ NName::NormalizeDirPathPrefix(dirPath);
+
+ if (!CreateComplexDir(dirPath))
+ {
+ ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,
+ #ifdef LANG
+ 0x02000603,
+ #endif
+ fs2us(dirPath));
+ Result = E_FAIL;
+ return;
+ }
+
+ ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)"Default", fi.MTime, 0);
+
+ Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback);
+ }
+
+ void Process()
+ {
+ try
+ {
+ #ifndef _NO_PROGRESS
+ CProgressCloser closer(ExtractCallbackSpec->ProgressDialog);
+ #endif
+ Process2();
+ }
+ catch(...) { Result = E_FAIL; }
+ }
+
+ static THREAD_FUNC_DECL MyThreadFunction(void *param)
+ {
+ ((CThreadExtracting *)param)->Process();
+ return 0;
+ }
+};
+
+HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,
+ bool showProgress, bool &isCorrupt, UString &errorMessage)
+{
+ isCorrupt = false;
+ CThreadExtracting t;
+
+ t.Codecs = codecs;
+ t.FileName = fileName;
+ t.DestFolder = destFolder;
+
+ t.ExtractCallbackSpec = new CExtractCallbackImp;
+ t.ExtractCallback = t.ExtractCallbackSpec;
+
+ #ifndef _NO_PROGRESS
+
+ if (showProgress)
+ {
+ t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON;
+ NWindows::CThread thread;
+ RINOK(thread.Create(CThreadExtracting::MyThreadFunction, &t));
+
+ UString title;
+ LangString(IDS_PROGRESS_EXTRACTING, title);
+ t.ExtractCallbackSpec->StartProgressDialog(title, thread);
+ }
+ else
+
+ #endif
+ {
+ t.Process2();
+ }
+
+ errorMessage = t.ErrorMessage;
+ if (errorMessage.IsEmpty())
+ errorMessage = t.ExtractCallbackSpec->_message;
+ isCorrupt = t.ExtractCallbackSpec->_isCorrupt;
+ return t.Result;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h
new file mode 100644
index 0000000000..8aa9724e27
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h
@@ -0,0 +1,11 @@
+// ExtractEngine.h
+
+#ifndef __EXTRACT_ENGINE_H
+#define __EXTRACT_ENGINE_H
+
+#include "../../UI/Common/LoadCodecs.h"
+
+HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,
+ bool showProgress, bool &isCorrupt, UString &errorMessage);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
new file mode 100644
index 0000000000..61cb260c1f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp
@@ -0,0 +1,803 @@
+# Microsoft Developer Studio Project File - Name="SFXSetup" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=SFXSetup - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "SFXSetup.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "SFXSetup.mak" CFG="SFXSetup - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SFXSetup - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "SFXSetup - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "SFXSetup - Win32 ReleaseD" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "SFXSetup - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /out:"Release\7zS.sfx" /opt:NOWIN98 /delayload:user32.dll /delayload:shell32.dll /delayload:oleaut32.dll
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "SFXSetup - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug\7zSfxS.exe" /pdbtype:sept /delayload:user32.dll /delayload:shell32.dll /delayload:oleaut32.dll
+
+!ELSEIF "$(CFG)" == "SFXSetup - Win32 ReleaseD"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseD"
+# PROP BASE Intermediate_Dir "ReleaseD"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseD"
+# PROP Intermediate_Dir "ReleaseD"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_SFX" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zWinSR.exe"
+# SUBTRACT BASE LINK32 /debug /nodefaultlib
+# 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 delayimp.lib /nologo /subsystem:windows /machine:I386 /out:"ReleaseD\7zSD.sfx" /opt:NOWIN98 /delayload:user32.dll /delayload:shell32.dll /delayload:oleaut32.dll
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "SFXSetup - Win32 Release"
+# Name "SFXSetup - Win32 Debug"
+# Name "SFXSetup - Win32 ReleaseD"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Interface"
+
+# PROP Default_Filter ""
+# End Group
+# Begin Group "7z"
+
+# PROP Default_Filter ""
+# 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\7zExtract.cpp
+# 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\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\7zRegister.cpp
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# 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\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Coder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjRegister.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\Compress\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\Compress\Lzma2Decoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma2Register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaRegister.cpp
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\TextConfig.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\TextConfig.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Group "Control"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Dialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Dialog.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ErrorMsg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ErrorMsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.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
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Window.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Window.h
+# End Source File
+# End Group
+# Begin Group "7z Common"
+
+# 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\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+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\InBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LimitedStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LimitedStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\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
+
+SOURCE=..\..\Common\StreamObjects.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.h
+# End Source File
+# End Group
+# Begin Group "UI"
+
+# PROP Default_Filter ""
+# Begin Group "Explorer"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Explorer\MyMessages.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Explorer\MyMessages.h
+# End Source File
+# End Group
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "File Manager"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\FormatUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\FormatUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\LangUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\ProgressDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\ProgressDialog.h
+# End Source File
+# End Group
+# Begin Group "C"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrcOpt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\..\..\C\Bra86.c
+# SUBTRACT CPP /YX /Yc /Yu
+# 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\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\DllSecur.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\DllSecur.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2Dec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2Dec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.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\MtDec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\MtDec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ExtractCallbackSfx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ExtractCallbackSfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ExtractEngine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ExtractEngine.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\setup.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\SfxSetup.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw
new file mode 100644
index 0000000000..2970370140
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "SFXSetup"=.\SFXSetup.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
new file mode 100644
index 0000000000..459c35d6e0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -0,0 +1,875 @@
+// Main.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyWindows.h"
+
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/TextConfig.h"
+
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileIO.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/NtCheck.h"
+#include "../../../Windows/ResourceString.h"
+
+#include "../../UI/Explorer/MyMessages.h"
+
+#include "ExtractEngine.h"
+
+#include "../../../../C/DllSecur.h"
+
+#include "resource.h"
+
+/* BEGIN Mozilla customizations */
+#include "../../../Common/IntToString.h"
+/* END Mozilla customizations */
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+HINSTANCE g_hInstance;
+
+static CFSTR const kTempDirPrefix = FTEXT("7zS");
+
+#define _SHELL_EXECUTE
+
+static bool ReadDataString(CFSTR fileName, LPCSTR startID,
+ LPCSTR endID, AString &stringResult)
+{
+ stringResult.Empty();
+ NIO::CInFile inFile;
+ if (!inFile.Open(fileName))
+ return false;
+ const int kBufferSize = (1 << 12);
+
+ Byte buffer[kBufferSize];
+ int signatureStartSize = MyStringLen(startID);
+ int signatureEndSize = MyStringLen(endID);
+
+ UInt32 numBytesPrev = 0;
+ bool writeMode = false;
+ UInt64 posTotal = 0;
+ for (;;)
+ {
+ if (posTotal > (1 << 20))
+ return (stringResult.IsEmpty());
+ UInt32 numReadBytes = kBufferSize - numBytesPrev;
+ UInt32 processedSize;
+ if (!inFile.Read(buffer + numBytesPrev, numReadBytes, processedSize))
+ return false;
+ if (processedSize == 0)
+ return true;
+ UInt32 numBytesInBuffer = numBytesPrev + processedSize;
+ UInt32 pos = 0;
+ for (;;)
+ {
+ if (writeMode)
+ {
+ if (pos > numBytesInBuffer - signatureEndSize)
+ break;
+ if (memcmp(buffer + pos, endID, signatureEndSize) == 0)
+ return true;
+ char b = buffer[pos];
+ if (b == 0)
+ return false;
+ stringResult += b;
+ pos++;
+ }
+ else
+ {
+ if (pos > numBytesInBuffer - signatureStartSize)
+ break;
+ if (memcmp(buffer + pos, startID, signatureStartSize) == 0)
+ {
+ writeMode = true;
+ pos += signatureStartSize;
+ }
+ else
+ pos++;
+ }
+ }
+ numBytesPrev = numBytesInBuffer - pos;
+ posTotal += pos;
+ memmove(buffer, buffer + pos, numBytesPrev);
+ }
+}
+
+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 };
+
+struct CInstallIDInit
+{
+ CInstallIDInit()
+ {
+ kStartID[0] = ';';
+ kEndID[0] = ';';
+ };
+} g_CInstallIDInit;
+
+
+#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1;
+
+static void ShowErrorMessageSpec(const UString &name)
+{
+ UString message = NError::MyFormatMessage(::GetLastError());
+ int pos = message.Find(L"%1");
+ if (pos >= 0)
+ {
+ message.Delete(pos, 2);
+ message.Insert(pos, name);
+ }
+ ShowErrorMessage(NULL, message);
+}
+
+/* BEGIN Mozilla customizations */
+
+static char const *
+FindStrInBuf(char const * buf, size_t bufLen, char const * str)
+{
+ size_t index = 0;
+ while (index < bufLen) {
+ char const * result = strstr(buf + index, str);
+ if (result) {
+ return result;
+ }
+ while ((buf[index] != '\0') && (index < bufLen)) {
+ index++;
+ }
+ index++;
+ }
+ return NULL;
+}
+
+static bool
+ReadPostSigningDataFromView(char const * view, DWORD size, AString& data)
+{
+ // Find the offset and length of the certificate table,
+ // so we know the valid range to look for the token.
+ if (size < (0x3c + sizeof(UInt32))) {
+ return false;
+ }
+ UInt32 PEHeaderOffset = *(UInt32*)(view + 0x3c);
+ UInt32 optionalHeaderOffset = PEHeaderOffset + 24;
+ UInt32 certDirEntryOffset = 0;
+ if (size < (optionalHeaderOffset + sizeof(UInt16))) {
+ return false;
+ }
+ UInt16 magic = *(UInt16*)(view + optionalHeaderOffset);
+ if (magic == 0x010b) {
+ // 32-bit executable
+ certDirEntryOffset = optionalHeaderOffset + 128;
+ } else if (magic == 0x020b) {
+ // 64-bit executable; certain header fields are wider
+ certDirEntryOffset = optionalHeaderOffset + 144;
+ } else {
+ // Unknown executable
+ return false;
+ }
+ if (size < certDirEntryOffset + 8) {
+ return false;
+ }
+ UInt32 certTableOffset = *(UInt32*)(view + certDirEntryOffset);
+ UInt32 certTableLen = *(UInt32*)(view + certDirEntryOffset + sizeof(UInt32));
+ if (certTableOffset == 0 || certTableLen == 0 ||
+ size < (certTableOffset + certTableLen)) {
+ return false;
+ }
+
+ char const token[] = "__MOZCUSTOM__:";
+ // We're searching for a string inside a binary blob,
+ // so a normal strstr that bails on the first NUL won't work.
+ char const * tokenPos = FindStrInBuf(view + certTableOffset,
+ certTableLen, token);
+ if (tokenPos) {
+ size_t tokenLen = (sizeof(token) / sizeof(token[0])) - 1;
+ data = AString(tokenPos + tokenLen);
+ return true;
+ }
+ return false;
+}
+
+static bool
+ReadPostSigningData(UString exePath, AString& data)
+{
+ bool retval = false;
+ HANDLE exeFile = CreateFileW(exePath, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (exeFile != INVALID_HANDLE_VALUE) {
+ HANDLE mapping = CreateFileMapping(exeFile, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (mapping != INVALID_HANDLE_VALUE) {
+ // MSDN claims the return value on failure is NULL,
+ // but I've also seen it returned on success, so double-check.
+ if (mapping || GetLastError() == ERROR_SUCCESS) {
+ char * view = (char*)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
+ if (view) {
+ DWORD fileSize = GetFileSize(exeFile, NULL);
+ retval = ReadPostSigningDataFromView(view, fileSize, data);
+ }
+ CloseHandle(mapping);
+ }
+ }
+ CloseHandle(exeFile);
+ }
+ return retval;
+}
+
+// Simple class for allocating a character buffer and automatically freeing it
+// when it goes out of scope.
+class AutoCharBuffer {
+private:
+ char *buffer;
+
+ void Alloc(UInt32 size) {
+ buffer = new char[size];
+ length = 0;
+ }
+public:
+ // Other than being reset when the buffer is deallocated/reallocated, this
+ // isn't updated by this class.
+ UInt32 length;
+
+ AutoCharBuffer()
+ : length(0)
+ , buffer(NULL) {}
+
+ AutoCharBuffer(UInt32 size) {
+ Alloc(size);
+ }
+
+ void Realloc(UInt32 size) {
+ delete [] buffer;
+ Alloc(size);
+ }
+
+ void Dealloc() {
+ delete [] buffer;
+ buffer = NULL;
+ length = 0;
+ }
+
+ virtual ~AutoCharBuffer() {
+ Dealloc();
+ }
+
+ char *Buffer() {
+ return buffer;
+ }
+};
+
+static void
+AppendStringValueToIni(AString& iniData, const char* key, const char* value) {
+ iniData += key;
+ iniData += '=';
+ iniData += value;
+ iniData += '\n';
+}
+
+static void
+AppendDwordValueToIni(AString& iniData, const char* key, DWORD intValue) {
+ AString stringValue;
+ stringValue.Add_UInt32(intValue);
+ AppendStringValueToIni(iniData, key, stringValue.Ptr());
+}
+
+static void
+AppendQwordValueToIni(AString& iniData, const char* key, LONGLONG intValue) {
+ // The implementations for `Convert<int_type>ToString` are a little wonky and
+ // expect the output buffer to just be the correct size. To make sure we are
+ // using it right here, this int conversion implementation was copied from
+ // `CStdOutStream::operator<<(Int64 number)` in `StdOutStream.cpp`.
+ char stringValue[32];
+ ConvertInt64ToString(intValue, stringValue);
+ AppendStringValueToIni(iniData, key, stringValue);
+}
+
+static void
+ReadExeFileSystemIntoIniData(const UString &exePath, AString& iniData) {
+ const char* fsKey = "fileSystem";
+ const char* readFsErrorTypeKey = "readFsError";
+ const char* readFsErrorCodeKey = "readFsErrorCode";
+
+ HANDLE exeFile = CreateFileW(exePath, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (exeFile == INVALID_HANDLE_VALUE) {
+ DWORD errorCode = GetLastError();
+ AppendStringValueToIni(iniData, readFsErrorTypeKey, "openFile");
+ AppendDwordValueToIni(iniData, readFsErrorCodeKey, errorCode);
+ return;
+ }
+
+ const size_t bufferSize = MAX_PATH + 1;
+ wchar_t buffer[bufferSize];
+ BOOL success = GetVolumeInformationByHandleW(exeFile, NULL, 0, NULL, NULL,
+ NULL, buffer, bufferSize);
+ if (!success) {
+ DWORD errorCode = GetLastError();
+ AppendStringValueToIni(iniData, readFsErrorTypeKey, "getVolInfo");
+ AppendDwordValueToIni(iniData, readFsErrorCodeKey, errorCode);
+ CloseHandle(exeFile);
+ return;
+ }
+ CloseHandle(exeFile);
+
+ size_t fsLen = wcsnlen(buffer, bufferSize);
+ if (fsLen == bufferSize) {
+ AppendStringValueToIni(iniData, readFsErrorTypeKey, "fsUnterminated");
+ return;
+ }
+
+ const int narrowBufferSize = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, NULL,
+ 0, NULL, NULL);
+ if (narrowBufferSize <= 0) {
+ DWORD errorCode = GetLastError();
+ AppendStringValueToIni(iniData, readFsErrorTypeKey, "getBufferSize");
+ AppendDwordValueToIni(iniData, readFsErrorCodeKey, errorCode);
+ return;
+ }
+ AutoCharBuffer fs(narrowBufferSize);
+ int written = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, fs.Buffer(),
+ narrowBufferSize, NULL, NULL);
+ if (written <= 0) {
+ DWORD errorCode = GetLastError();
+ AppendStringValueToIni(iniData, readFsErrorTypeKey, "convertString");
+ AppendDwordValueToIni(iniData, readFsErrorCodeKey, errorCode);
+ return;
+ }
+
+ // Like "fileSystem=FAT32" or "fileSystem=NTFS".
+ AppendStringValueToIni(iniData, fsKey, fs.Buffer());
+}
+
+// Read Zone Identifier information from alternate data stream.
+// Always either returns the data that was read, or data indicating what sort of
+// error was encountered when obtaining the data.
+// When this function returns, `metadata` is guaranteed to contain relevant
+// metadata that should be written out. But `data.Buffer()` may be null
+// depending on whether we successfully read data.
+static void
+ReadZoneIdentifierData(const UString &exePath, AString& metadata,
+ AutoCharBuffer& data)
+{
+ metadata.Empty();
+ data.Dealloc();
+
+ // We don't want to allow this function to just read an unlimited amount into
+ // `data`, so this value will control at what point we consider the file too
+ // big to be valid.
+ // 1 MB should be way more than enough. The Zone Identifier file generally
+ // consists of no more than 4 short lines of text.
+ const size_t maxReadSize = 1 * 1000 * 1000;
+ const char* readZoneIdErrorTypeKey = "readZoneIdError";
+ const char* readZoneIdErrorCodeKey = "readZoneIdErrorCode";
+ // It looks like the Zone Identifier will be INI data. But since there is no
+ // real guarantee of this, we are going to put an INI-compatible sentinel
+ // before we start appending the Zone Identifier file. This should help us
+ // better parse the file contents if we discover, say, that there is another
+ // possible format for Zone Identifier data.
+ const char* zoneIdStartSentinel = "\n[MozillaZoneIdentifierStartSentinel]\n";
+
+ metadata += "[Mozilla]\n";
+ ReadExeFileSystemIntoIniData(exePath, metadata);
+
+ UString adsPath(exePath);
+ // A colon (`:`) is not a valid path constituent (see
+ // https://learn.microsoft.com/en-ca/windows/win32/fileio/naming-a-file), so
+ // file systems that don't support ADS will fail to open rather than open an
+ // unrelated file.
+ adsPath += L":Zone.Identifier";
+ HANDLE adsFile = CreateFileW(adsPath, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (adsFile == INVALID_HANDLE_VALUE) {
+ DWORD errorCode = GetLastError();
+ AppendStringValueToIni(metadata, readZoneIdErrorTypeKey, "openFile");
+ AppendDwordValueToIni(metadata, readZoneIdErrorCodeKey, errorCode);
+ return;
+ }
+
+ LARGE_INTEGER fileSize;
+ BOOL success = GetFileSizeEx(adsFile, &fileSize);
+ UInt32 bufferSize = maxReadSize;
+ if (!success) {
+ AppendStringValueToIni(metadata, "zoneIdFileSize", "unknown");
+ AppendStringValueToIni(metadata, "zoneIdBufferLargeEnough", "unknown");
+ } else {
+ AppendQwordValueToIni(metadata, "zoneIdFileSize", fileSize.QuadPart);
+ if (fileSize.QuadPart < (LONGLONG)bufferSize) {
+ AppendStringValueToIni(metadata, "zoneIdBufferLargeEnough", "true");
+ bufferSize = (UInt32)fileSize.QuadPart;
+ } else {
+ AppendStringValueToIni(metadata, "zoneIdBufferLargeEnough", "false");
+ }
+ }
+ data.Realloc(bufferSize);
+
+ DWORD readCount;
+ success = ReadFile(adsFile, data.Buffer(), bufferSize, &readCount, NULL);
+ if (!success) {
+ DWORD errorCode = GetLastError();
+ AppendStringValueToIni(metadata, readZoneIdErrorTypeKey, "readFile");
+ AppendDwordValueToIni(metadata, readZoneIdErrorCodeKey, errorCode);
+
+ data.Dealloc();
+ CloseHandle(adsFile);
+ return;
+ }
+ data.length = readCount;
+
+ char dummyBuffer;
+
+ success = ReadFile(adsFile, &dummyBuffer, 1, &readCount, NULL);
+ CloseHandle(adsFile);
+ if (success) {
+ if (readCount == 0) {
+ // We are at the end of the file
+ AppendStringValueToIni(metadata, "zoneIdTruncated", "false");
+ } else {
+ AppendStringValueToIni(metadata, "zoneIdTruncated", "true");
+ }
+ } else {
+ AppendStringValueToIni(metadata, "zoneIdTruncated", "unknown");
+ }
+
+ metadata += zoneIdStartSentinel;
+}
+
+// Delayed load libraries are loaded when the first symbol is used.
+// The following ensures that we load the delayed loaded libraries from the
+// system directory.
+struct AutoLoadSystemDependencies
+{
+ AutoLoadSystemDependencies()
+ {
+ HMODULE module = ::GetModuleHandleW(L"kernel32.dll");
+ if (module) {
+ // SetDefaultDllDirectories is always available on Windows 8 and above. It
+ // is also available on Windows Vista, Windows Server 2008, and
+ // Windows 7 when MS KB2533623 has been applied.
+ typedef BOOL (WINAPI *SetDefaultDllDirectoriesType)(DWORD);
+ SetDefaultDllDirectoriesType setDefaultDllDirectories =
+ (SetDefaultDllDirectoriesType) GetProcAddress(module, "SetDefaultDllDirectories");
+ if (setDefaultDllDirectories) {
+ setDefaultDllDirectories(0x0800 /* LOAD_LIBRARY_SEARCH_SYSTEM32 */ );
+ return;
+ }
+ }
+
+ static LPCWSTR delayDLLs[] = { L"uxtheme.dll", L"userenv.dll",
+ L"setupapi.dll", L"apphelp.dll",
+ L"propsys.dll", L"dwmapi.dll",
+ L"cryptbase.dll", L"oleacc.dll",
+ L"clbcatq.dll" };
+ WCHAR systemDirectory[MAX_PATH + 1] = { L'\0' };
+ // If GetSystemDirectory fails we accept that we'll load the DLLs from the
+ // normal search path.
+ GetSystemDirectoryW(systemDirectory, MAX_PATH + 1);
+ size_t systemDirLen = wcslen(systemDirectory);
+
+ // Make the system directory path terminate with a slash
+ if (systemDirectory[systemDirLen - 1] != L'\\' && systemDirLen) {
+ systemDirectory[systemDirLen] = L'\\';
+ ++systemDirLen;
+ // No need to re-NULL terminate
+ }
+
+ // For each known DLL ensure it is loaded from the system32 directory
+ for (size_t i = 0; i < sizeof(delayDLLs) / sizeof(delayDLLs[0]); ++i) {
+ size_t fileLen = wcslen(delayDLLs[i]);
+ wcsncpy(systemDirectory + systemDirLen, delayDLLs[i],
+ MAX_PATH - systemDirLen);
+ if (systemDirLen + fileLen <= MAX_PATH) {
+ systemDirectory[systemDirLen + fileLen] = L'\0';
+ } else {
+ systemDirectory[MAX_PATH] = L'\0';
+ }
+ LPCWSTR fullModulePath = systemDirectory; // just for code readability
+ LoadLibraryW(fullModulePath);
+ }
+ }
+} loadDLLs;
+
+BOOL
+RemoveCurrentDirFromSearchPath()
+{
+ // kernel32.dll is in the knownDLL list so it is safe to load without a full path
+ HMODULE kernel32 = LoadLibraryW(L"kernel32.dll");
+ if (!kernel32) {
+ return FALSE;
+ }
+
+ typedef BOOL (WINAPI *SetDllDirectoryType)(LPCWSTR);
+ SetDllDirectoryType SetDllDirectoryFn =
+ (SetDllDirectoryType)GetProcAddress(kernel32, "SetDllDirectoryW");
+ if (!SetDllDirectoryFn) {
+ FreeLibrary(kernel32);
+ return FALSE;
+ }
+
+ // If this call fails we can't do much about it, so ignore it.
+ // It is unlikely to fail and this is just a precaution anyway.
+ SetDllDirectoryFn(L"");
+ FreeLibrary(kernel32);
+ return TRUE;
+}
+
+/* END Mozilla customizations */
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
+ #ifdef UNDER_CE
+ LPWSTR
+ #else
+ LPSTR
+ #endif
+ /* lpCmdLine */,int /* nCmdShow */)
+{
+ /* BEGIN Mozilla customizations */
+ // Disable current directory from being in the search path.
+ // This call does not help with implicitly loaded DLLs.
+ if (!RemoveCurrentDirFromSearchPath()) {
+ WCHAR minOSTitle[512] = { '\0' };
+ WCHAR minOSText[512] = { '\0' };
+ LoadStringW(NULL, IDS_MIN_OS_TITLE, minOSTitle,
+ sizeof(minOSTitle) / sizeof(minOSTitle[0]));
+ LoadStringW(NULL, IDS_MIN_OS_TEXT, minOSText,
+ sizeof(minOSText) / sizeof(minOSText[0]));
+ MessageBoxW(NULL, minOSText, minOSTitle, MB_OK | MB_ICONERROR);
+ return 1;
+ }
+ /* END Mozilla customizations */
+
+ g_hInstance = (HINSTANCE)hInstance;
+
+ NT_CHECK
+
+ // BEGIN Mozilla customizations
+ // Our AutoLoadSystemDependencies (see above) does the same job as the
+ // LoadSecurityDlls function, but slightly better because it runs as a static
+ // initializer, and it doesn't include LOAD_LIBRARY_SEARCH_USER_DIRS in
+ // the search path, which partially defeats the purpose of calling
+ // SetDefaultDllDirectories at all.
+ //#ifdef _WIN32
+ //LoadSecurityDlls();
+ //#endif
+ // END Mozilla customizations
+
+ // InitCommonControls();
+
+ UString archiveName, switches;
+ #ifdef _SHELL_EXECUTE
+ UString executeFile, executeParameters;
+ #endif
+ NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);
+
+ FString fullPath;
+ NDLL::MyGetModuleFileName(fullPath);
+
+ switches.Trim();
+ bool assumeYes = false;
+ if (switches.IsPrefixedBy_Ascii_NoCase("-y"))
+ {
+ assumeYes = true;
+ switches = switches.Ptr(2);
+ switches.Trim();
+ }
+
+ AString config;
+ if (!ReadDataString(fullPath, kStartID, kEndID, config))
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Can't load config info");
+ return 1;
+ }
+
+ UString dirPrefix ("." STRING_PATH_SEPARATOR);
+ UString appLaunched;
+ bool showProgress = true;
+
+ /* BEGIN Mozilla customizations */
+ bool extractOnly = false;
+ if (switches.IsPrefixedBy_NoCase(L"/extractdir=")) {
+ assumeYes = true;
+ showProgress = false;
+ extractOnly = true;
+ } else if (!switches.IsEmpty()) {
+ showProgress = false;
+ }
+ /* END Mozilla customizations */
+
+ if (!config.IsEmpty())
+ {
+ CObjectVector<CTextConfigPair> pairs;
+ if (!GetTextConfig(config, pairs))
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Config failed");
+ return 1;
+ }
+ UString friendlyName = GetTextConfigValue(pairs, "Title");
+ UString installPrompt = GetTextConfigValue(pairs, "BeginPrompt");
+ UString progress = GetTextConfigValue(pairs, "Progress");
+ if (progress.IsEqualTo_Ascii_NoCase("no"))
+ showProgress = false;
+ int index = FindTextConfigItem(pairs, "Directory");
+ if (index >= 0)
+ dirPrefix = pairs[index].String;
+ if (!installPrompt.IsEmpty() && !assumeYes)
+ {
+ if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO |
+ MB_ICONQUESTION) != IDYES)
+ return 0;
+ }
+ appLaunched = GetTextConfigValue(pairs, "RunProgram");
+
+ #ifdef _SHELL_EXECUTE
+ executeFile = GetTextConfigValue(pairs, "ExecuteFile");
+ executeParameters = GetTextConfigValue(pairs, "ExecuteParameters");
+ #endif
+ }
+
+ CTempDir tempDir;
+ /* Mozilla customizations - Added !extractOnly */
+ if (!extractOnly && !tempDir.Create(kTempDirPrefix))
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Can not create temp folder archive");
+ return 1;
+ }
+
+ CCodecs *codecs = new CCodecs;
+ CMyComPtr<IUnknown> compressCodecsInfo = codecs;
+ {
+ HRESULT result = codecs->Load();
+ if (result != S_OK)
+ {
+ ShowErrorMessage(L"Can not load codecs");
+ return 1;
+ }
+ }
+
+ /* BEGIN Mozilla customizations - added extractOnly parameter support */
+ const FString tempDirPath = extractOnly ? switches.Ptr(12) : GetUnicodeString(tempDir.GetPath());
+ /* END Mozilla customizations */
+ // tempDirPath = L"M:\\1\\"; // to test low disk space
+ {
+ bool isCorrupt = false;
+ UString errorMessage;
+ HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress,
+ isCorrupt, errorMessage);
+
+ if (result != S_OK)
+ {
+ if (!assumeYes)
+ {
+ if (result == S_FALSE || isCorrupt)
+ {
+ NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage);
+ result = E_FAIL;
+ }
+ if (result != E_ABORT)
+ {
+ if (errorMessage.IsEmpty())
+ errorMessage = NError::MyFormatMessage(result);
+ ::MessageBoxW(0, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);
+ }
+ }
+ return 1;
+ }
+ }
+
+ /* BEGIN Mozilla customizations */
+ // Retrieve and store any data added to this file after signing.
+ {
+ AString postSigningData;
+ if (ReadPostSigningData(fullPath, postSigningData)) {
+ FString postSigningDataFilePath(tempDirPath);
+ NFile::NName::NormalizeDirPathPrefix(postSigningDataFilePath);
+ postSigningDataFilePath += L"postSigningData";
+
+ NFile::NIO::COutFile postSigningDataFile;
+ postSigningDataFile.Create(postSigningDataFilePath, true);
+
+ UInt32 written = 0;
+ postSigningDataFile.Write(postSigningData, postSigningData.Len(), written);
+ }
+ }
+
+ // Read Zone Identifier information
+ // This will consist of two types of data that we will write to the same file.
+ // First we have the metadata, which will be INI data with these possible
+ // keys:
+ // - `fileSystem`: What file system the executable is on
+ // - `readFsError`: A string describing why we couldn't get the file system.
+ // Either this key will be present or the `fileSystem` key
+ // will be.
+ // - `readFsErrorCode`: An integer returned by `GetLastError()` indicating,
+ // in more detail, why we failed to obtain the file
+ // system. This key may exist if `readFsError` exists.
+ // - `readZoneIdError`: A string describing why we couldn't get the
+ // provenance data.
+ // - `readZoneIdErrorCode`: An integer returned by `GetLastError()`
+ // indicating, in more detail, why we failed to get the
+ // provenance data. This key may exist if
+ // `readZoneIdError` exists.
+ // - `zoneIdFileSize`: Either `"unknown"`, or an integer indicating the
+ // number of bytes in the zone identifier ADS.
+ // - `zoneIdBufferLargeEnough`: Either `"unknown"`, `"true"`, or `"false"`,
+ // indicating whether the file size was bigger
+ // than the maximum size that we will read from
+ // that file.
+ // - `zoneIdTruncated`: Either `"unknown"`, `"true"`, or `"false"`. Indicates
+ // whether or not we saw the end of the ADS file when we
+ // read from it.
+ // The above keys will be in the `"[Mozilla]"` section of the metadata.
+ // The other type of data that will go into the file is the directly copied
+ // data from the Zone Identifier ADS. This _should_ also be INI data, making
+ // the entirety of the file valid INI data.
+ // In the "good" case, this makes things very easy for us since INI reading
+ // functionality is already available. If we see an unexpected amount of
+ // telemetry data reporting that the INI is invalid, we will probably need to
+ // determine what other data formats are possible in that ADS.
+ // To make it easier to separate out the Zone Identifier data from the
+ // metadata, in that case, the metadata will always end with this sentinel,
+ // as long as `zoneIdData` contains valid data:
+ // `"\n[MozillaZoneIdentifierStartSentinel]\n"`
+ {
+ AString metadata;
+ AutoCharBuffer zoneIdData;
+ ReadZoneIdentifierData(fullPath, metadata, zoneIdData);
+ FString zoneIdDataFilePath(tempDirPath);
+ NFile::NName::NormalizeDirPathPrefix(zoneIdDataFilePath);
+ zoneIdDataFilePath += L"zoneIdProvenanceData";
+
+ NFile::NIO::COutFile zoneIdDataFile;
+ zoneIdDataFile.Create(zoneIdDataFilePath, true);
+
+ UInt32 written = 0;
+ zoneIdDataFile.Write(metadata, metadata.Len(), written);
+ if (zoneIdData.length > 0 && zoneIdData.Buffer()) {
+ zoneIdDataFile.Write(zoneIdData.Buffer(), zoneIdData.length, written);
+ }
+ }
+
+ if (extractOnly) {
+ return 0;
+ }
+ /* END Mozilla customizations */
+
+ #ifndef UNDER_CE
+ CCurrentDirRestorer currentDirRestorer;
+ if (!SetCurrentDir(tempDirPath))
+ return 1;
+ #endif
+
+ HANDLE hProcess = 0;
+#ifdef _SHELL_EXECUTE
+ if (!executeFile.IsEmpty())
+ {
+ CSysString filePath (GetSystemString(executeFile));
+ SHELLEXECUTEINFO execInfo;
+ execInfo.cbSize = sizeof(execInfo);
+ execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
+ #ifndef UNDER_CE
+ | SEE_MASK_FLAG_DDEWAIT
+ #endif
+ ;
+ execInfo.hwnd = NULL;
+ execInfo.lpVerb = NULL;
+ execInfo.lpFile = filePath;
+
+ if (!switches.IsEmpty())
+ {
+ executeParameters.Add_Space_if_NotEmpty();
+ executeParameters += switches;
+ }
+
+ CSysString parametersSys (GetSystemString(executeParameters));
+ if (parametersSys.IsEmpty())
+ execInfo.lpParameters = NULL;
+ else
+ execInfo.lpParameters = parametersSys;
+
+ execInfo.lpDirectory = NULL;
+ execInfo.nShow = SW_SHOWNORMAL;
+ execInfo.hProcess = 0;
+ /* BOOL success = */ ::ShellExecuteEx(&execInfo);
+ UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
+ if (result <= 32)
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Can not open file");
+ return 1;
+ }
+ hProcess = execInfo.hProcess;
+ }
+ else
+#endif
+ {
+ if (appLaunched.IsEmpty())
+ {
+ appLaunched = L"setup.exe";
+ if (!NFind::DoesFileExist(us2fs(appLaunched)))
+ {
+ if (!assumeYes)
+ ShowErrorMessage(L"Can not find setup.exe");
+ return 1;
+ }
+ }
+
+ {
+ FString s2 = tempDirPath;
+ NName::NormalizeDirPathPrefix(s2);
+ appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2));
+ }
+
+ UString appNameForError = appLaunched; // actually we need to rtemove parameters also
+
+ appLaunched.Replace(L"%%T", fs2us(tempDirPath));
+
+ if (!switches.IsEmpty())
+ {
+ appLaunched.Add_Space();
+ appLaunched += switches;
+ }
+ STARTUPINFO startupInfo;
+ startupInfo.cb = sizeof(startupInfo);
+ startupInfo.lpReserved = 0;
+ startupInfo.lpDesktop = 0;
+ startupInfo.lpTitle = 0;
+ startupInfo.dwFlags = 0;
+ startupInfo.cbReserved2 = 0;
+ startupInfo.lpReserved2 = 0;
+
+ PROCESS_INFORMATION processInformation;
+
+ CSysString appLaunchedSys (GetSystemString(dirPrefix + appLaunched));
+
+ BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys,
+ NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,
+ &startupInfo, &processInformation);
+ if (createResult == 0)
+ {
+ if (!assumeYes)
+ {
+ // we print name of exe file, if error message is
+ // ERROR_BAD_EXE_FORMAT: "%1 is not a valid Win32 application".
+ ShowErrorMessageSpec(appNameForError);
+ }
+ return 1;
+ }
+ ::CloseHandle(processInformation.hThread);
+ hProcess = processInformation.hProcess;
+ }
+ if (hProcess != 0)
+ {
+ WaitForSingleObject(hProcess, INFINITE);
+ ::CloseHandle(hProcess);
+ }
+ return 0;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.h
new file mode 100644
index 0000000000..72410eecd6
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.h
@@ -0,0 +1,13 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#include <commctrl.h>
+
+// #define printf(x) NO_PRINTF_(x)
+// #define sprintf(x) NO_SPRINTF_(x)
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/makefile b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/makefile
new file mode 100644
index 0000000000..b97daad719
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/makefile
@@ -0,0 +1,117 @@
+PROG = 7zS.sfx
+MY_FIXED = 1
+
+CFLAGS = $(CFLAGS) \
+ -DNO_REGISTRY \
+ -DEXTRACT_ONLY \
+ -DNO_READ_FROM_CODER \
+ -D_SFX \
+ -D_NO_CRYPTO \
+
+CURRENT_OBJS = \
+ $O\SfxSetup.obj \
+ $O\ExtractCallbackSfx.obj \
+ $O\ExtractEngine.obj \
+
+COMMON_OBJS = \
+ $O\CommandLineParser.obj \
+ $O\CRC.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\MyString.obj \
+ $O\StringConvert.obj \
+ $O\TextConfig.obj \
+ $O\UTFConvert.obj \
+ $O\MyVector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\ErrorMsg.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\PropVariant.obj \
+ $O\ResourceString.obj \
+ $O\Synchronization.obj \
+ $O\System.obj \
+ $O\Window.obj \
+
+WIN_CTRL_OBJS = \
+ $O\Dialog.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\CreateCoder.obj \
+ $O\CWrappers.obj \
+ $O\FileStreams.obj \
+ $O\InBuffer.obj \
+ $O\FilterCoder.obj \
+ $O\LimitedStreams.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\PropId.obj \
+ $O\StreamBinder.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+ $O\VirtThread.obj \
+
+UI_COMMON_OBJS = \
+ $O\ArchiveOpenCallback.obj \
+ $O\DefaultName.obj \
+ $O\LoadCodecs.obj \
+ $O\OpenArchive.obj \
+
+EXPLORER_OBJS = \
+ $O\MyMessages.obj \
+
+FM_OBJS = \
+ $O\FormatUtils.obj \
+ $O\ProgressDialog.obj \
+
+AR_COMMON_OBJS = \
+ $O\CoderMixer2.obj \
+ $O\ItemNameUtils.obj \
+ $O\OutStreamWithCRC.obj \
+
+7Z_OBJS = \
+ $O\7zDecode.obj \
+ $O\7zExtract.obj \
+ $O\7zHandler.obj \
+ $O\7zIn.obj \
+ $O\7zRegister.obj \
+
+COMPRESS_OBJS = \
+ $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 \
+ $O\LzmaRegister.obj \
+
+C_OBJS = \
+ $O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bra.obj \
+ $O\Bra86.obj \
+ $O\BraIA64.obj \
+ $O\CpuArch.obj \
+ $O\Delta.obj \
+ $O\DllSecur.obj \
+ $O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
+ $O\LzmaDec.obj \
+ $O\MtDec.obj \
+ $O\Threads.obj \
+
+!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.h
new file mode 100644
index 0000000000..975d7791d0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.h
@@ -0,0 +1,8 @@
+#define IDI_ICON 1
+
+#define IDS_EXTRACTION_ERROR_TITLE 7
+#define IDS_EXTRACTION_ERROR_MESSAGE 8
+#define IDS_CANNOT_CREATE_FOLDER 3003
+#define IDS_PROGRESS_EXTRACTING 3300
+#define IDS_MIN_OS_TITLE 70
+#define IDS_MIN_OS_TEXT 71
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.rc b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.rc
new file mode 100644
index 0000000000..9fda0d0d16
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.rc
@@ -0,0 +1,18 @@
+#include "../../MyVersionInfo.rc"
+#include "resource.h"
+
+MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx")
+
+IDI_ICON ICON "setup.ico"
+
+STRINGTABLE
+BEGIN
+ IDS_EXTRACTION_ERROR_TITLE "Extraction Failed"
+ IDS_EXTRACTION_ERROR_MESSAGE "File is corrupt"
+ IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'"
+ IDS_PROGRESS_EXTRACTING "Extracting"
+ IDS_MIN_OS_TITLE "Setup Error"
+ IDS_MIN_OS_TEXT "Microsoft Windows 7 or newer is required."
+END
+
+#include "../../UI/FileManager/ProgressDialog.rc"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/setup.ico b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/setup.ico
new file mode 100644
index 0000000000..bb455be1e7
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/setup.ico
Binary files differ
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/7z.ico b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/7z.ico
new file mode 100644
index 0000000000..47ffb781e0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/7z.ico
Binary files differ
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
new file mode 100644
index 0000000000..83ec931153
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
@@ -0,0 +1,988 @@
+# Microsoft Developer Studio Project File - Name="SFXWin" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=SFXWin - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "SFXWin.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "SFXWin.mak" CFG="SFXWin - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SFXWin - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "SFXWin - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "SFXWin - Win32 ReleaseD" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "SFXWin - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "SFXWin - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zsfx.exe" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "SFXWin - Win32 ReleaseD"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "SFXWin___Win32_ReleaseD"
+# PROP BASE Intermediate_Dir "SFXWin___Win32_ReleaseD"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "SFXWin___Win32_ReleaseD"
+# PROP Intermediate_Dir "SFXWin___Win32_ReleaseD"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_SFX" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zD.sfx" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "SFXWin - Win32 Release"
+# Name "SFXWin - Win32 Debug"
+# Name "SFXWin - Win32 ReleaseD"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "7z"
+
+# PROP Default_Filter ""
+# 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\7zExtract.cpp
+# 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\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\7zRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\SplitHandler.cpp
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# 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\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
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Coder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Bcj2Register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\BcjRegister.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\Compress\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\Compress\Lzma2Register.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LzmaRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\PpmdDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\PpmdRegister.cpp
+# End Source File
+# End Group
+# Begin Group "Crypto"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\7zAesRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\MyAes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\MyAes.h
+# End Source File
+# End Group
+# Begin Group "Dialogs"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\BrowseDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\BrowseDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\ComboDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\ComboDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\OverwriteDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\OverwriteDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\PasswordDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\PasswordDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\ProgressDialog2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\ProgressDialog2.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# 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
+
+SOURCE=..\..\Common\FilePathAutoRename.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+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\InBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LimitedStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LimitedStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\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
+
+SOURCE=..\..\Common\OutBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\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
+
+SOURCE=..\..\Common\StreamObjects.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.h
+# End Source File
+# End Group
+# Begin Group "File Manager"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\ExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\ExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\FileManager\FormatUtils.cpp
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\UI\FileManager\SysIconUtils.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Group "Control"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ComboBox.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ComboBox.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Dialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\Dialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ListView.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Control\ListView.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\Windows\CommonDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\CommonDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ErrorMsg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\ErrorMsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConv.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConv.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\Shell.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Shell.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Window.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Window.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "UI"
+
+# PROP Default_Filter ""
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Extract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Extract.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractingFilePath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.h
+# End Source File
+# End Group
+# Begin Group "GUI"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\GUI\ExtractDialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\GUI\ExtractDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\GUI\ExtractGUI.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\GUI\ExtractGUI.h
+# End Source File
+# End Group
+# Begin Group "Explorer"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Explorer\MyMessages.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Explorer\MyMessages.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "C"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrcOpt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Aes.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Aes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\AesOpt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+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
+
+SOURCE=..\..\..\..\C\Bra86.c
+# SUBTRACT CPP /YX /Yc /Yu
+# 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\DllSecur.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\DllSecur.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2Dec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2Dec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Lzma2DecMt.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\MtDec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\MtDec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Ppmd7.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Ppmd7.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Ppmd7Dec.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sha256.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\7z.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\7z1.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\SfxWin.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsw b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsw
new file mode 100644
index 0000000000..66958036b5
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "SFXWin"=.\SFXWin.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
new file mode 100644
index 0000000000..5eade1abd1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
@@ -0,0 +1,241 @@
+// Main.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyWindows.h"
+
+#include <Shlwapi.h>
+
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/NtCheck.h"
+#include "../../../Windows/ResourceString.h"
+
+#include "../../ICoder.h"
+#include "../../IPassword.h"
+#include "../../Archive/IArchive.h"
+#include "../../UI/Common/Extract.h"
+#include "../../UI/Common/ExitCode.h"
+#include "../../UI/Explorer/MyMessages.h"
+#include "../../UI/FileManager/MyWindowsNew.h"
+#include "../../UI/GUI/ExtractGUI.h"
+#include "../../UI/GUI/ExtractRes.h"
+
+#include "../../../../C/DllSecur.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+HINSTANCE g_hInstance;
+
+#ifndef UNDER_CE
+
+DWORD g_ComCtl32Version;
+
+static DWORD GetDllVersion(LPCTSTR dllName)
+{
+ DWORD dwVersion = 0;
+ HINSTANCE hinstDll = LoadLibrary(dllName);
+ if (hinstDll)
+ {
+ DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");
+ if (pDllGetVersion)
+ {
+ DLLVERSIONINFO dvi;
+ ZeroMemory(&dvi, sizeof(dvi));
+ dvi.cbSize = sizeof(dvi);
+ HRESULT hr = (*pDllGetVersion)(&dvi);
+ if (SUCCEEDED(hr))
+ dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
+ }
+ FreeLibrary(hinstDll);
+ }
+ return dwVersion;
+}
+
+#endif
+
+bool g_LVN_ITEMACTIVATE_Support = true;
+
+static const wchar_t * const kUnknownExceptionMessage = L"ERROR: Unknown Error!";
+
+void ErrorMessageForHRESULT(HRESULT res)
+{
+ ShowErrorMessage(HResultToMessage(res));
+}
+
+int APIENTRY WinMain2()
+{
+ // OleInitialize is required for ProgressBar in TaskBar.
+ #ifndef UNDER_CE
+ OleInitialize(NULL);
+ #endif
+
+ #ifndef UNDER_CE
+ g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));
+ g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));
+ #endif
+
+ UString password;
+ bool assumeYes = false;
+ bool outputFolderDefined = false;
+ FString outputFolder;
+ UStringVector commandStrings;
+ NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
+
+ #ifndef UNDER_CE
+ if (commandStrings.Size() > 0)
+ commandStrings.Delete(0);
+ #endif
+
+ FOR_VECTOR (i, commandStrings)
+ {
+ const UString &s = commandStrings[i];
+ if (s.Len() > 1 && s[0] == '-')
+ {
+ wchar_t c = MyCharLower_Ascii(s[1]);
+ if (c == 'y')
+ {
+ assumeYes = true;
+ if (s.Len() != 2)
+ {
+ ShowErrorMessage(L"Bad command");
+ return 1;
+ }
+ }
+ else if (c == 'o')
+ {
+ outputFolder = us2fs(s.Ptr(2));
+ NName::NormalizeDirPathPrefix(outputFolder);
+ outputFolderDefined = !outputFolder.IsEmpty();
+ }
+ else if (c == 'p')
+ {
+ password = s.Ptr(2);
+ }
+ }
+ }
+
+ FString path;
+ NDLL::MyGetModuleFileName(path);
+
+ FString fullPath;
+ if (!MyGetFullPathName(path, fullPath))
+ {
+ ShowErrorMessage(L"Error 1329484");
+ return 1;
+ }
+
+ CCodecs *codecs = new CCodecs;
+ CMyComPtr<IUnknown> compressCodecsInfo = codecs;
+ HRESULT result = codecs->Load();
+ if (result != S_OK)
+ {
+ ErrorMessageForHRESULT(result);
+ return 1;
+ }
+
+ // COpenCallbackGUI openCallback;
+
+ // openCallback.PasswordIsDefined = !password.IsEmpty();
+ // openCallback.Password = password;
+
+ CExtractCallbackImp *ecs = new CExtractCallbackImp;
+ CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
+ ecs->Init();
+
+ #ifndef _NO_CRYPTO
+ ecs->PasswordIsDefined = !password.IsEmpty();
+ ecs->Password = password;
+ #endif
+
+ CExtractOptions eo;
+
+ FString dirPrefix;
+ if (!GetOnlyDirPrefix(path, dirPrefix))
+ {
+ ShowErrorMessage(L"Error 1329485");
+ return 1;
+ }
+
+ eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix;
+ eo.YesToAll = assumeYes;
+ eo.OverwriteMode = assumeYes ?
+ NExtract::NOverwriteMode::kOverwrite :
+ NExtract::NOverwriteMode::kAsk;
+ eo.PathMode = NExtract::NPathMode::kFullPaths;
+ eo.TestMode = false;
+
+ UStringVector v1, v2;
+ v1.Add(fs2us(fullPath));
+ v2.Add(fs2us(fullPath));
+ NWildcard::CCensorNode wildcardCensor;
+ wildcardCensor.AddItem(true, L"*", true, true, true, true);
+
+ bool messageWasDisplayed = false;
+ result = ExtractGUI(codecs,
+ CObjectVector<COpenType>(), CIntVector(),
+ v1, v2,
+ wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs);
+
+ if (result == S_OK)
+ {
+ if (!ecs->IsOK())
+ return NExitCode::kFatalError;
+ return 0;
+ }
+ if (result == E_ABORT)
+ return NExitCode::kUserBreak;
+ if (!messageWasDisplayed)
+ {
+ if (result == S_FALSE)
+ ShowErrorMessage(L"Error in archive");
+ else
+ ErrorMessageForHRESULT(result);
+ }
+ if (result == E_OUTOFMEMORY)
+ return NExitCode::kMemoryError;
+ return NExitCode::kFatalError;
+}
+
+#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError;
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
+ #ifdef UNDER_CE
+ LPWSTR
+ #else
+ LPSTR
+ #endif
+ /* lpCmdLine */, int /* nCmdShow */)
+{
+ g_hInstance = (HINSTANCE)hInstance;
+
+ NT_CHECK
+
+ try
+ {
+ #ifdef _WIN32
+ LoadSecurityDlls();
+ #endif
+
+ return WinMain2();
+ }
+ catch(const CNewException &)
+ {
+ ErrorMessageForHRESULT(E_OUTOFMEMORY);
+ return NExitCode::kMemoryError;
+ }
+ catch(...)
+ {
+ ShowErrorMessage(kUnknownExceptionMessage);
+ return NExitCode::kFatalError;
+ }
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.h
new file mode 100644
index 0000000000..f263ecb77c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.h
@@ -0,0 +1,14 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#include <commctrl.h>
+#include <ShlObj.h>
+
+// #define printf(x) NO_PRINTF_(x)
+// #define sprintf(x) NO_SPRINTF_(x)
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/makefile b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/makefile
new file mode 100644
index 0000000000..21a67dd4d8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/makefile
@@ -0,0 +1,153 @@
+PROG = 7z.sfx
+MY_FIXED = 1
+
+CFLAGS = $(CFLAGS) \
+ -DNO_REGISTRY \
+ -DEXTRACT_ONLY \
+ -DNO_READ_FROM_CODER \
+ -D_SFX \
+
+!IFDEF UNDER_CE
+LIBS = $(LIBS) ceshell.lib Commctrl.lib
+!ELSE
+LIBS = $(LIBS) comctl32.lib comdlg32.lib
+!ENDIF
+
+CURRENT_OBJS = \
+ $O\SfxWin.obj \
+
+GUI_OBJS = \
+ $O\ExtractDialog.obj \
+ $O\ExtractGUI.obj \
+
+COMMON_OBJS = \
+ $O\CRC.obj \
+ $O\CommandLineParser.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\MyString.obj \
+ $O\StringConvert.obj \
+ $O\MyVector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\CommonDialog.obj \
+ $O\DLL.obj \
+ $O\ErrorMsg.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConv.obj \
+ $O\ResourceString.obj \
+ $O\Shell.obj \
+ $O\Synchronization.obj \
+ $O\System.obj \
+ $O\Window.obj \
+
+WIN_CTRL_OBJS = \
+ $O\ComboBox.obj \
+ $O\Dialog.obj \
+ $O\ListView.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\CreateCoder.obj \
+ $O\CWrappers.obj \
+ $O\FilePathAutoRename.obj \
+ $O\FileStreams.obj \
+ $O\InBuffer.obj \
+ $O\FilterCoder.obj \
+ $O\LimitedStreams.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\PropId.obj \
+ $O\StreamBinder.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+ $O\VirtThread.obj \
+
+UI_COMMON_OBJS = \
+ $O\ArchiveExtractCallback.obj \
+ $O\ArchiveOpenCallback.obj \
+ $O\DefaultName.obj \
+ $O\Extract.obj \
+ $O\ExtractingFilePath.obj \
+ $O\LoadCodecs.obj \
+ $O\OpenArchive.obj \
+
+EXPLORER_OBJS = \
+ $O\MyMessages.obj \
+
+FM_OBJS = \
+ $O\BrowseDialog.obj \
+ $O\ComboDialog.obj \
+ $O\ExtractCallback.obj \
+ $O\FormatUtils.obj \
+ $O\OverwriteDialog.obj \
+ $O\PasswordDialog.obj \
+ $O\ProgressDialog2.obj \
+ $O\PropertyName.obj \
+ $O\SysIconUtils.obj \
+
+AR_OBJS = \
+ $O\SplitHandler.obj \
+
+AR_COMMON_OBJS = \
+ $O\CoderMixer2.obj \
+ $O\ItemNameUtils.obj \
+ $O\MultiStream.obj \
+ $O\OutStreamWithCRC.obj \
+
+7Z_OBJS = \
+ $O\7zDecode.obj \
+ $O\7zExtract.obj \
+ $O\7zHandler.obj \
+ $O\7zIn.obj \
+ $O\7zRegister.obj \
+
+COMPRESS_OBJS = \
+ $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 \
+ $O\LzmaRegister.obj \
+ $O\PpmdDecoder.obj \
+ $O\PpmdRegister.obj \
+
+CRYPTO_OBJS = \
+ $O\7zAes.obj \
+ $O\7zAesRegister.obj \
+ $O\MyAes.obj \
+
+C_OBJS = \
+ $O\Alloc.obj \
+ $O\Bcj2.obj \
+ $O\Bra.obj \
+ $O\Bra86.obj \
+ $O\BraIA64.obj \
+ $O\CpuArch.obj \
+ $O\Delta.obj \
+ $O\DllSecur.obj \
+ $O\Lzma2Dec.obj \
+ $O\Lzma2DecMt.obj \
+ $O\LzmaDec.obj \
+ $O\MtDec.obj \
+ $O\Ppmd7.obj \
+ $O\Ppmd7Dec.obj \
+ $O\Sha256.obj \
+ $O\Threads.obj \
+
+!include "../../Aes.mak"
+!include "../../Crc.mak"
+!include "../../LzmaDec.mak"
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.h b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.h
new file mode 100644
index 0000000000..d9fae1ba6e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.h
@@ -0,0 +1 @@
+#define IDI_ICON 1
diff --git a/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.rc b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.rc
new file mode 100644
index 0000000000..3b69b357e3
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.rc
@@ -0,0 +1,50 @@
+#include "../../MyVersionInfo.rc"
+#include "../../GuiCommon.rc"
+#include "../../UI/GUI/ExtractDialogRes.h"
+#include "../../UI/FileManager/PropertyNameRes.h"
+
+#include "resource.h"
+
+MY_VERSION_INFO_APP("7z SFX", "7z.sfx")
+
+#define xc 240
+#define yc 64
+
+IDI_ICON ICON "7z.ico"
+
+IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+CAPTION "7-Zip self-extracting archive"
+BEGIN
+ LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8
+ EDITTEXT IDC_EXTRACT_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL
+ PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, 20, bxsDots, bys, WS_GROUP
+ DEFPUSHBUTTON "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
+END
+
+#ifdef UNDER_CE
+
+#undef xc
+#define xc 144
+
+IDD_EXTRACT_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+CAPTION "7-Zip self-extracting archive"
+BEGIN
+ LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 12, 8
+ EDITTEXT IDC_EXTRACT_PATH, m, m + bys + 4, xc, 14, ES_AUTOHSCROLL
+ PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m, bxsDots, bys, WS_GROUP
+ DEFPUSHBUTTON "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
+END
+
+#endif
+
+#include "../../UI/FileManager/OverwriteDialog.rc"
+#include "../../UI/FileManager/PasswordDialog.rc"
+#include "../../UI/FileManager/ProgressDialog2.rc"
+#include "../../UI/GUI/Extract.rc"
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_PROP_MTIME "Modified"
+END
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.cpp
new file mode 100644
index 0000000000..e726dadc25
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.cpp
@@ -0,0 +1,250 @@
+// CWrappers.h
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "CWrappers.h"
+
+#include "StreamUtils.h"
+
+SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw()
+{
+ switch (res)
+ {
+ case S_OK: return SZ_OK;
+ case E_OUTOFMEMORY: return SZ_ERROR_MEM;
+ case E_INVALIDARG: return SZ_ERROR_PARAM;
+ case E_ABORT: return SZ_ERROR_PROGRESS;
+ case S_FALSE: return SZ_ERROR_DATA;
+ case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED;
+ }
+ return defaultRes;
+}
+
+
+HRESULT SResToHRESULT(SRes res) throw()
+{
+ switch (res)
+ {
+ case SZ_OK: return S_OK;
+
+ case SZ_ERROR_DATA:
+ case SZ_ERROR_CRC:
+ case SZ_ERROR_INPUT_EOF:
+ return S_FALSE;
+
+ case SZ_ERROR_MEM: return E_OUTOFMEMORY;
+ case SZ_ERROR_PARAM: return E_INVALIDARG;
+ case SZ_ERROR_PROGRESS: return E_ABORT;
+ case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
+ // case SZ_ERROR_OUTPUT_EOF:
+ // case SZ_ERROR_READ:
+ // case SZ_ERROR_WRITE:
+ // case SZ_ERROR_THREAD:
+ // case SZ_ERROR_ARCHIVE:
+ // case SZ_ERROR_NO_ARCHIVE:
+ // return E_FAIL;
+ }
+ if (res < 0)
+ return res;
+ return E_FAIL;
+}
+
+
+#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1)
+
+#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)
+
+
+static SRes CompressProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) throw()
+{
+ CCompressProgressWrap *p = CONTAINER_FROM_VTBL(pp, CCompressProgressWrap, vt);
+ p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));
+ return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
+}
+
+void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw()
+{
+ vt.Progress = CompressProgress;
+ Progress = progress;
+ Res = SZ_OK;
+}
+
+static const UInt32 kStreamStepSize = (UInt32)1 << 31;
+
+static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw()
+{
+ CSeqInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqInStreamWrap, vt);
+ UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);
+ p->Res = (p->Stream->Read(data, curSize, &curSize));
+ *size = curSize;
+ p->Processed += curSize;
+ if (p->Res == S_OK)
+ return SZ_OK;
+ return HRESULT_To_SRes(p->Res, SZ_ERROR_READ);
+}
+
+static size_t MyWrite(const ISeqOutStream *pp, const void *data, size_t size) throw()
+{
+ CSeqOutStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqOutStreamWrap, vt);
+ if (p->Stream)
+ {
+ p->Res = WriteStream(p->Stream, data, size);
+ if (p->Res != 0)
+ return 0;
+ }
+ else
+ p->Res = S_OK;
+ p->Processed += size;
+ return size;
+}
+
+
+void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw()
+{
+ vt.Read = MyRead;
+ Stream = stream;
+ Processed = 0;
+ Res = S_OK;
+}
+
+void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw()
+{
+ vt.Write = MyWrite;
+ Stream = stream;
+ Res = SZ_OK;
+ Processed = 0;
+}
+
+
+static SRes InStreamWrap_Read(const ISeekInStream *pp, void *data, size_t *size) throw()
+{
+ CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
+ UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);
+ p->Res = p->Stream->Read(data, curSize, &curSize);
+ *size = curSize;
+ return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;
+}
+
+static SRes InStreamWrap_Seek(const ISeekInStream *pp, Int64 *offset, ESzSeek origin) throw()
+{
+ CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt);
+ UInt32 moveMethod;
+ switch (origin)
+ {
+ case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break;
+ case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break;
+ case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break;
+ default: return SZ_ERROR_PARAM;
+ }
+ UInt64 newPosition;
+ p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition);
+ *offset = (Int64)newPosition;
+ return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;
+}
+
+void CSeekInStreamWrap::Init(IInStream *stream) throw()
+{
+ Stream = stream;
+ vt.Read = InStreamWrap_Read;
+ vt.Seek = InStreamWrap_Seek;
+ Res = S_OK;
+}
+
+
+/* ---------- CByteInBufWrap ---------- */
+
+void CByteInBufWrap::Free() throw()
+{
+ ::MidFree(Buf);
+ Buf = 0;
+}
+
+bool CByteInBufWrap::Alloc(UInt32 size) throw()
+{
+ if (Buf == 0 || size != Size)
+ {
+ Free();
+ Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size);
+ Size = size;
+ }
+ return (Buf != 0);
+}
+
+Byte CByteInBufWrap::ReadByteFromNewBlock() throw()
+{
+ if (Res == S_OK)
+ {
+ UInt32 avail;
+ Processed += (Cur - Buf);
+ Res = Stream->Read(Buf, Size, &avail);
+ Cur = Buf;
+ Lim = Buf + avail;
+ if (avail != 0)
+ return *Cur++;
+ }
+ Extra = true;
+ return 0;
+}
+
+static Byte Wrap_ReadByte(const IByteIn *pp) throw()
+{
+ CByteInBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt);
+ if (p->Cur != p->Lim)
+ return *p->Cur++;
+ return p->ReadByteFromNewBlock();
+}
+
+CByteInBufWrap::CByteInBufWrap(): Buf(0)
+{
+ vt.Read = Wrap_ReadByte;
+}
+
+
+/* ---------- CByteOutBufWrap ---------- */
+
+void CByteOutBufWrap::Free() throw()
+{
+ ::MidFree(Buf);
+ Buf = 0;
+}
+
+bool CByteOutBufWrap::Alloc(size_t size) throw()
+{
+ if (Buf == 0 || size != Size)
+ {
+ Free();
+ Buf = (Byte *)::MidAlloc(size);
+ Size = size;
+ }
+ return (Buf != 0);
+}
+
+HRESULT CByteOutBufWrap::Flush() throw()
+{
+ if (Res == S_OK)
+ {
+ size_t size = (Cur - Buf);
+ Res = WriteStream(Stream, Buf, size);
+ if (Res == S_OK)
+ Processed += size;
+ Cur = Buf;
+ }
+ return Res;
+}
+
+static void Wrap_WriteByte(const IByteOut *pp, Byte b) throw()
+{
+ CByteOutBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt);
+ Byte *dest = p->Cur;
+ *dest = b;
+ p->Cur = ++dest;
+ if (dest == p->Lim)
+ p->Flush();
+}
+
+CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0)
+{
+ vt.Write = Wrap_WriteByte;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.h b/other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.h
new file mode 100644
index 0000000000..f93c98adc7
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.h
@@ -0,0 +1,120 @@
+// CWrappers.h
+
+#ifndef __C_WRAPPERS_H
+#define __C_WRAPPERS_H
+
+#include "../ICoder.h"
+#include "../../Common/MyCom.h"
+
+SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw();
+HRESULT SResToHRESULT(SRes res) throw();
+
+struct CCompressProgressWrap
+{
+ ICompressProgress vt;
+ ICompressProgressInfo *Progress;
+ HRESULT Res;
+
+ void Init(ICompressProgressInfo *progress) throw();
+};
+
+
+struct CSeqInStreamWrap
+{
+ ISeqInStream vt;
+ ISequentialInStream *Stream;
+ HRESULT Res;
+ UInt64 Processed;
+
+ void Init(ISequentialInStream *stream) throw();
+};
+
+
+struct CSeekInStreamWrap
+{
+ ISeekInStream vt;
+ IInStream *Stream;
+ HRESULT Res;
+
+ void Init(IInStream *stream) throw();
+};
+
+
+struct CSeqOutStreamWrap
+{
+ ISeqOutStream vt;
+ ISequentialOutStream *Stream;
+ HRESULT Res;
+ UInt64 Processed;
+
+ void Init(ISequentialOutStream *stream) throw();
+};
+
+
+struct CByteInBufWrap
+{
+ IByteIn vt;
+ const Byte *Cur;
+ const Byte *Lim;
+ Byte *Buf;
+ UInt32 Size;
+ ISequentialInStream *Stream;
+ UInt64 Processed;
+ bool Extra;
+ HRESULT Res;
+
+ CByteInBufWrap();
+ ~CByteInBufWrap() { Free(); }
+ void Free() throw();
+ bool Alloc(UInt32 size) throw();
+ void Init()
+ {
+ Lim = Cur = Buf;
+ Processed = 0;
+ Extra = false;
+ Res = S_OK;
+ }
+ UInt64 GetProcessed() const { return Processed + (Cur - Buf); }
+ Byte ReadByteFromNewBlock() throw();
+ Byte ReadByte()
+ {
+ if (Cur != Lim)
+ return *Cur++;
+ return ReadByteFromNewBlock();
+ }
+};
+
+
+struct CByteOutBufWrap
+{
+ IByteOut vt;
+ Byte *Cur;
+ const Byte *Lim;
+ Byte *Buf;
+ size_t Size;
+ ISequentialOutStream *Stream;
+ UInt64 Processed;
+ HRESULT Res;
+
+ CByteOutBufWrap() throw();
+ ~CByteOutBufWrap() { Free(); }
+ void Free() throw();
+ bool Alloc(size_t size) throw();
+ void Init()
+ {
+ Cur = Buf;
+ Lim = Buf + Size;
+ Processed = 0;
+ Res = S_OK;
+ }
+ UInt64 GetProcessed() const { return Processed + (Cur - Buf); }
+ HRESULT Flush() throw();
+ void WriteByte(Byte b)
+ {
+ *Cur++ = b;
+ if (Cur == Lim)
+ Flush();
+ }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.cpp
new file mode 100644
index 0000000000..5040765731
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.cpp
@@ -0,0 +1,536 @@
+// CreateCoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../Windows/Defs.h"
+#include "../../Windows/PropVariant.h"
+
+#include "CreateCoder.h"
+
+#include "FilterCoder.h"
+#include "RegisterCodec.h"
+
+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 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;
+ RINOK(codecsInfo->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_EMPTY)
+ res = 1;
+ else if (prop.vt == VT_UI4)
+ res = prop.ulVal;
+ else
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
+{
+ NWindows::NCOM::CPropVariant prop;
+ RINOK(codecsInfo->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_EMPTY)
+ res = true;
+ else if (prop.vt == VT_BOOL)
+ res = VARIANT_BOOLToBool(prop.boolVal);
+ else
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+HRESULT CExternalCodecs::Load()
+{
+ Codecs.Clear();
+ Hashers.Clear();
+
+ if (GetCodecs)
+ {
+ CCodecInfoEx info;
+
+ UString s;
+ UInt32 num;
+ RINOK(GetCodecs->GetNumMethods(&num));
+
+ for (UInt32 i = 0; i < num; i++)
+ {
+ NWindows::NCOM::CPropVariant prop;
+
+ RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop));
+ 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.SetFromWStr_if_Ascii(prop.bstrVal);
+ else if (prop.vt != VT_EMPTY)
+ continue;
+
+ 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++)
+ {
+ 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.SetFromWStr_if_Ascii(prop.bstrVal);
+ else if (prop.vt != VT_EMPTY)
+ continue;
+
+ Hashers.Add(info);
+ }
+ }
+
+ return S_OK;
+}
+
+#endif
+
+
+int FindMethod_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const AString &name,
+ bool encode,
+ CMethodId &methodId,
+ UInt32 &numStreams)
+{
+ unsigned i;
+ for (i = 0; i < g_NumCodecs; i++)
+ {
+ const CCodecInfo &codec = *g_Codecs[i];
+ if ((encode ? codec.CreateEncoder : codec.CreateDecoder)
+ && StringsAreEqualNoCase_Ascii(name, codec.Name))
+ {
+ methodId = codec.Id;
+ numStreams = codec.NumStreams;
+ return i;
+ }
+ }
+
+ #ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
+ if (__externalCodecs)
+ for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
+ {
+ const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
+ if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)
+ && StringsAreEqualNoCase_Ascii(name, codec.Name))
+ {
+ methodId = codec.Id;
+ numStreams = codec.NumStreams;
+ return g_NumCodecs + i;
+ }
+ }
+
+ #endif
+
+ return -1;
+}
+
+
+static int FindMethod_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode)
+{
+ unsigned i;
+ for (i = 0; i < g_NumCodecs; i++)
+ {
+ const CCodecInfo &codec = *g_Codecs[i];
+ if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder))
+ return i;
+ }
+
+ #ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
+ if (__externalCodecs)
+ for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
+ {
+ const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
+ if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned))
+ return g_NumCodecs + i;
+ }
+
+ #endif
+
+ return -1;
+}
+
+
+bool FindMethod(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ AString &name)
+{
+ name.Empty();
+
+ unsigned i;
+ for (i = 0; i < g_NumCodecs; i++)
+ {
+ const CCodecInfo &codec = *g_Codecs[i];
+ if (methodId == codec.Id)
+ {
+ name = codec.Name;
+ return true;
+ }
+ }
+
+ #ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
+ if (__externalCodecs)
+ for (i = 0; i < __externalCodecs->Codecs.Size(); i++)
+ {
+ const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
+ if (methodId == codec.Id)
+ {
+ name = codec.Name;
+ return true;
+ }
+ }
+
+ #endif
+
+ return false;
+}
+
+bool FindHashMethod(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const AString &name,
+ CMethodId &methodId)
+{
+ unsigned i;
+ for (i = 0; i < g_NumHashers; i++)
+ {
+ const CHasherInfo &codec = *g_Hashers[i];
+ if (StringsAreEqualNoCase_Ascii(name, codec.Name))
+ {
+ methodId = codec.Id;
+ return true;
+ }
+ }
+
+ #ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
+ if (__externalCodecs)
+ for (i = 0; i < __externalCodecs->Hashers.Size(); i++)
+ {
+ const CHasherInfoEx &codec = __externalCodecs->Hashers[i];
+ if (StringsAreEqualNoCase_Ascii(name, codec.Name))
+ {
+ methodId = codec.Id;
+ return true;
+ }
+ }
+
+ #endif
+
+ return false;
+}
+
+void GetHashMethods(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CRecordVector<CMethodId> &methods)
+{
+ methods.ClearAndSetSize(g_NumHashers);
+ 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 < __externalCodecs->Hashers.Size(); i++)
+ methods.Add(__externalCodecs->Hashers[i].Id);
+
+ #endif
+}
+
+
+
+HRESULT CreateCoder_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ unsigned i, bool encode,
+ CMyComPtr<ICompressFilter> &filter,
+ CCreatedCoder &cod)
+{
+ cod.IsExternal = false;
+ cod.IsFilter = false;
+ cod.NumStreams = 1;
+
+ if (i < g_NumCodecs)
+ {
+ const CCodecInfo &codec = *g_Codecs[i];
+ // if (codec.Id == methodId)
+ {
+ if (encode)
+ {
+ if (codec.CreateEncoder)
+ {
+ void *p = codec.CreateEncoder();
+ if (codec.IsFilter) filter = (ICompressFilter *)p;
+ else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
+ else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
+ return S_OK;
+ }
+ }
+ else
+ if (codec.CreateDecoder)
+ {
+ void *p = codec.CreateDecoder();
+ if (codec.IsFilter) filter = (ICompressFilter *)p;
+ else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
+ else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
+ return S_OK;
+ }
+ }
+ }
+
+ #ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
+ if (__externalCodecs)
+ {
+ i -= g_NumCodecs;
+ cod.IsExternal = true;
+ if (i < __externalCodecs->Codecs.Size())
+ {
+ const CCodecInfoEx &codec = __externalCodecs->Codecs[i];
+ // if (codec.Id == methodId)
+ {
+ if (encode)
+ {
+ if (codec.EncoderIsAssigned)
+ {
+ if (codec.NumStreams == 1)
+ {
+ 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);
+ }
+ cod.NumStreams = codec.NumStreams;
+ return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
+ }
+ }
+ else
+ if (codec.DecoderIsAssigned)
+ {
+ if (codec.NumStreams == 1)
+ {
+ 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);
+ }
+ cod.NumStreams = codec.NumStreams;
+ return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
+ }
+ }
+ }
+ }
+ #endif
+
+ return S_OK;
+}
+
+
+HRESULT CreateCoder_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ unsigned index, bool encode,
+ CCreatedCoder &cod)
+{
+ CMyComPtr<ICompressFilter> filter;
+ HRESULT res = CreateCoder_Index(
+ EXTERNAL_CODECS_LOC_VARS
+ index, encode,
+ filter, cod);
+
+ if (filter)
+ {
+ cod.IsFilter = true;
+ CFilterCoder *coderSpec = new CFilterCoder(encode);
+ cod.Coder = coderSpec;
+ coderSpec->Filter = filter;
+ }
+
+ return res;
+}
+
+
+HRESULT CreateCoder_Id(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter,
+ CCreatedCoder &cod)
+{
+ int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);
+ if (index < 0)
+ return S_OK;
+ return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS index, encode, filter, cod);
+}
+
+
+HRESULT CreateCoder_Id(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CCreatedCoder &cod)
+{
+ CMyComPtr<ICompressFilter> filter;
+ HRESULT res = CreateCoder_Id(
+ 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_Id(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressCoder> &coder)
+{
+ CCreatedCoder cod;
+ HRESULT res = CreateCoder_Id(
+ EXTERNAL_CODECS_LOC_VARS
+ methodId, encode,
+ cod);
+ coder = cod.Coder;
+ return res;
+}
+
+HRESULT CreateFilter(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter)
+{
+ CCreatedCoder cod;
+ return CreateCoder_Id(
+ EXTERNAL_CODECS_LOC_VARS
+ methodId, encode,
+ filter, cod);
+}
+
+
+HRESULT CreateHasher(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ AString &name,
+ CMyComPtr<IHasher> &hasher)
+{
+ name.Empty();
+
+ unsigned i;
+ for (i = 0; i < g_NumHashers; i++)
+ {
+ const CHasherInfo &codec = *g_Hashers[i];
+ if (codec.Id == methodId)
+ {
+ hasher = codec.CreateHasher();
+ name = codec.Name;
+ break;
+ }
+ }
+
+ #ifdef EXTERNAL_CODECS
+
+ CHECK_GLOBAL_CODECS
+
+ if (!hasher && __externalCodecs)
+ 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((UInt32)i, &hasher);
+ }
+ }
+
+ #endif
+
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.h b/other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.h
new file mode 100644
index 0000000000..2105818fbf
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.h
@@ -0,0 +1,192 @@
+// CreateCoder.h
+
+#ifndef __CREATE_CODER_H
+#define __CREATE_CODER_H
+
+#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
+{
+ CMethodId Id;
+ AString Name;
+ UInt32 NumStreams;
+ bool EncoderIsAssigned;
+ bool DecoderIsAssigned;
+
+ CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}
+};
+
+struct CHasherInfoEx
+{
+ CMethodId Id;
+ AString Name;
+};
+
+#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,
+#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)
+#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);
+#define IMPL_ISetCompressCodecsInfo2(x) \
+STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \
+ COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.Load(); COM_TRY_END }
+#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)
+
+struct CExternalCodecs
+{
+ CMyComPtr<ICompressCodecsInfo> GetCodecs;
+ CMyComPtr<IHashers> GetHashers;
+
+ CObjectVector<CCodecInfoEx> Codecs;
+ CObjectVector<CHasherInfoEx> Hashers;
+
+ 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();
+ }
+};
+
+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_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
+
+#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,
+#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,
+
+#else
+
+#define PUBLIC_ISetCompressCodecsInfo
+#define QUERY_ENTRY_ISetCompressCodecsInfo
+#define DECL_ISetCompressCodecsInfo
+#define IMPL_ISetCompressCodecsInfo
+#define EXTERNAL_CODECS_VARS2
+#define DECL_EXTERNAL_CODECS_VARS
+#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
+#define EXTERNAL_CODECS_LOC_VARS
+
+#endif
+
+int FindMethod_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const AString &name,
+ bool encode,
+ CMethodId &methodId,
+ UInt32 &numStreams);
+
+bool FindMethod(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ AString &name);
+
+bool FindHashMethod(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const AString &name,
+ CMethodId &methodId);
+
+void GetHashMethods(
+ 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_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ unsigned codecIndex, bool encode,
+ CMyComPtr<ICompressFilter> &filter,
+ CCreatedCoder &cod);
+
+HRESULT CreateCoder_Index(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ unsigned index, bool encode,
+ CCreatedCoder &cod);
+
+HRESULT CreateCoder_Id(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter,
+ CCreatedCoder &cod);
+
+HRESULT CreateCoder_Id(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CCreatedCoder &cod);
+
+HRESULT CreateCoder_Id(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressCoder> &coder);
+
+HRESULT CreateFilter(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId, bool encode,
+ CMyComPtr<ICompressFilter> &filter);
+
+HRESULT CreateHasher(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ CMethodId methodId,
+ AString &name,
+ CMyComPtr<IHasher> &hasher);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.cpp
new file mode 100644
index 0000000000..84c9e2bce8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.cpp
@@ -0,0 +1,46 @@
+// FilePathAutoRename.cpp
+
+#include "StdAfx.h"
+
+#include "../../Windows/FileFind.h"
+
+#include "FilePathAutoRename.h"
+
+using namespace NWindows;
+
+static bool MakeAutoName(const FString &name,
+ const FString &extension, UInt32 value, FString &path)
+{
+ path = name;
+ path.Add_UInt32(value);
+ path += extension;
+ return NFile::NFind::DoesFileOrDirExist(path);
+}
+
+bool AutoRenamePath(FString &path)
+{
+ int dotPos = path.ReverseFind_Dot();
+ int slashPos = path.ReverseFind_PathSepar();
+
+ FString name = path;
+ FString extension;
+ if (dotPos > slashPos + 1)
+ {
+ name.DeleteFrom(dotPos);
+ extension = path.Ptr(dotPos);
+ }
+ name += '_';
+
+ FString temp;
+
+ UInt32 left = 1, right = ((UInt32)1 << 30);
+ while (left != right)
+ {
+ UInt32 mid = (left + right) / 2;
+ if (MakeAutoName(name, extension, mid, temp))
+ left = mid + 1;
+ else
+ right = mid;
+ }
+ return !MakeAutoName(name, extension, right, path);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.h b/other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.h
new file mode 100644
index 0000000000..cb2d71b409
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.h
@@ -0,0 +1,10 @@
+// FilePathAutoRename.h
+
+#ifndef __FILE_PATH_AUTO_RENAME_H
+#define __FILE_PATH_AUTO_RENAME_H
+
+#include "../../Common/MyString.h"
+
+bool AutoRenamePath(FString &fullProcessedPath);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.cpp
new file mode 100644
index 0000000000..11c14d219d
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.cpp
@@ -0,0 +1,475 @@
+// FileStreams.cpp
+
+#include "StdAfx.h"
+
+#ifndef _WIN32
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+
+#ifdef SUPPORT_DEVICE_FILE
+#include "../../../C/Alloc.h"
+#include "../../Common/Defs.h"
+#endif
+
+#include "FileStreams.h"
+
+static inline HRESULT ConvertBoolToHRESULT(bool result)
+{
+ #ifdef _WIN32
+ if (result)
+ return S_OK;
+ DWORD lastError = ::GetLastError();
+ if (lastError == 0)
+ return E_FAIL;
+ return HRESULT_FROM_WIN32(lastError);
+ #else
+ return result ? S_OK: E_FAIL;
+ #endif
+}
+
+
+static const UInt32 kClusterSize = 1 << 18;
+CInFileStream::CInFileStream():
+ #ifdef SUPPORT_DEVICE_FILE
+ VirtPos(0),
+ PhyPos(0),
+ Buf(0),
+ BufSize(0),
+ #endif
+ SupportHardLinks(false),
+ Callback(NULL),
+ CallbackRef(0)
+{
+}
+
+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)
+{
+ #ifdef USE_WIN_FILE
+
+ #ifdef SUPPORT_DEVICE_FILE
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ if (File.IsDeviceFile)
+ {
+ if (File.SizeDefined)
+ {
+ if (VirtPos >= File.Size)
+ return VirtPos == File.Size ? S_OK : E_FAIL;
+ UInt64 rem = File.Size - VirtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ for (;;)
+ {
+ const UInt32 mask = kClusterSize - 1;
+ const UInt64 mask2 = ~(UInt64)mask;
+ UInt64 alignedPos = VirtPos & mask2;
+ if (BufSize > 0 && BufStartPos == alignedPos)
+ {
+ UInt32 pos = (UInt32)VirtPos & mask;
+ if (pos >= BufSize)
+ return S_OK;
+ UInt32 rem = MyMin(BufSize - pos, size);
+ memcpy(data, Buf + pos, rem);
+ VirtPos += rem;
+ if (processedSize)
+ *processedSize += rem;
+ return S_OK;
+ }
+
+ bool useBuf = false;
+ if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )
+ useBuf = true;
+ else
+ {
+ UInt64 end = VirtPos + size;
+ if ((end & mask) != 0)
+ {
+ end &= mask2;
+ if (end <= VirtPos)
+ useBuf = true;
+ else
+ size = (UInt32)(end - VirtPos);
+ }
+ }
+ if (!useBuf)
+ break;
+ if (alignedPos != PhyPos)
+ {
+ UInt64 realNewPosition;
+ bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition);
+ if (!result)
+ return ConvertBoolToHRESULT(result);
+ PhyPos = realNewPosition;
+ }
+
+ BufStartPos = alignedPos;
+ UInt32 readSize = kClusterSize;
+ if (File.SizeDefined)
+ readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize);
+
+ if (!Buf)
+ {
+ Buf = (Byte *)MidAlloc(kClusterSize);
+ if (!Buf)
+ return E_OUTOFMEMORY;
+ }
+ bool result = File.Read1(Buf, readSize, BufSize);
+ if (!result)
+ return ConvertBoolToHRESULT(result);
+
+ if (BufSize == 0)
+ return S_OK;
+ PhyPos += BufSize;
+ }
+
+ if (VirtPos != PhyPos)
+ {
+ UInt64 realNewPosition;
+ bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition);
+ if (!result)
+ return ConvertBoolToHRESULT(result);
+ PhyPos = VirtPos = realNewPosition;
+ }
+ }
+ #endif
+
+ UInt32 realProcessedSize;
+ bool result = File.ReadPart(data, size, realProcessedSize);
+ if (processedSize)
+ *processedSize = realProcessedSize;
+
+ #ifdef SUPPORT_DEVICE_FILE
+ VirtPos += realProcessedSize;
+ PhyPos += realProcessedSize;
+ #endif
+
+ 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;
+
+ #endif
+}
+
+#ifdef UNDER_CE
+STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ size_t s2 = fread(data, 1, size, stdin);
+ int error = ferror(stdin);
+ if (processedSize)
+ *processedSize = s2;
+ if (s2 <= size && error == 0)
+ return S_OK;
+ return E_FAIL;
+}
+#else
+STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ #ifdef _WIN32
+
+ DWORD realProcessedSize;
+ UInt32 sizeTemp = (1 << 20);
+ if (sizeTemp > size)
+ sizeTemp = size;
+ BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
+ return S_OK;
+ return ConvertBoolToHRESULT(res != FALSE);
+
+ #else
+
+ if (processedSize)
+ *processedSize = 0;
+ ssize_t res;
+ do
+ {
+ res = read(0, data, (size_t)size);
+ }
+ while (res < 0 && (errno == EINTR));
+ if (res == -1)
+ return E_FAIL;
+ if (processedSize)
+ *processedSize = (UInt32)res;
+ return S_OK;
+
+ #endif
+}
+
+#endif
+
+STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ if (seekOrigin >= 3)
+ return STG_E_INVALIDFUNCTION;
+
+ #ifdef USE_WIN_FILE
+
+ #ifdef SUPPORT_DEVICE_FILE
+ if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END))
+ {
+ switch (seekOrigin)
+ {
+ case STREAM_SEEK_SET: break;
+ case STREAM_SEEK_CUR: offset += VirtPos; break;
+ case STREAM_SEEK_END: offset += File.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;
+ }
+ #endif
+
+ UInt64 realNewPosition;
+ bool result = File.Seek(offset, seekOrigin, realNewPosition);
+
+ #ifdef SUPPORT_DEVICE_FILE
+ PhyPos = VirtPos = realNewPosition;
+ #endif
+
+ if (newPosition)
+ *newPosition = realNewPosition;
+ return ConvertBoolToHRESULT(result);
+
+ #else
+
+ off_t res = File.Seek((off_t)offset, seekOrigin);
+ if (res == -1)
+ return E_FAIL;
+ if (newPosition)
+ *newPosition = (UInt64)res;
+ return S_OK;
+
+ #endif
+}
+
+STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
+{
+ return ConvertBoolToHRESULT(File.GetLength(*size));
+}
+
+#ifdef USE_WIN_FILE
+
+STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)
+{
+ BY_HANDLE_FILE_INFORMATION info;
+ if (File.GetFileInformation(&info))
+ {
+ if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
+ if (cTime) *cTime = info.ftCreationTime;
+ if (aTime) *aTime = info.ftLastAccessTime;
+ if (mTime) *mTime = info.ftLastWriteTime;
+ if (attrib) *attrib = info.dwFileAttributes;
+ return S_OK;
+ }
+ return GetLastError();
+}
+
+STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)
+{
+ BY_HANDLE_FILE_INFORMATION info;
+ if (File.GetFileInformation(&info))
+ {
+ props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
+ props->VolID = info.dwVolumeSerialNumber;
+ props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
+ props->FileID_High = 0;
+ props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;
+ props->Attrib = info.dwFileAttributes;
+ props->CTime = info.ftCreationTime;
+ props->ATime = info.ftLastAccessTime;
+ props->MTime = info.ftLastWriteTime;
+ return S_OK;
+ }
+ return GetLastError();
+}
+
+#endif
+
+//////////////////////////
+// COutFileStream
+
+HRESULT COutFileStream::Close()
+{
+ return ConvertBoolToHRESULT(File.Close());
+}
+
+STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ #ifdef USE_WIN_FILE
+
+ UInt32 realProcessedSize;
+ bool result = File.Write(data, size, realProcessedSize);
+ ProcessedSize += realProcessedSize;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return ConvertBoolToHRESULT(result);
+
+ #else
+
+ if (processedSize)
+ *processedSize = 0;
+ ssize_t res = File.Write(data, (size_t)size);
+ if (res == -1)
+ return E_FAIL;
+ if (processedSize)
+ *processedSize = (UInt32)res;
+ ProcessedSize += res;
+ return S_OK;
+
+ #endif
+}
+
+STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ if (seekOrigin >= 3)
+ return STG_E_INVALIDFUNCTION;
+
+ #ifdef USE_WIN_FILE
+
+ UInt64 realNewPosition;
+ bool result = File.Seek(offset, seekOrigin, realNewPosition);
+ if (newPosition)
+ *newPosition = realNewPosition;
+ return ConvertBoolToHRESULT(result);
+
+ #else
+
+ off_t res = File.Seek((off_t)offset, seekOrigin);
+ if (res == -1)
+ return E_FAIL;
+ if (newPosition)
+ *newPosition = (UInt64)res;
+ return S_OK;
+
+ #endif
+}
+
+STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
+{
+ #ifdef USE_WIN_FILE
+
+ UInt64 currentPos;
+ if (!File.Seek(0, FILE_CURRENT, currentPos))
+ return E_FAIL;
+ bool result = File.SetLength(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);
+ if (processedSize)
+ *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)
+ {
+ // Seems that Windows doesn't like big amounts writing to stdout.
+ // So we limit portions by 32KB.
+ UInt32 sizeTemp = (1 << 15);
+ if (sizeTemp > size)
+ 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)
+ *processedSize += realProcessedSize;
+ }
+ return ConvertBoolToHRESULT(res != FALSE);
+
+ #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;
+
+ #endif
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.h b/other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.h
new file mode 100644
index 0000000000..a0996f80ac
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.h
@@ -0,0 +1,166 @@
+// FileStreams.h
+
+#ifndef __FILE_STREAMS_H
+#define __FILE_STREAMS_H
+
+#ifdef _WIN32
+#define USE_WIN_FILE
+#endif
+
+#include "../../Common/MyString.h"
+
+#ifdef USE_WIN_FILE
+#include "../../Windows/FileIO.h"
+#else
+#include "../../Common/C_FileIO.h"
+#endif
+
+#include "../../Common/MyCom.h"
+
+#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,
+ #ifdef USE_WIN_FILE
+ public IStreamGetProps,
+ public IStreamGetProps2,
+ #endif
+ public CMyUnknownImp
+{
+public:
+ #ifdef USE_WIN_FILE
+ NWindows::NFile::NIO::CInFile File;
+
+ #ifdef SUPPORT_DEVICE_FILE
+ UInt64 VirtPos;
+ UInt64 PhyPos;
+ UInt64 BufStartPos;
+ Byte *Buf;
+ UInt32 BufSize;
+ #endif
+
+ #else
+ NC::NFile::NIO::CInFile File;
+ #endif
+
+ bool SupportHardLinks;
+
+ IInFileStream_Callback *Callback;
+ My_UINT_PTR CallbackRef;
+
+ virtual ~CInFileStream();
+
+ CInFileStream();
+
+ bool Open(CFSTR fileName)
+ {
+ return File.Open(fileName);
+ }
+
+ bool OpenShared(CFSTR fileName, bool shareForWrite)
+ {
+ return File.OpenShared(fileName, shareForWrite);
+ }
+
+ MY_QUERYINTERFACE_BEGIN2(IInStream)
+ MY_QUERYINTERFACE_ENTRY(IStreamGetSize)
+ #ifdef USE_WIN_FILE
+ MY_QUERYINTERFACE_ENTRY(IStreamGetProps)
+ MY_QUERYINTERFACE_ENTRY(IStreamGetProps2)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ STDMETHOD(GetSize)(UInt64 *size);
+ #ifdef USE_WIN_FILE
+ STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib);
+ STDMETHOD(GetProps2)(CStreamFileProps *props);
+ #endif
+};
+
+class CStdInFileStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ virtual ~CStdInFileStream() {}
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+class COutFileStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+public:
+ #ifdef USE_WIN_FILE
+ NWindows::NFile::NIO::COutFile File;
+ #else
+ NC::NFile::NIO::COutFile File;
+ #endif
+ virtual ~COutFileStream() {}
+ bool Create(CFSTR fileName, bool createAlways)
+ {
+ ProcessedSize = 0;
+ return File.Create(fileName, createAlways);
+ }
+ bool Open(CFSTR fileName, DWORD creationDisposition)
+ {
+ ProcessedSize = 0;
+ return File.Open(fileName, creationDisposition);
+ }
+
+ HRESULT Close();
+
+ UInt64 ProcessedSize;
+
+ #ifdef USE_WIN_FILE
+ bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
+ {
+ return File.SetTime(cTime, aTime, mTime);
+ }
+ bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); }
+ #endif
+
+
+ MY_UNKNOWN_IMP1(IOutStream)
+
+ 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);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.cpp
new file mode 100644
index 0000000000..275c60d4ba
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.cpp
@@ -0,0 +1,418 @@
+// FilterCoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/Defs.h"
+
+#include "FilterCoder.h"
+#include "StreamUtils.h"
+
+/*
+ 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;
+
+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()
+{
+ 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;
+}
+
+HRESULT CFilterCoder::Init_and_Alloc()
+{
+ RINOK(Filter->Init());
+ return Alloc();
+}
+
+CFilterCoder::CFilterCoder(bool encodeMode):
+ _bufSize(0),
+ _inBufSize(kBufSize),
+ _outBufSize(kBufSize),
+ _encodeMode(encodeMode),
+ _outSizeIsDefined(false),
+ _outSize(0),
+ _nowPos64(0)
+ {}
+
+CFilterCoder::~CFilterCoder()
+{
+}
+
+STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ RINOK(Init_and_Alloc());
+
+ UInt64 nowPos64 = 0;
+ bool inputFinished = false;
+ UInt32 pos = 0;
+
+ while (!outSize || nowPos64 < *outSize)
+ {
+ UInt32 endPos = pos;
+
+ if (!inputFinished)
+ {
+ size_t processedSize = _bufSize - pos;
+ RINOK(ReadStream(inStream, _buf + pos, &processedSize));
+ endPos = pos + (UInt32)processedSize;
+ inputFinished = (endPos != _bufSize);
+ }
+
+ pos = Filter->Filter(_buf, endPos);
+
+ if (pos > 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;
+ }
+
+ if (endPos == 0)
+ return S_OK;
+
+ UInt32 size = (pos != 0 ? pos : endPos);
+ if (outSize)
+ {
+ 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 (pos < endPos)
+ _buf[i++] = _buf[pos++];
+ pos = i;
+ }
+
+ return S_OK;
+}
+
+
+
+// ---------- Write to Filter ----------
+
+STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
+{
+ _outStream = outStream;
+ return S_OK;
+}
+
+STDMETHODIMP CFilterCoder::ReleaseOutStream()
+{
+ _outStream.Release();
+ 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)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ RINOK(Flush2());
+
+ // _convSize is 0
+ // _convPos is 0
+ // _bufPos is small
+
+ if (_bufPos != _bufSize)
+ {
+ 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;
+ }
+
+ // _bufPos == _bufSize
+ _convSize = Filter->Filter(_buf, _bufPos);
+
+ if (_convSize == 0)
+ break;
+ if (_convSize > _bufPos)
+ {
+ // that case is not possible.
+ _convSize = 0;
+ return E_FAIL;
+ }
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CFilterCoder::OutStreamFinish()
+{
+ for (;;)
+ {
+ RINOK(Flush2());
+ if (_bufPos == 0)
+ break;
+ _convSize = Filter->Filter(_buf, _bufPos);
+ if (_convSize == 0)
+ _convSize = _bufPos;
+ else if (_convSize > _bufPos)
+ {
+ // 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;
+ }
+ }
+
+ CMyComPtr<IOutStreamFinish> finish;
+ _outStream.QueryInterface(IID_IOutStreamFinish, &finish);
+ if (finish)
+ return finish->OutStreamFinish();
+ return S_OK;
+}
+
+// ---------- Init functions ----------
+
+STDMETHODIMP CFilterCoder::InitEncoder()
+{
+ 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)
+{
+ _inStream = inStream;
+ return S_OK;
+}
+
+STDMETHODIMP CFilterCoder::ReleaseInStream()
+{
+ _inStream.Release();
+ return S_OK;
+}
+
+
+STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ while (size != 0)
+ {
+ if (_convSize != 0)
+ {
+ 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;
+ }
+
+ 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 (_bufPos == 0)
+ break;
+ // BCJ
+ _convSize = _bufPos;
+ continue;
+ }
+
+ if (_convSize > _bufPos)
+ {
+ // 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); }
+
+STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size)
+ { return _CryptoProperties->SetKey(data, size); }
+
+STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 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); }
+
+STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
+ { return _WriteCoderProperties->WriteCoderProperties(outStream); }
+
+/*
+STDMETHODIMP CFilterCoder::ResetSalt()
+ { return _CryptoResetSalt->ResetSalt(); }
+*/
+
+STDMETHODIMP CFilterCoder::ResetInitVector()
+ { return _CryptoResetInitVector->ResetInitVector(); }
+
+#endif
+
+
+STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
+ { return _SetDecoderProperties2->SetDecoderProperties2(data, size); }
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.h b/other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.h
new file mode 100644
index 0000000000..0e2f84f115
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.h
@@ -0,0 +1,235 @@
+// FilterCoder.h
+
+#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
+{
+ #ifdef _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 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 CAlignedMidBuffer
+{
+ UInt32 _bufSize;
+ UInt32 _inBufSize;
+ UInt32 _outBufSize;
+
+ bool _encodeMode;
+ bool _outSizeIsDefined;
+ UInt64 _outSize;
+ UInt64 _nowPos64;
+
+ 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()
+ {
+ _bufPos = 0;
+ _convPos = 0;
+ _convSize = 0;
+
+ _outSizeIsDefined = false;
+ _outSize = 0;
+ _nowPos64 = 0;
+ }
+
+ HRESULT Alloc();
+ HRESULT Init_and_Alloc();
+ HRESULT Flush2();
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoSetPassword> _SetPassword;
+ CMyComPtr<ICryptoProperties> _CryptoProperties;
+ #endif
+
+ #ifndef EXTRACT_ONLY
+ CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
+ CMyComPtr<ICompressWriteCoderProperties> _WriteCoderProperties;
+ // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
+ CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
+ #endif
+
+ CMyComPtr<ICompressSetDecoderProperties2> _SetDecoderProperties2;
+
+public:
+ CMyComPtr<ICompressFilter> Filter;
+
+ CFilterCoder(bool encodeMode);
+ ~CFilterCoder();
+
+ 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(); }
+ };
+
+ class C_Filter_Releaser
+ {
+ public:
+ CFilterCoder *FilterCoder;
+ C_Filter_Releaser(): FilterCoder(NULL) {}
+ ~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); }
+ };
+
+
+ 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(IOutStreamFinish)
+
+ MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
+
+ #ifndef _NO_CRYPTO
+ 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(ICryptoResetSalt, Filter, _CryptoResetSalt)
+ MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
+ #endif
+
+ 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(SetOutStreamSize)(const UInt64 *outSize);
+ STDMETHOD(InitEncoder)();
+
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+ 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(OutStreamFinish)();
+
+ STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
+ STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
+
+ #ifndef _NO_CRYPTO
+ STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
+
+ 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);
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+ // STDMETHOD(ResetSalt)();
+ STDMETHOD(ResetInitVector)();
+ #endif
+
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+
+
+ HRESULT Init_NoSubFilterInit();
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.cpp
new file mode 100644
index 0000000000..826e98b191
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.cpp
@@ -0,0 +1,163 @@
+// InBuffer.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "InBuffer.h"
+
+CInBufferBase::CInBufferBase() throw():
+ _buf(0),
+ _bufLim(0),
+ _bufBase(0),
+ _stream(0),
+ _processedSize(0),
+ _bufSize(0),
+ _wasFinished(false),
+ NumExtraBytes(0)
+{}
+
+bool CInBuffer::Create(size_t bufSize) throw()
+{
+ const unsigned kMinBlockSize = 1;
+ if (bufSize < kMinBlockSize)
+ bufSize = kMinBlockSize;
+ if (_bufBase != 0 && _bufSize == bufSize)
+ return true;
+ Free();
+ _bufSize = bufSize;
+ _bufBase = (Byte *)::MidAlloc(bufSize);
+ return (_bufBase != 0);
+}
+
+void CInBuffer::Free() throw()
+{
+ ::MidFree(_bufBase);
+ _bufBase = 0;
+}
+
+void CInBufferBase::Init() throw()
+{
+ _processedSize = 0;
+ _buf = _bufBase;
+ _bufLim = _buf;
+ _wasFinished = false;
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = S_OK;
+ #endif
+ NumExtraBytes = 0;
+}
+
+bool CInBufferBase::ReadBlock()
+{
+ #ifdef _NO_EXCEPTIONS
+ if (ErrorCode != S_OK)
+ return false;
+ #endif
+ if (_wasFinished)
+ return false;
+ _processedSize += (_buf - _bufBase);
+ _buf = _bufBase;
+ _bufLim = _bufBase;
+ UInt32 processed;
+ // FIX_ME: we can improve it to support (_bufSize >= (1 << 32))
+ HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = result;
+ #else
+ if (result != S_OK)
+ throw CInBufferException(result);
+ #endif
+ _bufLim = _buf + processed;
+ _wasFinished = (processed == 0);
+ return !_wasFinished;
+}
+
+bool CInBufferBase::ReadByte_FromNewBlock(Byte &b)
+{
+ if (!ReadBlock())
+ {
+ NumExtraBytes++;
+ b = 0xFF;
+ return false;
+ }
+ b = *_buf++;
+ return true;
+}
+
+Byte CInBufferBase::ReadByte_FromNewBlock()
+{
+ if (!ReadBlock())
+ {
+ NumExtraBytes++;
+ return 0xFF;
+ }
+ return *_buf++;
+}
+
+size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
+{
+ size_t num = 0;
+ for (;;)
+ {
+ const size_t rem = _bufLim - _buf;
+ if (size <= rem)
+ {
+ if (size != 0)
+ {
+ memcpy(buf, _buf, size);
+ _buf += size;
+ num += size;
+ }
+ return num;
+ }
+ if (rem != 0)
+ {
+ memcpy(buf, _buf, rem);
+ _buf += rem;
+ buf += rem;
+ num += rem;
+ size -= rem;
+ }
+ if (!ReadBlock())
+ return num;
+ }
+
+ /*
+ if ((size_t)(_bufLim - _buf) >= size)
+ {
+ const Byte *src = _buf;
+ for (size_t i = 0; i < size; i++)
+ buf[i] = src[i];
+ _buf += size;
+ return size;
+ }
+ for (size_t i = 0; i < size; i++)
+ {
+ if (_buf >= _bufLim)
+ if (!ReadBlock())
+ return i;
+ buf[i] = *_buf++;
+ }
+ return size;
+ */
+}
+
+size_t CInBufferBase::Skip(size_t size)
+{
+ size_t processed = 0;
+ for (;;)
+ {
+ size_t rem = (_bufLim - _buf);
+ if (rem >= size)
+ {
+ _buf += size;
+ return processed + size;
+ }
+ _buf += rem;
+ processed += rem;
+ size -= rem;
+ if (!ReadBlock())
+ return processed;
+ }
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.h b/other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.h
new file mode 100644
index 0000000000..76e359a00b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.h
@@ -0,0 +1,92 @@
+// InBuffer.h
+
+#ifndef __IN_BUFFER_H
+#define __IN_BUFFER_H
+
+#include "../../Common/MyException.h"
+#include "../IStream.h"
+
+#ifndef _NO_EXCEPTIONS
+struct CInBufferException: public CSystemException
+{
+ CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
+};
+#endif
+
+class CInBufferBase
+{
+protected:
+ Byte *_buf;
+ Byte *_bufLim;
+ Byte *_bufBase;
+
+ ISequentialInStream *_stream;
+ UInt64 _processedSize;
+ size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger
+ // only up to 32-bits values now are supported!
+ bool _wasFinished;
+
+ bool ReadBlock();
+ bool ReadByte_FromNewBlock(Byte &b);
+ Byte ReadByte_FromNewBlock();
+
+public:
+ #ifdef _NO_EXCEPTIONS
+ HRESULT ErrorCode;
+ #endif
+ UInt32 NumExtraBytes;
+
+ CInBufferBase() throw();
+
+ UInt64 GetStreamSize() const { return _processedSize + (_buf - _bufBase); }
+ UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (_buf - _bufBase); }
+ bool WasFinished() const { return _wasFinished; }
+
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+
+ void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos)
+ {
+ _bufBase = buf;
+ _bufSize = bufSize;
+ _processedSize = 0;
+ _buf = buf + pos;
+ _bufLim = buf + end;
+ _wasFinished = false;
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = S_OK;
+ #endif
+ NumExtraBytes = 0;
+ }
+
+ void Init() throw();
+
+ MY_FORCE_INLINE
+ bool ReadByte(Byte &b)
+ {
+ if (_buf >= _bufLim)
+ return ReadByte_FromNewBlock(b);
+ b = *_buf++;
+ return true;
+ }
+
+ MY_FORCE_INLINE
+ Byte ReadByte()
+ {
+ if (_buf >= _bufLim)
+ return ReadByte_FromNewBlock();
+ return *_buf++;
+ }
+
+ size_t ReadBytes(Byte *buf, size_t size);
+ size_t Skip(size_t size);
+};
+
+class CInBuffer: public CInBufferBase
+{
+public:
+ ~CInBuffer() { Free(); }
+ bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported!
+ void Free() throw();
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.cpp
new file mode 100644
index 0000000000..d83d67467e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.cpp
@@ -0,0 +1,127 @@
+// InOutTempBuffer.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/7zCrc.h"
+
+#include "../../Common/Defs.h"
+
+#include "InOutTempBuffer.h"
+#include "StreamUtils.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+static const size_t kTempBufSize = (1 << 20);
+
+#define kTempFilePrefixString FTEXT("7zt")
+
+CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { }
+
+void CInOutTempBuffer::Create()
+{
+ if (!_buf)
+ _buf = new Byte[kTempBufSize];
+}
+
+CInOutTempBuffer::~CInOutTempBuffer()
+{
+ delete []_buf;
+}
+
+void CInOutTempBuffer::InitWriting()
+{
+ _bufPos = 0;
+ _tempFileCreated = false;
+ _size = 0;
+ _crc = CRC_INIT_VAL;
+}
+
+bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
+{
+ if (size == 0)
+ return true;
+ if (!_tempFileCreated)
+ {
+ if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))
+ return false;
+ _tempFileCreated = true;
+ }
+ UInt32 processed;
+ if (!_outFile.Write(data, size, processed))
+ return false;
+ _crc = CrcUpdate(_crc, data, processed);
+ _size += processed;
+ return (processed == size);
+}
+
+bool CInOutTempBuffer::Write(const void *data, UInt32 size)
+{
+ if (size == 0)
+ return true;
+ size_t cur = kTempBufSize - _bufPos;
+ if (cur != 0)
+ {
+ if (cur > size)
+ cur = size;
+ memcpy(_buf + _bufPos, data, cur);
+ _crc = CrcUpdate(_crc, data, cur);
+ _bufPos += cur;
+ _size += cur;
+ size -= (UInt32)cur;
+ data = ((const Byte *)data) + cur;
+ }
+ return WriteToFile(data, size);
+}
+
+HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
+{
+ if (!_outFile.Close())
+ return E_FAIL;
+
+ UInt64 size = 0;
+ UInt32 crc = CRC_INIT_VAL;
+
+ if (_bufPos != 0)
+ {
+ RINOK(WriteStream(stream, _buf, _bufPos));
+ crc = CrcUpdate(crc, _buf, _bufPos);
+ size += _bufPos;
+ }
+
+ if (_tempFileCreated)
+ {
+ NIO::CInFile inFile;
+ if (!inFile.Open(_tempFile.GetPath()))
+ return E_FAIL;
+ while (size < _size)
+ {
+ UInt32 processed;
+ if (!inFile.ReadPart(_buf, kTempBufSize, processed))
+ return E_FAIL;
+ if (processed == 0)
+ break;
+ RINOK(WriteStream(stream, _buf, processed));
+ crc = CrcUpdate(crc, _buf, processed);
+ 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)
+ *processed = 0;
+ return E_FAIL;
+ }
+ if (processed)
+ *processed = size;
+ return S_OK;
+}
+*/
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.h b/other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.h
new file mode 100644
index 0000000000..4140d28308
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.h
@@ -0,0 +1,48 @@
+// InOutTempBuffer.h
+
+#ifndef __IN_OUT_TEMP_BUFFER_H
+#define __IN_OUT_TEMP_BUFFER_H
+
+#include "../../Common/MyCom.h"
+#include "../../Windows/FileDir.h"
+
+#include "../IStream.h"
+
+class CInOutTempBuffer
+{
+ NWindows::NFile::NDir::CTempFile _tempFile;
+ NWindows::NFile::NIO::COutFile _outFile;
+ Byte *_buf;
+ size_t _bufPos;
+ UInt64 _size;
+ UInt32 _crc;
+ bool _tempFileCreated;
+
+ bool WriteToFile(const void *data, UInt32 size);
+public:
+ CInOutTempBuffer();
+ ~CInOutTempBuffer();
+ void Create();
+
+ void InitWriting();
+ bool Write(const void *data, UInt32 size);
+
+ HRESULT WriteToStream(ISequentialOutStream *stream);
+ UInt64 GetDataSize() const { return _size; }
+};
+
+/*
+class CSequentialOutTempBufferImp:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CInOutTempBuffer *_buf;
+public:
+ void Init(CInOutTempBuffer *buffer) { _buf = buffer; }
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+*/
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.cpp
new file mode 100644
index 0000000000..fc7e794cf8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.cpp
@@ -0,0 +1,367 @@
+// LimitedStreams.cpp
+
+#include "StdAfx.h"
+
+#include <string.h>
+
+#include "LimitedStreams.h"
+
+STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize = 0;
+ {
+ const UInt64 rem = _size - _pos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ HRESULT result = S_OK;
+ if (size != 0)
+ {
+ result = _stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ if (realProcessedSize == 0)
+ _wasFinished = true;
+ }
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return result;
+}
+
+STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (_virtPos >= _size)
+ {
+ // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.
+ return S_OK;
+ // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF
+ }
+ {
+ const UInt64 rem = _size - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ UInt64 newPos = _startOffset + _virtPos;
+ if (newPos != _physPos)
+ {
+ _physPos = newPos;
+ RINOK(SeekToPhys());
+ }
+ HRESULT res = _stream->Read(data, size, &size);
+ if (processedSize)
+ *processedSize = size;
+ _physPos += size;
+ _virtPos += size;
+ return res;
+}
+
+STDMETHODIMP CLimitedInStream::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 += _size; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _virtPos = offset;
+ if (newPosition)
+ *newPosition = _virtPos;
+ return S_OK;
+}
+
+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)
+{
+ *resStream = 0;
+ CLimitedInStream *streamSpec = new CLimitedInStream;
+ CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+ streamSpec->SetStream(inStream);
+ RINOK(streamSpec->InitAndSeek(pos, size));
+ streamSpec->SeekToStart();
+ *resStream = streamTemp.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (_virtPos >= Size)
+ return S_OK;
+ {
+ UInt64 rem = Size - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ if (size == 0)
+ return S_OK;
+
+ if (_curRem == 0)
+ {
+ const UInt32 blockSize = (UInt32)1 << BlockSizeLog;
+ const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);
+ const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
+ const UInt32 phyBlock = Vector[virtBlock];
+
+ UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;
+ if (newPos != _physPos)
+ {
+ _physPos = newPos;
+ RINOK(SeekToPhys());
+ }
+
+ _curRem = blockSize - offsetInBlock;
+
+ for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)
+ _curRem += (UInt32)1 << BlockSizeLog;
+ }
+
+ if (size > _curRem)
+ size = _curRem;
+ HRESULT res = Stream->Read(data, size, &size);
+ if (processedSize)
+ *processedSize = size;
+ _physPos += size;
+ _virtPos += size;
+ _curRem -= size;
+ return res;
+}
+
+STDMETHODIMP CClusterInStream::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 += Size; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ if (_virtPos != (UInt64)offset)
+ _curRem = 0;
+ _virtPos = offset;
+ if (newPosition)
+ *newPosition = offset;
+ return S_OK;
+}
+
+
+STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (_virtPos >= Extents.Back().Virt)
+ return S_OK;
+ if (size == 0)
+ return S_OK;
+
+ unsigned left = 0, right = Extents.Size() - 1;
+ for (;;)
+ {
+ unsigned mid = (left + right) / 2;
+ if (mid == left)
+ break;
+ if (_virtPos < Extents[mid].Virt)
+ right = mid;
+ else
+ left = mid;
+ }
+
+ const CSeekExtent &extent = Extents[left];
+ UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt);
+ if (_needStartSeek || _phyPos != phyPos)
+ {
+ _needStartSeek = false;
+ _phyPos = phyPos;
+ RINOK(SeekToPhys());
+ }
+
+ UInt64 rem = Extents[left + 1].Virt - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+
+ HRESULT res = Stream->Read(data, size, &size);
+ _phyPos += size;
+ _virtPos += size;
+ if (processedSize)
+ *processedSize = size;
+ return res;
+}
+
+STDMETHODIMP CExtentsStream::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 += Extents.Back().Virt; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _virtPos = offset;
+ if (newPosition)
+ *newPosition = _virtPos;
+ return S_OK;
+}
+
+
+STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ HRESULT result = S_OK;
+ if (processedSize)
+ *processedSize = 0;
+ if (size > _size)
+ {
+ if (_size == 0)
+ {
+ _overflow = true;
+ if (!_overflowIsAllowed)
+ return E_FAIL;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ }
+ size = (UInt32)_size;
+ }
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ _size -= size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
+}
+
+
+STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 cur;
+ HRESULT res = Stream->Read(data, size, &cur);
+ if (processedSize)
+ *processedSize = cur;
+ _virtPos += cur;
+ return res;
+}
+
+STDMETHODIMP CTailInStream::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:
+ {
+ UInt64 pos = 0;
+ RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos));
+ if (pos < Offset)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _virtPos = pos - Offset;
+ if (newPosition)
+ *newPosition = _virtPos;
+ return S_OK;
+ }
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _virtPos = offset;
+ if (newPosition)
+ *newPosition = _virtPos;
+ return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL);
+}
+
+STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (_virtPos >= _size)
+ {
+ // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.
+ return S_OK;
+ // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF
+ }
+ UInt64 rem = _size - _virtPos;
+ if (rem < size)
+ size = (UInt32)rem;
+
+ UInt64 newPos = _startOffset + _virtPos;
+ UInt64 offsetInCache = newPos - _cachePhyPos;
+ HRESULT res = S_OK;
+ if (newPos >= _cachePhyPos &&
+ offsetInCache <= _cacheSize &&
+ size <= _cacheSize - (size_t)offsetInCache)
+ {
+ if (size != 0)
+ memcpy(data, _cache + (size_t)offsetInCache, size);
+ }
+ else
+ {
+ if (newPos != _physPos)
+ {
+ _physPos = newPos;
+ RINOK(SeekToPhys());
+ }
+ res = _stream->Read(data, size, &size);
+ _physPos += size;
+ }
+ if (processedSize)
+ *processedSize = size;
+ _virtPos += size;
+ return res;
+}
+
+STDMETHODIMP CLimitedCachedInStream::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 += _size; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _virtPos = offset;
+ if (newPosition)
+ *newPosition = _virtPos;
+ return S_OK;
+}
+
+STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 cur;
+ HRESULT res = Stream->Write(data, size, &cur);
+ if (processedSize)
+ *processedSize = cur;
+ _virtPos += cur;
+ if (_virtSize < _virtPos)
+ _virtSize = _virtPos;
+ return res;
+}
+
+STDMETHODIMP CTailOutStream::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 += _virtSize; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _virtPos = offset;
+ if (newPosition)
+ *newPosition = _virtPos;
+ return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL);
+}
+
+STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize)
+{
+ _virtSize = newSize;
+ return Stream->SetSize(Offset + newSize);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.h b/other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.h
new file mode 100644
index 0000000000..2e55aa0b64
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.h
@@ -0,0 +1,252 @@
+// LimitedStreams.h
+
+#ifndef __LIMITED_STREAMS_H
+#define __LIMITED_STREAMS_H
+
+#include "../../Common/MyBuffer.h"
+#include "../../Common/MyCom.h"
+#include "../../Common/MyVector.h"
+#include "../IStream.h"
+
+class CLimitedSequentialInStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _size;
+ UInt64 _pos;
+ bool _wasFinished;
+public:
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init(UInt64 streamSize)
+ {
+ _size = streamSize;
+ _pos = 0;
+ _wasFinished = false;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ UInt64 GetSize() const { return _pos; }
+ UInt64 GetRem() const { return _size - _pos; }
+ bool WasFinished() const { return _wasFinished; }
+};
+
+class CLimitedInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<IInStream> _stream;
+ UInt64 _virtPos;
+ UInt64 _physPos;
+ UInt64 _size;
+ UInt64 _startOffset;
+
+ HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
+public:
+ void SetStream(IInStream *stream) { _stream = stream; }
+ HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
+ {
+ _startOffset = startOffset;
+ _physPos = startOffset;
+ _virtPos = 0;
+ _size = size;
+ return SeekToPhys();
+ }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
+};
+
+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);
+
+class CClusterInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ UInt64 _virtPos;
+ UInt64 _physPos;
+ UInt32 _curRem;
+public:
+ unsigned BlockSizeLog;
+ UInt64 Size;
+ CMyComPtr<IInStream> Stream;
+ CRecordVector<UInt32> Vector;
+ UInt64 StartOffset;
+
+ HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
+
+ HRESULT InitAndSeek()
+ {
+ _curRem = 0;
+ _virtPos = 0;
+ _physPos = StartOffset;
+ if (Vector.Size() > 0)
+ {
+ _physPos = StartOffset + (Vector[0] << BlockSizeLog);
+ return SeekToPhys();
+ }
+ return S_OK;
+ }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+struct CSeekExtent
+{
+ UInt64 Phy;
+ UInt64 Virt;
+};
+
+class CExtentsStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ UInt64 _phyPos;
+ UInt64 _virtPos;
+ bool _needStartSeek;
+
+ HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); }
+
+public:
+ CMyComPtr<IInStream> Stream;
+ CRecordVector<CSeekExtent> Extents;
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+ void ReleaseStream() { Stream.Release(); }
+
+ void Init()
+ {
+ _virtPos = 0;
+ _phyPos = 0;
+ _needStartSeek = true;
+ }
+};
+
+class CLimitedSequentialOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+ bool _overflow;
+ bool _overflowIsAllowed;
+public:
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init(UInt64 size, bool overflowIsAllowed = false)
+ {
+ _size = size;
+ _overflow = false;
+ _overflowIsAllowed = overflowIsAllowed;
+ }
+ bool IsFinishedOK() const { return (_size == 0 && !_overflow); }
+ UInt64 GetRem() const { return _size; }
+};
+
+
+class CTailInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ UInt64 _virtPos;
+public:
+ CMyComPtr<IInStream> Stream;
+ UInt64 Offset;
+
+ void Init()
+ {
+ _virtPos = 0;
+ }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); }
+};
+
+class CLimitedCachedInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<IInStream> _stream;
+ UInt64 _virtPos;
+ UInt64 _physPos;
+ UInt64 _size;
+ UInt64 _startOffset;
+
+ const Byte *_cache;
+ size_t _cacheSize;
+ size_t _cachePhyPos;
+
+
+ HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
+public:
+ CByteBuffer Buffer;
+
+ void SetStream(IInStream *stream) { _stream = stream; }
+ void SetCache(size_t cacheSize, size_t cachePos)
+ {
+ _cache = Buffer;
+ _cacheSize = cacheSize;
+ _cachePhyPos = cachePos;
+ }
+
+ HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
+ {
+ _startOffset = startOffset;
+ _physPos = startOffset;
+ _virtPos = 0;
+ _size = size;
+ return SeekToPhys();
+ }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+ HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
+};
+
+class CTailOutStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+ UInt64 _virtPos;
+ UInt64 _virtSize;
+public:
+ CMyComPtr<IOutStream> Stream;
+ UInt64 Offset;
+
+ virtual ~CTailOutStream() {}
+
+ MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream)
+
+ void Init()
+ {
+ _virtPos = 0;
+ _virtSize = 0;
+ }
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+ STDMETHOD(SetSize)(UInt64 newSize);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.cpp
new file mode 100644
index 0000000000..1223efe857
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.cpp
@@ -0,0 +1,3 @@
+// LockedStream.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.h b/other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.h
new file mode 100644
index 0000000000..5bf5c85a44
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.h
@@ -0,0 +1,6 @@
+// LockedStream.h
+
+#ifndef __LOCKED_STREAM_H
+#define __LOCKED_STREAM_H
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/MethodId.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/MethodId.cpp
new file mode 100644
index 0000000000..9a07e4c9a1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/MethodId.cpp
@@ -0,0 +1,3 @@
+// MethodId.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/MethodId.h b/other-licenses/7zstub/src/CPP/7zip/Common/MethodId.h
new file mode 100644
index 0000000000..1ba9f49afc
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/MethodId.h
@@ -0,0 +1,10 @@
+// MethodId.h
+
+#ifndef __7Z_METHOD_ID_H
+#define __7Z_METHOD_ID_H
+
+#include "../../Common/MyTypes.h"
+
+typedef UInt64 CMethodId;
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp
new file mode 100644
index 0000000000..2134462c79
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp
@@ -0,0 +1,509 @@
+// MethodProps.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/StringToInt.h"
+
+#include "MethodProps.h"
+
+using namespace NWindows;
+
+bool StringToBool(const wchar_t *s, bool &res)
+{
+ if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON"))
+ {
+ res = true;
+ return true;
+ }
+ if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF"))
+ {
+ res = false;
+ return true;
+ }
+ return false;
+}
+
+HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest)
+{
+ switch (prop.vt)
+ {
+ case VT_EMPTY: dest = true; return S_OK;
+ case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK;
+ case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG;
+ }
+ return E_INVALIDARG;
+}
+
+unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number)
+{
+ const wchar_t *start = srcString;
+ const wchar_t *end;
+ number = ConvertStringToUInt32(start, &end);
+ return (unsigned)(end - start);
+}
+
+static unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number)
+{
+ const wchar_t *start = srcString;
+ const wchar_t *end;
+ number = ConvertStringToUInt64(start, &end);
+ return (unsigned)(end - start);
+}
+
+HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
+{
+ // =VT_UI4
+ // =VT_EMPTY
+ // {stringUInt32}=VT_EMPTY
+
+ if (prop.vt == VT_UI4)
+ {
+ if (!name.IsEmpty())
+ return E_INVALIDARG;
+ resValue = prop.ulVal;
+ return S_OK;
+ }
+ if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ if (name.IsEmpty())
+ return S_OK;
+ UInt32 v;
+ if (ParseStringToUInt32(name, v) != name.Len())
+ return E_INVALIDARG;
+ resValue = v;
+ return S_OK;
+}
+
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
+{
+ if (name.IsEmpty())
+ {
+ switch (prop.vt)
+ {
+ case VT_UI4:
+ numThreads = prop.ulVal;
+ break;
+ default:
+ {
+ bool val;
+ RINOK(PROPVARIANT_to_bool(prop, val));
+ numThreads = (val ? defaultNumThreads : 1);
+ break;
+ }
+ }
+ return S_OK;
+ }
+ if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return ParsePropToUInt32(name, prop, numThreads);
+}
+
+
+static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp)
+{
+ const wchar_t *end;
+ UInt32 number = ConvertStringToUInt32(s, &end);
+ unsigned numDigits = (unsigned)(end - s.Ptr());
+ if (numDigits == 0 || s.Len() > numDigits + 1)
+ return E_INVALIDARG;
+
+ if (s.Len() == numDigits)
+ {
+ if (number >= 64)
+ return E_INVALIDARG;
+ if (number < 32)
+ destProp = (UInt32)((UInt32)1 << (unsigned)number);
+ else
+ destProp = (UInt64)((UInt64)1 << (unsigned)number);
+ return S_OK;
+ }
+
+ unsigned numBits;
+
+ switch (MyCharLower_Ascii(s[numDigits]))
+ {
+ case 'b': destProp = number; return S_OK;
+ case 'k': numBits = 10; break;
+ case 'm': numBits = 20; break;
+ case 'g': numBits = 30; break;
+ default: return E_INVALIDARG;
+ }
+
+ if (number < ((UInt32)1 << (32 - numBits)))
+ destProp = (UInt32)(number << numBits);
+ else
+ destProp = (UInt64)((UInt64)number << numBits);
+
+ return S_OK;
+}
+
+
+static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp)
+{
+ if (prop.vt == VT_UI4)
+ {
+ UInt32 v = prop.ulVal;
+ if (v >= 64)
+ return E_INVALIDARG;
+ if (v < 32)
+ destProp = (UInt32)((UInt32)1 << (unsigned)v);
+ else
+ destProp = (UInt64)((UInt64)1 << (unsigned)v);
+ return S_OK;
+ }
+ if (prop.vt == VT_BSTR)
+ {
+ UString s;
+ s = prop.bstrVal;
+ return StringToDictSize(s, destProp);
+ }
+ return E_INVALIDARG;
+}
+
+
+void CProps::AddProp32(PROPID propid, UInt32 val)
+{
+ CProp &prop = Props.AddNew();
+ prop.IsOptional = true;
+ prop.Id = propid;
+ prop.Value = (UInt32)val;
+}
+
+void CProps::AddPropBool(PROPID propid, bool val)
+{
+ CProp &prop = Props.AddNew();
+ prop.IsOptional = true;
+ prop.Id = propid;
+ prop.Value = val;
+}
+
+class CCoderProps
+{
+ PROPID *_propIDs;
+ NCOM::CPropVariant *_props;
+ unsigned _numProps;
+ unsigned _numPropsMax;
+public:
+ CCoderProps(unsigned numPropsMax)
+ {
+ _numPropsMax = numPropsMax;
+ _numProps = 0;
+ _propIDs = new PROPID[numPropsMax];
+ _props = new NCOM::CPropVariant[numPropsMax];
+ }
+ ~CCoderProps()
+ {
+ delete []_propIDs;
+ delete []_props;
+ }
+ void AddProp(const CProp &prop);
+ HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties)
+ {
+ return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps);
+ }
+};
+
+void CCoderProps::AddProp(const CProp &prop)
+{
+ if (_numProps >= _numPropsMax)
+ throw 1;
+ _propIDs[_numProps] = prop.Id;
+ _props[_numProps] = prop.Value;
+ _numProps++;
+}
+
+HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const
+{
+ CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0));
+ FOR_VECTOR (i, Props)
+ coderProps.AddProp(Props[i]);
+ if (dataSizeReduce)
+ {
+ CProp prop;
+ prop.Id = NCoderPropID::kReduceSize;
+ prop.Value = *dataSizeReduce;
+ coderProps.AddProp(prop);
+ }
+ return coderProps.SetProps(scp);
+}
+
+
+int CMethodProps::FindProp(PROPID id) const
+{
+ for (int i = Props.Size() - 1; i >= 0; i--)
+ if (Props[i].Id == id)
+ return i;
+ return -1;
+}
+
+int CMethodProps::GetLevel() const
+{
+ int i = FindProp(NCoderPropID::kLevel);
+ if (i < 0)
+ return 5;
+ if (Props[i].Value.vt != VT_UI4)
+ return 9;
+ UInt32 level = Props[i].Value.ulVal;
+ return level > 9 ? 9 : (int)level;
+}
+
+struct CNameToPropID
+{
+ VARTYPE VarType;
+ const char *Name;
+};
+
+
+// the following are related to NCoderPropID::EEnum values
+
+static const CNameToPropID g_NameToPropID[] =
+{
+ { VT_UI4, "" },
+ { VT_UI4, "d" },
+ { VT_UI4, "mem" },
+ { VT_UI4, "o" },
+ { VT_UI4, "c" },
+ { VT_UI4, "pb" },
+ { VT_UI4, "lc" },
+ { VT_UI4, "lp" },
+ { VT_UI4, "fb" },
+ { VT_BSTR, "mf" },
+ { VT_UI4, "mc" },
+ { VT_UI4, "pass" },
+ { VT_UI4, "a" },
+ { VT_UI4, "mt" },
+ { VT_BOOL, "eos" },
+ { VT_UI4, "x" },
+ { VT_UI8, "reduce" },
+ { VT_UI8, "expect" },
+ { VT_UI4, "b" },
+ { VT_UI4, "check" },
+ { VT_BSTR, "filter" },
+ { VT_UI8, "memuse" }
+};
+
+static int FindPropIdExact(const UString &name)
+{
+ for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++)
+ if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name))
+ return i;
+ return -1;
+}
+
+static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
+{
+ if (varType == srcProp.vt)
+ {
+ destProp = srcProp;
+ return true;
+ }
+
+ if (varType == VT_UI8 && srcProp.vt == VT_UI4)
+ {
+ destProp = (UInt64)srcProp.ulVal;
+ return true;
+ }
+
+ if (varType == VT_BOOL)
+ {
+ bool res;
+ if (PROPVARIANT_to_bool(srcProp, res) != S_OK)
+ return false;
+ destProp = res;
+ return true;
+ }
+ if (srcProp.vt == VT_EMPTY)
+ {
+ destProp = srcProp;
+ return true;
+ }
+ return false;
+}
+
+static void SplitParams(const UString &srcString, UStringVector &subStrings)
+{
+ subStrings.Clear();
+ UString s;
+ unsigned len = srcString.Len();
+ if (len == 0)
+ return;
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = srcString[i];
+ if (c == L':')
+ {
+ subStrings.Add(s);
+ s.Empty();
+ }
+ else
+ s += c;
+ }
+ subStrings.Add(s);
+}
+
+static void SplitParam(const UString &param, UString &name, UString &value)
+{
+ int eqPos = param.Find(L'=');
+ if (eqPos >= 0)
+ {
+ name.SetFrom(param, eqPos);
+ value = param.Ptr(eqPos + 1);
+ return;
+ }
+ unsigned i;
+ for (i = 0; i < param.Len(); i++)
+ {
+ wchar_t c = param[i];
+ if (c >= L'0' && c <= L'9')
+ break;
+ }
+ name.SetFrom(param, i);
+ value = param.Ptr(i);
+}
+
+static bool IsLogSizeProp(PROPID propid)
+{
+ switch (propid)
+ {
+ case NCoderPropID::kDictionarySize:
+ case NCoderPropID::kUsedMemorySize:
+ case NCoderPropID::kBlockSize:
+ case NCoderPropID::kBlockSize2:
+ // case NCoderPropID::kReduceSize:
+ return true;
+ }
+ return false;
+}
+
+HRESULT CMethodProps::SetParam(const UString &name, const UString &value)
+{
+ int index = FindPropIdExact(name);
+ if (index < 0)
+ return E_INVALIDARG;
+ const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
+ CProp prop;
+ prop.Id = index;
+
+ if (IsLogSizeProp(prop.Id))
+ {
+ RINOK(StringToDictSize(value, prop.Value));
+ }
+ else
+ {
+ NCOM::CPropVariant propValue;
+ if (nameToPropID.VarType == VT_BSTR)
+ propValue = value;
+ else if (nameToPropID.VarType == VT_BOOL)
+ {
+ bool res;
+ if (!StringToBool(value, res))
+ return E_INVALIDARG;
+ propValue = res;
+ }
+ else if (!value.IsEmpty())
+ {
+ if (nameToPropID.VarType == VT_UI4)
+ {
+ UInt32 number;
+ if (ParseStringToUInt32(value, number) == value.Len())
+ propValue = number;
+ else
+ propValue = value;
+ }
+ else if (nameToPropID.VarType == VT_UI8)
+ {
+ UInt64 number;
+ if (ParseStringToUInt64(value, number) == value.Len())
+ propValue = number;
+ else
+ propValue = value;
+ }
+ else
+ propValue = value;
+ }
+ if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))
+ return E_INVALIDARG;
+ }
+ Props.Add(prop);
+ return S_OK;
+}
+
+HRESULT CMethodProps::ParseParamsFromString(const UString &srcString)
+{
+ UStringVector params;
+ SplitParams(srcString, params);
+ FOR_VECTOR (i, params)
+ {
+ const UString &param = params[i];
+ UString name, value;
+ SplitParam(param, name, value);
+ RINOK(SetParam(name, value));
+ }
+ return S_OK;
+}
+
+HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
+{
+ if (realName.Len() == 0)
+ {
+ // [empty]=method
+ return E_INVALIDARG;
+ }
+ if (value.vt == VT_EMPTY)
+ {
+ // {realName}=[empty]
+ UString name, valueStr;
+ SplitParam(realName, name, valueStr);
+ return SetParam(name, valueStr);
+ }
+
+ // {realName}=value
+ int index = FindPropIdExact(realName);
+ if (index < 0)
+ return E_INVALIDARG;
+ const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
+ CProp prop;
+ prop.Id = index;
+
+ if (IsLogSizeProp(prop.Id))
+ {
+ RINOK(PROPVARIANT_to_DictSize(value, prop.Value));
+ }
+ else
+ {
+ if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))
+ return E_INVALIDARG;
+ }
+ Props.Add(prop);
+ return S_OK;
+}
+
+HRESULT COneMethodInfo::ParseMethodFromString(const UString &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;
+ PropsString = s.Ptr(splitPos + 1);
+ return ParseParamsFromString(PropsString);
+}
+
+HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
+{
+ if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m"))
+ return ParseParamsFromPROPVARIANT(realName, value);
+ // -m{N}=method
+ if (value.vt != VT_BSTR)
+ return E_INVALIDARG;
+ UString s;
+ s = value.bstrVal;
+ return ParseMethodFromString(s);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.h b/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.h
new file mode 100644
index 0000000000..c8a3d0dc3a
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.h
@@ -0,0 +1,264 @@
+// MethodProps.h
+
+#ifndef __7Z_METHOD_PROPS_H
+#define __7Z_METHOD_PROPS_H
+
+#include "../../Common/MyString.h"
+#include "../../Common/Defs.h"
+
+#include "../../Windows/Defs.h"
+
+#include "../../Windows/PropVariant.h"
+
+#include "../ICoder.h"
+
+bool StringToBool(const wchar_t *s, bool &res);
+HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);
+unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);
+HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
+
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
+
+struct CProp
+{
+ PROPID Id;
+ bool IsOptional;
+ NWindows::NCOM::CPropVariant Value;
+ CProp(): IsOptional(false) {}
+};
+
+struct CProps
+{
+ CObjectVector<CProp> Props;
+
+ void Clear() { Props.Clear(); }
+
+ bool AreThereNonOptionalProps() const
+ {
+ FOR_VECTOR (i, Props)
+ if (!Props[i].IsOptional)
+ return true;
+ return false;
+ }
+
+ void AddProp32(PROPID propid, UInt32 val);
+
+ void AddPropBool(PROPID propid, bool val);
+
+ void AddProp_Ascii(PROPID propid, const char *s)
+ {
+ CProp &prop = Props.AddNew();
+ prop.IsOptional = true;
+ prop.Id = propid;
+ prop.Value = s;
+ }
+
+ HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const;
+};
+
+class CMethodProps: public CProps
+{
+ HRESULT SetParam(const UString &name, const UString &value);
+public:
+ int GetLevel() const;
+ int Get_NumThreads() const
+ {
+ int i = FindProp(NCoderPropID::kNumThreads);
+ if (i >= 0)
+ if (Props[i].Value.vt == VT_UI4)
+ return (int)Props[i].Value.ulVal;
+ return -1;
+ }
+
+ bool Get_DicSize(UInt32 &res) const
+ {
+ res = 0;
+ int i = FindProp(NCoderPropID::kDictionarySize);
+ if (i >= 0)
+ if (Props[i].Value.vt == VT_UI4)
+ {
+ res = Props[i].Value.ulVal;
+ return true;
+ }
+ return false;
+ }
+
+ int FindProp(PROPID id) const;
+
+ UInt32 Get_Lzma_Algo() const
+ {
+ int i = FindProp(NCoderPropID::kAlgorithm);
+ if (i >= 0)
+ if (Props[i].Value.vt == VT_UI4)
+ return Props[i].Value.ulVal;
+ return GetLevel() >= 5 ? 1 : 0;
+ }
+
+ UInt32 Get_Lzma_DicSize() const
+ {
+ int i = FindProp(NCoderPropID::kDictionarySize);
+ if (i >= 0)
+ if (Props[i].Value.vt == VT_UI4)
+ return Props[i].Value.ulVal;
+ int level = GetLevel();
+ return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26));
+ }
+
+ bool Get_Lzma_Eos() const
+ {
+ int i = FindProp(NCoderPropID::kEndMarker);
+ if (i >= 0)
+ {
+ const NWindows::NCOM::CPropVariant &val = Props[i].Value;
+ if (val.vt == VT_BOOL)
+ return VARIANT_BOOLToBool(val.boolVal);
+ }
+ return false;
+ }
+
+ 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() const
+ {
+ if (Get_Lzma_Algo() == 0)
+ return 1;
+ int numThreads = Get_NumThreads();
+ if (numThreads >= 0)
+ return numThreads < 2 ? 1 : 2;
+ return 2;
+ }
+
+ int Get_Xz_NumThreads(UInt32 &lzmaThreads) const
+ {
+ lzmaThreads = 1;
+ int numThreads = Get_NumThreads();
+ if (numThreads >= 0 && numThreads <= 1)
+ return 1;
+ if (Get_Lzma_Algo() != 0)
+ lzmaThreads = 2;
+ return numThreads;
+ }
+
+ UInt64 GetProp_BlockSize(PROPID id) const
+ {
+ int i = FindProp(id);
+ if (i >= 0)
+ {
+ const NWindows::NCOM::CPropVariant &val = Props[i].Value;
+ if (val.vt == VT_UI4) { return val.ulVal; }
+ if (val.vt == VT_UI8) { return val.uhVal.QuadPart; }
+ }
+ return 0;
+ }
+
+ UInt64 Get_Xz_BlockSize() const
+ {
+ {
+ UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize);
+ UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2);
+ UInt64 minSize = MyMin(blockSize1, blockSize2);
+ if (minSize != 0)
+ return minSize;
+ UInt64 maxSize = MyMax(blockSize1, blockSize2);
+ if (maxSize != 0)
+ return maxSize;
+ }
+ const UInt32 kMinSize = (UInt32)1 << 20;
+ const UInt32 kMaxSize = (UInt32)1 << 28;
+ UInt32 dictSize = Get_Lzma_DicSize();
+ UInt64 blockSize = (UInt64)dictSize << 2;
+ if (blockSize < kMinSize) blockSize = kMinSize;
+ if (blockSize > kMaxSize) blockSize = kMaxSize;
+ if (blockSize < dictSize) blockSize = dictSize;
+ blockSize += (kMinSize - 1);
+ blockSize &= ~(UInt64)(kMinSize - 1);
+ return blockSize;
+ }
+
+
+ UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const
+ {
+ fixedNumber = false;
+ int numThreads = Get_NumThreads();
+ if (numThreads >= 0)
+ {
+ fixedNumber = true;
+ if (numThreads < 1) return 1;
+ const unsigned kNumBZip2ThreadsMax = 64;
+ if (numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax;
+ return numThreads;
+ }
+ return 1;
+ }
+
+ UInt32 Get_BZip2_BlockSize() const
+ {
+ int i = FindProp(NCoderPropID::kDictionarySize);
+ if (i >= 0)
+ if (Props[i].Value.vt == VT_UI4)
+ {
+ UInt32 blockSize = Props[i].Value.ulVal;
+ const UInt32 kDicSizeMin = 100000;
+ const UInt32 kDicSizeMax = 900000;
+ if (blockSize < kDicSizeMin) blockSize = kDicSizeMin;
+ if (blockSize > kDicSizeMax) blockSize = kDicSizeMax;
+ return blockSize;
+ }
+ int level = GetLevel();
+ return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));
+ }
+
+ UInt32 Get_Ppmd_MemSize() const
+ {
+ int i = FindProp(NCoderPropID::kUsedMemorySize);
+ if (i >= 0)
+ if (Props[i].Value.vt == VT_UI4)
+ return Props[i].Value.ulVal;
+ int level = GetLevel();
+ return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19));
+ }
+
+ void AddProp_Level(UInt32 level)
+ {
+ AddProp32(NCoderPropID::kLevel, level);
+ }
+
+ void AddProp_NumThreads(UInt32 numThreads)
+ {
+ AddProp32(NCoderPropID::kNumThreads, numThreads);
+ }
+
+ void AddProp_EndMarker_if_NotFound(bool eos)
+ {
+ if (FindProp(NCoderPropID::kEndMarker) < 0)
+ AddPropBool(NCoderPropID::kEndMarker, eos);
+ }
+
+ HRESULT ParseParamsFromString(const UString &srcString);
+ HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
+};
+
+class COneMethodInfo: public CMethodProps
+{
+public:
+ 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);
+ HRESULT ParseMethodFromString(const UString &s);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.cpp
new file mode 100644
index 0000000000..3b01c7f651
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.cpp
@@ -0,0 +1,39 @@
+// OffsetStream.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/Defs.h"
+
+#include "OffsetStream.h"
+
+HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)
+{
+ _offset = offset;
+ _stream = stream;
+ return _stream->Seek(offset, STREAM_SEEK_SET, NULL);
+}
+
+STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ return _stream->Write(data, size, processedSize);
+}
+
+STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ UInt64 absoluteNewPosition;
+ if (seekOrigin == STREAM_SEEK_SET)
+ {
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ offset += _offset;
+ }
+ HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);
+ if (newPosition)
+ *newPosition = absoluteNewPosition - _offset;
+ return result;
+}
+
+STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize)
+{
+ return _stream->SetSize(_offset + newSize);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.h b/other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.h
new file mode 100644
index 0000000000..ad835f2dfc
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.h
@@ -0,0 +1,26 @@
+// OffsetStream.h
+
+#ifndef __OFFSET_STREAM_H
+#define __OFFSET_STREAM_H
+
+#include "../../Common/MyCom.h"
+
+#include "../IStream.h"
+
+class COffsetOutStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+ UInt64 _offset;
+ CMyComPtr<IOutStream> _stream;
+public:
+ HRESULT Init(IOutStream *stream, UInt64 offset);
+
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+ STDMETHOD(SetSize)(UInt64 newSize);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.cpp
new file mode 100644
index 0000000000..fb8dc8d16d
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.cpp
@@ -0,0 +1,111 @@
+// OutBuffer.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "OutBuffer.h"
+
+bool COutBuffer::Create(UInt32 bufSize) throw()
+{
+ const UInt32 kMinBlockSize = 1;
+ if (bufSize < kMinBlockSize)
+ bufSize = kMinBlockSize;
+ if (_buf != 0 && _bufSize == bufSize)
+ return true;
+ Free();
+ _bufSize = bufSize;
+ _buf = (Byte *)::MidAlloc(bufSize);
+ return (_buf != 0);
+}
+
+void COutBuffer::Free() throw()
+{
+ ::MidFree(_buf);
+ _buf = 0;
+}
+
+void COutBuffer::Init() throw()
+{
+ _streamPos = 0;
+ _limitPos = _bufSize;
+ _pos = 0;
+ _processedSize = 0;
+ _overDict = false;
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = S_OK;
+ #endif
+}
+
+UInt64 COutBuffer::GetProcessedSize() const throw()
+{
+ UInt64 res = _processedSize + _pos - _streamPos;
+ if (_streamPos > _pos)
+ res += _bufSize;
+ return res;
+}
+
+
+HRESULT COutBuffer::FlushPart() throw()
+{
+ // _streamPos < _bufSize
+ UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos);
+ HRESULT result = S_OK;
+ #ifdef _NO_EXCEPTIONS
+ result = ErrorCode;
+ #endif
+ if (_buf2 != 0)
+ {
+ memcpy(_buf2, _buf + _streamPos, size);
+ _buf2 += size;
+ }
+
+ if (_stream != 0
+ #ifdef _NO_EXCEPTIONS
+ && (ErrorCode == S_OK)
+ #endif
+ )
+ {
+ UInt32 processedSize = 0;
+ result = _stream->Write(_buf + _streamPos, size, &processedSize);
+ size = processedSize;
+ }
+ _streamPos += size;
+ if (_streamPos == _bufSize)
+ _streamPos = 0;
+ if (_pos == _bufSize)
+ {
+ _overDict = true;
+ _pos = 0;
+ }
+ _limitPos = (_streamPos > _pos) ? _streamPos : _bufSize;
+ _processedSize += size;
+ return result;
+}
+
+HRESULT COutBuffer::Flush() throw()
+{
+ #ifdef _NO_EXCEPTIONS
+ if (ErrorCode != S_OK)
+ return ErrorCode;
+ #endif
+
+ while (_streamPos != _pos)
+ {
+ HRESULT result = FlushPart();
+ if (result != S_OK)
+ return result;
+ }
+ return S_OK;
+}
+
+void COutBuffer::FlushWithCheck()
+{
+ HRESULT result = Flush();
+ #ifdef _NO_EXCEPTIONS
+ ErrorCode = result;
+ #else
+ if (result != S_OK)
+ throw COutBufferException(result);
+ #endif
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.h b/other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.h
new file mode 100644
index 0000000000..2ffb5cd323
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.h
@@ -0,0 +1,66 @@
+// OutBuffer.h
+
+#ifndef __OUT_BUFFER_H
+#define __OUT_BUFFER_H
+
+#include "../IStream.h"
+#include "../../Common/MyCom.h"
+#include "../../Common/MyException.h"
+
+#ifndef _NO_EXCEPTIONS
+struct COutBufferException: public CSystemException
+{
+ COutBufferException(HRESULT errorCode): CSystemException(errorCode) {}
+};
+#endif
+
+class COutBuffer
+{
+protected:
+ Byte *_buf;
+ UInt32 _pos;
+ UInt32 _limitPos;
+ UInt32 _streamPos;
+ UInt32 _bufSize;
+ ISequentialOutStream *_stream;
+ UInt64 _processedSize;
+ Byte *_buf2;
+ bool _overDict;
+
+ HRESULT FlushPart() throw();
+public:
+ #ifdef _NO_EXCEPTIONS
+ HRESULT ErrorCode;
+ #endif
+
+ COutBuffer(): _buf(0), _pos(0), _stream(0), _buf2(0) {}
+ ~COutBuffer() { Free(); }
+
+ bool Create(UInt32 bufSize) throw();
+ void Free() throw();
+
+ void SetMemStream(Byte *buf) { _buf2 = buf; }
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void Init() throw();
+ HRESULT Flush() throw();
+ void FlushWithCheck();
+
+ void WriteByte(Byte b)
+ {
+ UInt32 pos = _pos;
+ _buf[pos] = b;
+ pos++;
+ _pos = pos;
+ if (pos == _limitPos)
+ FlushWithCheck();
+ }
+ void WriteBytes(const void *data, size_t size)
+ {
+ for (size_t i = 0; i < size; i++)
+ WriteByte(((const Byte *)data)[i]);
+ }
+
+ UInt64 GetProcessedSize() const throw();
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.cpp
new file mode 100644
index 0000000000..86f1e78268
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.cpp
@@ -0,0 +1,51 @@
+// ProgressUtils.cpp
+
+#include "StdAfx.h"
+
+#include "ProgressUtils.h"
+
+CLocalProgress::CLocalProgress():
+ ProgressOffset(0),
+ InSize(0),
+ OutSize(0),
+ SendRatio(true),
+ SendProgress(true)
+ {}
+
+void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
+{
+ _ratioProgress.Release();
+ _progress = progress;
+ _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress);
+ _inSizeIsMain = inSizeIsMain;
+}
+
+STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ UInt64 inSize2 = InSize;
+ UInt64 outSize2 = OutSize;
+
+ if (inSize)
+ inSize2 += (*inSize);
+ if (outSize)
+ outSize2 += (*outSize);
+
+ if (SendRatio && _ratioProgress)
+ {
+ RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2));
+ }
+
+ if (SendProgress)
+ {
+ inSize2 += ProgressOffset;
+ outSize2 += ProgressOffset;
+ return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2);
+ }
+
+ return S_OK;
+}
+
+HRESULT CLocalProgress::SetCur()
+{
+ return SetRatioInfo(NULL, NULL);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.h b/other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.h
new file mode 100644
index 0000000000..176e8bb438
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.h
@@ -0,0 +1,35 @@
+// ProgressUtils.h
+
+#ifndef __PROGRESS_UTILS_H
+#define __PROGRESS_UTILS_H
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+#include "../IProgress.h"
+
+class CLocalProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+ CMyComPtr<IProgress> _progress;
+ CMyComPtr<ICompressProgressInfo> _ratioProgress;
+ bool _inSizeIsMain;
+public:
+ UInt64 ProgressOffset;
+ UInt64 InSize;
+ UInt64 OutSize;
+ bool SendRatio;
+ bool SendProgress;
+
+ CLocalProgress();
+
+ void Init(IProgress *progress, bool inSizeIsMain);
+ HRESULT SetCur();
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/PropId.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/PropId.cpp
new file mode 100644
index 0000000000..96f8f0564f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/PropId.cpp
@@ -0,0 +1,108 @@
+// PropId.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/MyWindows.h"
+
+#include "../PropID.h"
+
+// VARTYPE
+const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
+{
+ VT_EMPTY,
+ VT_UI4,
+ VT_UI4,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BOOL,
+ VT_UI8,
+ VT_UI8,
+ VT_UI4,
+ VT_FILETIME,
+ VT_FILETIME,
+ VT_FILETIME,
+ VT_BOOL,
+ VT_BOOL,
+ VT_BOOL,
+ VT_BOOL,
+ VT_BOOL,
+ VT_UI4,
+ VT_UI4,
+ VT_BSTR,
+ VT_BOOL,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BSTR,
+ VT_UI8,
+ VT_BSTR,
+ VT_UI8,
+ VT_BSTR,
+ VT_UI8,
+ VT_UI8,
+ VT_BSTR, // or VT_UI8 kpidUnpackVer
+ VT_UI4, // or VT_UI8 kpidVolume
+ VT_BOOL,
+ VT_UI8,
+ VT_UI8,
+ VT_UI8,
+ VT_UI8,
+ VT_UI4,
+ VT_BOOL,
+ VT_BOOL,
+ VT_BSTR,
+ VT_UI8,
+ VT_UI8,
+ VT_UI4, // kpidChecksum
+ VT_BSTR,
+ VT_UI8,
+ VT_BSTR, // or VT_UI8 kpidId
+ VT_BSTR,
+ VT_BSTR,
+ VT_UI4,
+ VT_UI4,
+ VT_BSTR,
+ VT_BSTR,
+ VT_UI8,
+ VT_UI8,
+ VT_UI4,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BSTR, // kpidNtSecure
+ VT_BOOL,
+ VT_BOOL,
+ VT_BOOL,
+ VT_BOOL,
+ VT_BSTR, // SHA-1
+ VT_BSTR, // SHA-256
+ VT_BSTR,
+ VT_UI8,
+ VT_UI4,
+ VT_UI4,
+ VT_BSTR,
+ VT_UI8,
+ VT_UI8,
+ VT_UI8,
+ VT_UI8,
+ VT_UI8,
+ VT_UI8,
+ VT_UI8,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BSTR,
+ VT_BOOL,
+ VT_BOOL,
+ VT_BOOL,
+ VT_UI8,
+ VT_UI8,
+ VT_BSTR, // kpidNtReparse
+ VT_BSTR,
+ VT_UI8,
+ VT_UI8,
+ VT_BOOL,
+ VT_BSTR,
+ VT_BSTR
+};
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/RegisterArc.h b/other-licenses/7zstub/src/CPP/7zip/Common/RegisterArc.h
new file mode 100644
index 0000000000..08aa2d478e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/RegisterArc.h
@@ -0,0 +1,78 @@
+// RegisterArc.h
+
+#ifndef __REGISTER_ARC_H
+#define __REGISTER_ARC_H
+
+#include "../Archive/IArchive.h"
+
+struct CArcInfo
+{
+ UInt16 Flags;
+ Byte Id;
+ Byte SignatureSize;
+ UInt16 SignatureOffset;
+
+ const Byte *Signature;
+ const char *Name;
+ const char *Ext;
+ const char *AddExt;
+
+ Func_CreateInArchive CreateInArchive;
+ Func_CreateOutArchive CreateOutArchive;
+ Func_IsArc IsArc;
+
+ bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; }
+};
+
+void RegisterArc(const CArcInfo *arcInfo) throw();
+
+
+#define IMP_CreateArcIn_2(c) \
+ static IInArchive *CreateArc() { return new c; }
+
+#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler())
+
+#ifdef EXTRACT_ONLY
+ #define IMP_CreateArcOut
+ #define CreateArcOut NULL
+#else
+ #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/other-licenses/7zstub/src/CPP/7zip/Common/RegisterCodec.h b/other-licenses/7zstub/src/CPP/7zip/Common/RegisterCodec.h
new file mode 100644
index 0000000000..b5660658fd
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/RegisterCodec.h
@@ -0,0 +1,106 @@
+// RegisterCodec.h
+
+#ifndef __REGISTER_CODEC_H
+#define __REGISTER_CODEC_H
+
+#include "../Common/MethodId.h"
+
+#include "../ICoder.h"
+
+typedef void * (*CreateCodecP)();
+
+struct CCodecInfo
+{
+ CreateCodecP CreateDecoder;
+ CreateCodecP CreateEncoder;
+ CMethodId Id;
+ 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 char *Name;
+ UInt32 DigestSize;
+};
+
+void RegisterHasher(const CHasherInfo *hasher) throw();
+
+#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x
+
+#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/other-licenses/7zstub/src/CPP/7zip/Common/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Common/StdAfx.h
new file mode 100644
index 0000000000..42a088f121
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.cpp
new file mode 100644
index 0000000000..a6627db213
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.cpp
@@ -0,0 +1,156 @@
+// StreamBinder.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/MyCom.h"
+
+#include "StreamBinder.h"
+
+class CBinderInStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CStreamBinder *_binder;
+public:
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ ~CBinderInStream() { _binder->CloseRead(); }
+ CBinderInStream(CStreamBinder *binder): _binder(binder) {}
+};
+
+STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+ { return _binder->Read(data, size, processedSize); }
+
+class CBinderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CStreamBinder *_binder;
+public:
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ ~CBinderOutStream() { _binder->CloseWrite(); }
+ CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
+};
+
+STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+ { return _binder->Write(data, size, processedSize); }
+
+
+
+WRes CStreamBinder::CreateEvents()
+{
+ RINOK(_canWrite_Event.Create());
+ RINOK(_canRead_Event.Create());
+ return _readingWasClosed_Event.Create();
+}
+
+void CStreamBinder::ReInit()
+{
+ _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);
+ *inStream = inStreamLoc.Detach();
+
+ CBinderOutStream *outStreamSpec = new CBinderOutStream(this);
+ CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
+ *outStream = outStreamLoc.Detach();
+}
+
+// (_canRead_Event && _bufSize == 0) means that stream is finished.
+
+HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size != 0)
+ {
+ if (_waitWrite)
+ {
+ RINOK(_canRead_Event.Lock());
+ _waitWrite = false;
+ }
+ if (size > _bufSize)
+ size = _bufSize;
+ if (size != 0)
+ {
+ memcpy(data, _buf, size);
+ _buf = ((const Byte *)_buf) + size;
+ ProcessedSize += size;
+ if (processedSize)
+ *processedSize = size;
+ _bufSize -= size;
+ if (_bufSize == 0)
+ {
+ _waitWrite = true;
+ _canRead_Event.Reset();
+ _canWrite_Event.Set();
+ }
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+
+ if (!_readingWasClosed2)
+ {
+ _buf = data;
+ _bufSize = size;
+ _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 + 2)
+ return E_FAIL;
+
+ size -= _bufSize;
+ if (size != 0)
+ {
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+ }
+ // if (waitResult == WAIT_OBJECT_0 + 1)
+ _readingWasClosed2 = true;
+ }
+
+ // WritingWasCut = true;
+ return k_My_HRESULT_WritingWasCut;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.h b/other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.h
new file mode 100644
index 0000000000..f4d4f3b42c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.h
@@ -0,0 +1,60 @@
+// StreamBinder.h
+
+#ifndef __STREAM_BINDER_H
+#define __STREAM_BINDER_H
+
+#include "../../Windows/Synchronization.h"
+
+#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::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;
+public:
+ UInt64 ProcessedSize;
+
+ 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();
+ // _readingWasClosed = true;
+ // _canWrite_Event.Set();
+ }
+
+ void CloseWrite()
+ {
+ _buf = NULL;
+ _bufSize = 0;
+ _canRead_Event.Set();
+ }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.cpp
new file mode 100644
index 0000000000..4cd9cc65be
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.cpp
@@ -0,0 +1,285 @@
+// StreamObjects.cpp
+
+#include "StdAfx.h"
+
+#include <stdlib.h>
+
+#include "../../../C/Alloc.h"
+
+#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)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ if (_pos >= _size)
+ return S_OK;
+ size_t rem = _size - (size_t)_pos;
+ if (rem > size)
+ rem = (size_t)size;
+ memcpy(data, _data + (size_t)_pos, rem);
+ _pos += rem;
+ if (processedSize)
+ *processedSize = (UInt32)rem;
+ return S_OK;
+}
+
+STDMETHODIMP CBufInStream::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 += _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;
+}
+
+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, ref);
+ *stream = streamTemp.Detach();
+}
+
+void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream)
+{
+ *stream = NULL;
+ CBufferInStream *inStreamSpec = new CBufferInStream;
+ CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
+ inStreamSpec->Buf.CopyFrom((const Byte *)data, size);
+ inStreamSpec->Init();
+ *stream = streamTemp.Detach();
+}
+
+void CByteDynBuffer::Free() throw()
+{
+ free(_buf);
+ _buf = 0;
+ _capacity = 0;
+}
+
+bool CByteDynBuffer::EnsureCapacity(size_t cap) throw()
+{
+ if (cap <= _capacity)
+ return true;
+ size_t delta;
+ if (_capacity > 64)
+ delta = _capacity / 4;
+ else if (_capacity > 8)
+ delta = 16;
+ else
+ delta = 4;
+ cap = MyMax(_capacity + delta, cap);
+ Byte *buf = (Byte *)realloc(_buf, cap);
+ if (!buf)
+ return false;
+ _buf = buf;
+ _capacity = cap;
+ return true;
+}
+
+Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)
+{
+ addSize += _size;
+ if (addSize < _size)
+ return NULL;
+ if (!_buffer.EnsureCapacity(addSize))
+ return NULL;
+ return (Byte *)_buffer + _size;
+}
+
+void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
+{
+ dest.CopyFrom((const Byte *)_buffer, _size);
+}
+
+STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ Byte *buf = GetBufPtrForWriting(size);
+ if (!buf)
+ return E_OUTOFMEMORY;
+ memcpy(buf, data, size);
+ UpdateSize(size);
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+}
+
+STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ size_t rem = _size - _pos;
+ if (rem > size)
+ rem = (size_t)size;
+ if (rem != 0)
+ {
+ memcpy(_buffer + _pos, data, rem);
+ _pos += rem;
+ }
+ if (processedSize)
+ *processedSize = (UInt32)rem;
+ return (rem != 0 || size == 0) ? S_OK : E_FAIL;
+}
+
+STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Write(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return result;
+}
+
+static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
+
+void CCachedInStream::Free() throw()
+{
+ MyFree(_tags);
+ _tags = 0;
+ MidFree(_data);
+ _data = 0;
+}
+
+bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw()
+{
+ unsigned sizeLog = blockSizeLog + numBlocksLog;
+ if (sizeLog >= sizeof(size_t) * 8)
+ return false;
+ size_t dataSize = (size_t)1 << sizeLog;
+ if (_data == 0 || dataSize != _dataSize)
+ {
+ MidFree(_data);
+ _data = (Byte *)MidAlloc(dataSize);
+ if (_data == 0)
+ return false;
+ _dataSize = dataSize;
+ }
+ if (_tags == 0 || numBlocksLog != _numBlocksLog)
+ {
+ MyFree(_tags);
+ _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);
+ if (_tags == 0)
+ return false;
+ _numBlocksLog = numBlocksLog;
+ }
+ _blockSizeLog = blockSizeLog;
+ return true;
+}
+
+void CCachedInStream::Init(UInt64 size) throw()
+{
+ _size = size;
+ _pos = 0;
+ size_t numBlocks = (size_t)1 << _numBlocksLog;
+ for (size_t i = 0; i < numBlocks; i++)
+ _tags[i] = kEmptyTag;
+}
+
+STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ if (_pos >= _size)
+ return S_OK;
+
+ {
+ UInt64 rem = _size - _pos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+
+ while (size != 0)
+ {
+ UInt64 cacheTag = _pos >> _blockSizeLog;
+ size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);
+ Byte *p = _data + (cacheIndex << _blockSizeLog);
+ if (_tags[cacheIndex] != cacheTag)
+ {
+ UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
+ size_t blockSize = (size_t)1 << _blockSizeLog;
+ if (blockSize > remInBlock)
+ blockSize = (size_t)remInBlock;
+ RINOK(ReadBlock(cacheTag, p, blockSize));
+ _tags[cacheIndex] = cacheTag;
+ }
+ size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1);
+ UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size);
+ memcpy(data, p + offset, cur);
+ if (processedSize)
+ *processedSize += cur;
+ data = (void *)((const Byte *)data + cur);
+ _pos += cur;
+ size -= cur;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CCachedInStream::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 += _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;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.h b/other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.h
new file mode 100644
index 0000000000..c3e083747f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.h
@@ -0,0 +1,157 @@
+// StreamObjects.h
+
+#ifndef __STREAM_OBJECTS_H
+#define __STREAM_OBJECTS_H
+
+#include "../../Common/MyBuffer.h"
+#include "../../Common/MyCom.h"
+#include "../../Common/MyVector.h"
+
+#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
+{
+ CByteBuffer Buf;
+ MY_UNKNOWN_IMP
+};
+
+class CBufInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ const Byte *_data;
+ UInt64 _pos;
+ size_t _size;
+ CMyComPtr<IUnknown> _ref;
+public:
+ void Init(const Byte *data, size_t size, IUnknown *ref = 0)
+ {
+ _data = data;
+ _size = size;
+ _pos = 0;
+ _ref = ref;
+ }
+ void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); }
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+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
+{
+ size_t _capacity;
+ Byte *_buf;
+public:
+ CByteDynBuffer(): _capacity(0), _buf(0) {};
+ // there is no copy constructor. So don't copy this object.
+ ~CByteDynBuffer() { Free(); }
+ void Free() throw();
+ size_t GetCapacity() const { return _capacity; }
+ operator Byte*() const { return _buf; }
+ operator const Byte*() const { return _buf; }
+ bool EnsureCapacity(size_t capacity) throw();
+};
+
+class CDynBufSeqOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CByteDynBuffer _buffer;
+ size_t _size;
+public:
+ CDynBufSeqOutStream(): _size(0) {}
+ void Init() { _size = 0; }
+ size_t GetSize() const { return _size; }
+ const Byte *GetBuffer() const { return _buffer; }
+ void CopyToBuffer(CByteBuffer &dest) const;
+ Byte *GetBufPtrForWriting(size_t addSize);
+ void UpdateSize(size_t addSize) { _size += addSize; }
+
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+class CBufPtrSeqOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ Byte *_buffer;
+ size_t _size;
+ size_t _pos;
+public:
+ void Init(Byte *buffer, size_t size)
+ {
+ _buffer = buffer;
+ _pos = 0;
+ _size = size;
+ }
+ size_t GetPos() const { return _pos; }
+
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+class CSequentialOutStreamSizeCount:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+public:
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void Init() { _size = 0; }
+ UInt64 GetSize() const { return _size; }
+
+ MY_UNKNOWN_IMP1(ISequentialOutStream)
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+class CCachedInStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ UInt64 *_tags;
+ Byte *_data;
+ size_t _dataSize;
+ unsigned _blockSizeLog;
+ unsigned _numBlocksLog;
+ UInt64 _size;
+ UInt64 _pos;
+protected:
+ virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0;
+public:
+ CCachedInStream(): _tags(0), _data(0) {}
+ virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!!
+ void Free() throw();
+ bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw();
+ void Init(UInt64 size) throw();
+
+ MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.cpp
new file mode 100644
index 0000000000..a79de23525
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.cpp
@@ -0,0 +1,56 @@
+// StreamUtils.cpp
+
+#include "StdAfx.h"
+
+#include "StreamUtils.h"
+
+static const UInt32 kBlockSize = ((UInt32)1 << 31);
+
+HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw()
+{
+ size_t size = *processedSize;
+ *processedSize = 0;
+ while (size != 0)
+ {
+ UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;
+ UInt32 processedSizeLoc;
+ HRESULT res = stream->Read(data, curSize, &processedSizeLoc);
+ *processedSize += processedSizeLoc;
+ data = (void *)((Byte *)data + processedSizeLoc);
+ size -= processedSizeLoc;
+ RINOK(res);
+ if (processedSizeLoc == 0)
+ return S_OK;
+ }
+ return S_OK;
+}
+
+HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw()
+{
+ size_t processedSize = size;
+ RINOK(ReadStream(stream, data, &processedSize));
+ return (size == processedSize) ? S_OK : S_FALSE;
+}
+
+HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw()
+{
+ size_t processedSize = size;
+ RINOK(ReadStream(stream, data, &processedSize));
+ return (size == processedSize) ? S_OK : E_FAIL;
+}
+
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw()
+{
+ while (size != 0)
+ {
+ UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;
+ UInt32 processedSizeLoc;
+ HRESULT res = stream->Write(data, curSize, &processedSizeLoc);
+ data = (const void *)((const Byte *)data + processedSizeLoc);
+ size -= processedSizeLoc;
+ RINOK(res);
+ if (processedSizeLoc == 0)
+ return E_FAIL;
+ }
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.h b/other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.h
new file mode 100644
index 0000000000..799a8b9db1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.h
@@ -0,0 +1,13 @@
+// StreamUtils.h
+
+#ifndef __STREAM_UTILS_H
+#define __STREAM_UTILS_H
+
+#include "../IStream.h"
+
+HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw();
+HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw();
+HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw();
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw();
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.cpp
new file mode 100644
index 0000000000..5baf1a4953
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.cpp
@@ -0,0 +1,57 @@
+// UniqBlocks.cpp
+
+#include "StdAfx.h"
+
+#include <string.h>
+
+#include "UniqBlocks.h"
+
+unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
+{
+ unsigned left = 0, right = Sorted.Size();
+ while (left != right)
+ {
+ unsigned mid = (left + right) / 2;
+ unsigned index = Sorted[mid];
+ const CByteBuffer &buf = Bufs[index];
+ size_t sizeMid = buf.Size();
+ if (size < sizeMid)
+ right = mid;
+ else if (size > sizeMid)
+ left = mid + 1;
+ else
+ {
+ if (size == 0)
+ return index;
+ int cmp = memcmp(data, buf, size);
+ if (cmp == 0)
+ return index;
+ if (cmp < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ }
+ unsigned index = Bufs.Size();
+ Sorted.Insert(left, index);
+ Bufs.AddNew().CopyFrom(data, size);
+ return index;
+}
+
+UInt64 CUniqBlocks::GetTotalSizeInBytes() const
+{
+ UInt64 size = 0;
+ FOR_VECTOR (i, Bufs)
+ size += Bufs[i].Size();
+ return size;
+}
+
+void CUniqBlocks::GetReverseMap()
+{
+ unsigned num = Sorted.Size();
+ BufIndexToSortedIndex.ClearAndSetSize(num);
+ unsigned *p = &BufIndexToSortedIndex[0];
+ const unsigned *sorted = &Sorted[0];
+ for (unsigned i = 0; i < num; i++)
+ p[sorted[i]] = i;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.h b/other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.h
new file mode 100644
index 0000000000..d9ec17da11
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.h
@@ -0,0 +1,26 @@
+// UniqBlocks.h
+
+#ifndef __UNIQ_BLOCKS_H
+#define __UNIQ_BLOCKS_H
+
+#include "../../Common/MyTypes.h"
+#include "../../Common/MyBuffer.h"
+#include "../../Common/MyVector.h"
+
+struct CUniqBlocks
+{
+ CObjectVector<CByteBuffer> Bufs;
+ CUIntVector Sorted;
+ CUIntVector BufIndexToSortedIndex;
+
+ unsigned AddUniq(const Byte *data, size_t size);
+ UInt64 GetTotalSizeInBytes() const;
+ void GetReverseMap();
+
+ bool IsOnlyEmpty() const
+ {
+ return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0);
+ }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.cpp
new file mode 100644
index 0000000000..3cf9acd3ea
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.cpp
@@ -0,0 +1,48 @@
+// VirtThread.cpp
+
+#include "StdAfx.h"
+
+#include "VirtThread.h"
+
+static THREAD_FUNC_DECL CoderThread(void *p)
+{
+ for (;;)
+ {
+ CVirtThread *t = (CVirtThread *)p;
+ t->StartEvent.Lock();
+ if (t->Exit)
+ return 0;
+ t->Execute();
+ t->FinishedEvent.Set();
+ }
+}
+
+WRes CVirtThread::Create()
+{
+ RINOK(StartEvent.CreateIfNotCreated());
+ RINOK(FinishedEvent.CreateIfNotCreated());
+ StartEvent.Reset();
+ FinishedEvent.Reset();
+ Exit = false;
+ if (Thread.IsCreated())
+ return S_OK;
+ return Thread.Create(CoderThread, this);
+}
+
+void CVirtThread::Start()
+{
+ Exit = false;
+ StartEvent.Set();
+}
+
+void CVirtThread::WaitThreadFinish()
+{
+ Exit = true;
+ if (StartEvent.IsCreated())
+ StartEvent.Set();
+ if (Thread.IsCreated())
+ {
+ Thread.Wait();
+ Thread.Close();
+ }
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.h b/other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.h
new file mode 100644
index 0000000000..a2711036ad
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.h
@@ -0,0 +1,24 @@
+// VirtThread.h
+
+#ifndef __VIRT_THREAD_H
+#define __VIRT_THREAD_H
+
+#include "../../Windows/Synchronization.h"
+#include "../../Windows/Thread.h"
+
+struct CVirtThread
+{
+ NWindows::NSynchronization::CAutoResetEvent StartEvent;
+ NWindows::NSynchronization::CAutoResetEvent FinishedEvent;
+ NWindows::CThread Thread;
+ bool Exit;
+
+ ~CVirtThread() { WaitThreadFinish(); }
+ void WaitThreadFinish(); // call it in destructor of child class !
+ WRes Create();
+ void Start();
+ virtual void Execute() = 0;
+ void WaitExecuteFinish() { FinishedEvent.Lock(); }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.cpp
new file mode 100644
index 0000000000..4e083bf194
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.cpp
@@ -0,0 +1,666 @@
+// Bcj2Coder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../Common/StreamUtils.h"
+
+#include "Bcj2Coder.h"
+
+namespace NCompress {
+namespace NBcj2 {
+
+CBaseCoder::CBaseCoder()
+{
+ for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++)
+ {
+ _bufs[i] = NULL;
+ _bufsCurSizes[i] = 0;
+ _bufsNewSizes[i] = (1 << 18);
+ }
+}
+
+CBaseCoder::~CBaseCoder()
+{
+ for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++)
+ ::MidFree(_bufs[i]);
+}
+
+HRESULT CBaseCoder::Alloc(bool allocForOrig)
+{
+ 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;
+}
+
+
+
+#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)
+{
+ 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 * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
+ ISequentialOutStream * const *outStreams, const UInt64 * const * /* outSizes */, UInt32 numOutStreams,
+ ICompressProgressInfo *progress)
+{
+ if (numInStreams != 1 || numOutStreams != BCJ2_NUM_STREAMS)
+ return E_INVALIDARG;
+
+ RINOK(Alloc());
+
+ UInt32 fileSize_for_Conv = 0;
+ if (inSizes && inSizes[0])
+ {
+ UInt64 inSize = *inSizes[0];
+ if (inSize <= BCJ2_FileSize_MAX)
+ fileSize_for_Conv = (UInt32)inSize;
+ }
+
+ 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++)
+ {
+ enc.bufs[i] = _bufs[i];
+ enc.lims[i] = _bufs[i] + _bufsCurSizes[i];
+ }
+ }
+
+ 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;
+
+ Bcj2Enc_Init(&enc);
+
+ enc.fileIp = 0;
+ enc.fileSize = fileSize_for_Conv;
+
+ enc.relatLimit = _relatLim;
+
+ enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
+
+ bool needSubSize = false;
+ UInt64 subStreamIndex = 0;
+ UInt64 subStreamStartPos = 0;
+ bool readWasFinished = false;
+
+ for (;;)
+ {
+ if (needSubSize && getSubStreamSize)
+ {
+ enc.fileIp = 0;
+ enc.fileSize = fileSize_for_Conv;
+ enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;
+
+ for (;;)
+ {
+ UInt64 subStreamSize = 0;
+ HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
+ needSubSize = false;
+
+ if (result == S_OK)
+ {
+ UInt64 newEndPos = subStreamStartPos + subStreamSize;
+
+ bool isAccurateEnd = (newEndPos < totalStreamRead ||
+ (newEndPos <= totalStreamRead && readWasFinished));
+
+ if (newEndPos <= currentInPos && isAccurateEnd)
+ {
+ subStreamStartPos = newEndPos;
+ subStreamIndex++;
+ continue;
+ }
+
+ enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;
+
+ if (isAccurateEnd)
+ {
+ // 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;
+ }
+
+ if (subStreamSize <= BCJ2_FileSize_MAX)
+ {
+ enc.fileIp = enc.ip + (UInt32)(subStreamStartPos - currentInPos);
+ enc.fileSize = (UInt32)subStreamSize;
+ }
+ break;
+ }
+
+ if (result == S_FALSE)
+ break;
+ if (result == E_NOTIMPL)
+ {
+ getSubStreamSize.Release();
+ break;
+ }
+ return result;
+ }
+ }
+
+ 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]))
+ {
+ enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;
+ continue;
+ }
+
+ 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)
+ {
+ readWasFinished = true;
+ continue;
+ }
+
+ numBytes_in_ReadBuf = curSize;
+ totalStreamRead += numBytes_in_ReadBuf;
+ enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf;
+ }
+
+ if (progress && currentInPos - prevProgress >= (1 << 20))
+ {
+ 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));
+ }
+ }
+
+ 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 * 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(...) { return E_FAIL; }
+}
+
+#endif
+
+
+
+
+
+
+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)
+{
+ _finishMode = (finishMode != 0);
+ return S_OK;
+}
+
+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 != BCJ2_NUM_STREAMS || numOutStreams != 1)
+ return E_INVALIDARG;
+
+ RINOK(Alloc());
+
+ InitCommon();
+
+ dec.destLim = dec.dest = _bufs[BCJ2_NUM_STREAMS];
+
+ UInt64 outSizeProcessed = 0;
+ UInt64 prevProgress = 0;
+
+ HRESULT res = S_OK;
+
+ for (;;)
+ {
+ if (Bcj2Dec_Decode(&dec) != SZ_OK)
+ return S_FALSE;
+
+ if (dec.state < BCJ2_NUM_STREAMS)
+ {
+ 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;
+ }
+ else // if (dec.state <= BCJ2_STATE_ORIG)
+ {
+ 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;
+ }
+ }
+
+ if (progress)
+ {
+ const UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]);
+ if (outSize2 - prevProgress >= (1 << 22))
+ {
+ const 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;
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream)
+{
+ _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)
+ {
+ 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;
+ */
+ }
+
+ return res;
+}
+
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value)
+{
+ const size_t rem = dec.lims[streamIndex] - dec.bufs[streamIndex] + _extraReadSizes[streamIndex];
+ *value = _inStreamsProcessed[streamIndex] - rem;
+ return S_OK;
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.h
new file mode 100644
index 0000000000..666bf8c4cd
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.h
@@ -0,0 +1,120 @@
+// Bcj2Coder.h
+
+#ifndef __COMPRESS_BCJ2_CODER_H
+#define __COMPRESS_BCJ2_CODER_H
+
+#include "../../../C/Bcj2.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NBcj2 {
+
+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 ICompressSetCoderProperties,
+ public ICompressSetBufSize,
+ public CMyUnknownImp,
+ public CBaseCoder
+{
+ UInt32 _relatLim;
+
+ 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_IMP3(ICompressCoder2, ICompressSetCoderProperties, ICompressSetBufSize)
+
+ 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);
+
+ STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
+ STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
+
+ CEncoder();
+ ~CEncoder();
+};
+
+#endif
+
+class CDecoder:
+ public ICompressCoder2,
+ public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize2,
+ public ICompressSetInStream2,
+ public ISequentialInStream,
+ public ICompressSetOutStreamSize,
+ public ICompressSetBufSize,
+ public CMyUnknownImp,
+ public CBaseCoder
+{
+ 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_IMP7(
+ ICompressCoder2,
+ ICompressSetFinishMode,
+ ICompressGetInStreamProcessedSize2,
+ ICompressSetInStream2,
+ ISequentialInStream,
+ ICompressSetOutStreamSize,
+ ICompressSetBufSize
+ );
+
+ 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(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value);
+
+ 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);
+
+ CDecoder();
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Register.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Register.cpp
new file mode 100644
index 0000000000..bce617892f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Register.cpp
@@ -0,0 +1,24 @@
+// Bcj2Register.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "Bcj2Coder.h"
+
+namespace NCompress {
+namespace NBcj2 {
+
+REGISTER_CODEC_CREATE_2(CreateCodec, CDecoder(), ICompressCoder2)
+#ifndef EXTRACT_ONLY
+REGISTER_CODEC_CREATE_2(CreateCodecOut, CEncoder(), ICompressCoder2)
+#else
+#define CreateCodecOut NULL
+#endif
+
+REGISTER_CODEC_VAR
+ { CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false };
+
+REGISTER_CODEC(BCJ2)
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.cpp
new file mode 100644
index 0000000000..a50360c190
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.cpp
@@ -0,0 +1,24 @@
+// BcjCoder.cpp
+
+#include "StdAfx.h"
+
+#include "BcjCoder.h"
+
+namespace NCompress {
+namespace NBcj {
+
+STDMETHODIMP CCoder::Init()
+{
+ _bufferPos = 0;
+ x86_Convert_Init(_prevMask);
+ return S_OK;
+}
+
+STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size)
+{
+ UInt32 processed = (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, _encode);
+ _bufferPos += processed;
+ return processed;
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.h
new file mode 100644
index 0000000000..475dfe55a4
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.h
@@ -0,0 +1,31 @@
+// BcjCoder.h
+
+#ifndef __COMPRESS_BCJ_CODER_H
+#define __COMPRESS_BCJ_CODER_H
+
+#include "../../../C/Bra.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NBcj {
+
+class CCoder:
+ public ICompressFilter,
+ public CMyUnknownImp
+{
+ UInt32 _bufferPos;
+ UInt32 _prevMask;
+ int _encode;
+public:
+ MY_UNKNOWN_IMP1(ICompressFilter);
+ INTERFACE_ICompressFilter(;)
+
+ CCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); }
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/BcjRegister.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/BcjRegister.cpp
new file mode 100644
index 0000000000..48cc057fa1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/BcjRegister.cpp
@@ -0,0 +1,17 @@
+// BcjRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "BcjCoder.h"
+
+namespace NCompress {
+namespace NBcj {
+
+REGISTER_FILTER_E(BCJ,
+ CCoder(false),
+ CCoder(true),
+ 0x3030103, "BCJ")
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.cpp
new file mode 100644
index 0000000000..d5a90f1794
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.cpp
@@ -0,0 +1,23 @@
+// BranchMisc.cpp
+
+#include "StdAfx.h"
+
+#include "BranchMisc.h"
+
+namespace NCompress {
+namespace NBranch {
+
+STDMETHODIMP CCoder::Init()
+{
+ _bufferPos = 0;
+ return S_OK;
+}
+
+STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size)
+{
+ UInt32 processed = (UInt32)BraFunc(data, size, _bufferPos, _encode);
+ _bufferPos += processed;
+ return processed;
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.h b/other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.h
new file mode 100644
index 0000000000..02a56c3903
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.h
@@ -0,0 +1,35 @@
+// BranchMisc.h
+
+#ifndef __COMPRESS_BRANCH_MISC_H
+#define __COMPRESS_BRANCH_MISC_H
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+EXTERN_C_BEGIN
+
+typedef SizeT (*Func_Bra)(Byte *data, SizeT size, UInt32 ip, int encoding);
+
+EXTERN_C_END
+
+namespace NCompress {
+namespace NBranch {
+
+class CCoder:
+ public ICompressFilter,
+ public CMyUnknownImp
+{
+ UInt32 _bufferPos;
+ int _encode;
+ Func_Bra BraFunc;
+public:
+ MY_UNKNOWN_IMP1(ICompressFilter);
+ INTERFACE_ICompressFilter(;)
+
+ CCoder(Func_Bra bra, int encode): _bufferPos(0), _encode(encode), BraFunc(bra) {}
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/BranchRegister.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/BranchRegister.cpp
new file mode 100644
index 0000000000..b83c6bcbd3
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/BranchRegister.cpp
@@ -0,0 +1,41 @@
+// BranchRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Bra.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "BranchMisc.h"
+
+namespace NCompress {
+namespace NBranch {
+
+#define CREATE_BRA(n) \
+ REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(n ## _Convert, false)) \
+ REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(n ## _Convert, true)) \
+
+CREATE_BRA(PPC)
+CREATE_BRA(IA64)
+CREATE_BRA(ARM)
+CREATE_BRA(ARMT)
+CREATE_BRA(SPARC)
+
+#define METHOD_ITEM(n, id, name) \
+ REGISTER_FILTER_ITEM( \
+ CreateBra_Decoder_ ## n, \
+ CreateBra_Encoder_ ## n, \
+ 0x3030000 + id, name)
+
+REGISTER_CODECS_VAR
+{
+ 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/other-licenses/7zstub/src/CPP/7zip/Compress/ByteSwap.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/ByteSwap.cpp
new file mode 100644
index 0000000000..ee103afe7a
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/ByteSwap.cpp
@@ -0,0 +1,92 @@
+// ByteSwap.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+#include "../Common/RegisterCodec.h"
+
+namespace NCompress {
+namespace NByteSwap {
+
+class CByteSwap2:
+ public ICompressFilter,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICompressFilter);
+ INTERFACE_ICompressFilter(;)
+};
+
+class CByteSwap4:
+ public ICompressFilter,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICompressFilter);
+ INTERFACE_ICompressFilter(;)
+};
+
+STDMETHODIMP CByteSwap2::Init() { return S_OK; }
+
+STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size)
+{
+ const UInt32 kStep = 2;
+ if (size < kStep)
+ return 0;
+ size &= ~(kStep - 1);
+
+ const Byte *end = data + (size_t)size;
+
+ do
+ {
+ Byte b0 = data[0];
+ data[0] = data[1];
+ data[1] = b0;
+ data += kStep;
+ }
+ while (data != end);
+
+ return size;
+}
+
+STDMETHODIMP CByteSwap4::Init() { return S_OK; }
+
+STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size)
+{
+ const UInt32 kStep = 4;
+ if (size < kStep)
+ return 0;
+ size &= ~(kStep - 1);
+
+ const Byte *end = data + (size_t)size;
+
+ do
+ {
+ Byte b0 = data[0];
+ Byte b1 = data[1];
+ data[0] = data[3];
+ data[1] = data[2];
+ data[2] = b1;
+ data[3] = b0;
+ data += kStep;
+ }
+ while (data != end);
+
+ return size;
+}
+
+REGISTER_FILTER_CREATE(CreateFilter2, CByteSwap2())
+REGISTER_FILTER_CREATE(CreateFilter4, CByteSwap4())
+
+REGISTER_CODECS_VAR
+{
+ REGISTER_FILTER_ITEM(CreateFilter2, CreateFilter2, 0x20302, "Swap2"),
+ REGISTER_FILTER_ITEM(CreateFilter4, CreateFilter4, 0x20304, "Swap4")
+};
+
+REGISTER_CODECS(ByteSwap)
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/CodecExports.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/CodecExports.cpp
new file mode 100644
index 0000000000..7be496c243
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/CodecExports.cpp
@@ -0,0 +1,344 @@
+// CodecExports.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "../../Common/ComTry.h"
+#include "../../Common/MyCom.h"
+
+#include "../../Windows/Defs.h"
+
+#include "../ICoder.h"
+
+#include "../Common/RegisterCodec.h"
+
+extern unsigned g_NumCodecs;
+extern const CCodecInfo *g_Codecs[];
+
+extern unsigned g_NumHashers;
+extern const CHasherInfo *g_Hashers[];
+
+static void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw()
+{
+ UINT len = (UINT)strlen(s);
+ BSTR 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) throw()
+{
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL)
+ value->vt = VT_BSTR;
+ return S_OK;
+}
+
+static HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw()
+{
+ GUID clsId;
+ 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, bool isCoder2, bool isFilter, bool &encode, int &index) throw()
+{
+ index = -1;
+ if (clsid->Data1 != k_7zip_GUID_Data1 ||
+ clsid->Data2 != k_7zip_GUID_Data2)
+ return S_OK;
+
+ encode = true;
+
+ 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 : !codec.CreateDecoder)
+ || (isFilter ? !codec.IsFilter : codec.IsFilter))
+ continue;
+
+ if (codec.NumStreams == 1 ? isCoder2 : !isCoder2)
+ return E_NOINTERFACE;
+
+ index = i;
+ return S_OK;
+ }
+
+ return S_OK;
+}
+
+static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder)
+{
+ COM_TRY_BEGIN
+
+ const CCodecInfo &codec = *g_Codecs[index];
+
+ void *c;
+ if (encode)
+ c = codec.CreateEncoder();
+ else
+ c = codec.CreateDecoder();
+
+ if (c)
+ {
+ IUnknown *unk;
+ if (codec.IsFilter)
+ unk = (IUnknown *)(ICompressFilter *)c;
+ else if (codec.NumStreams != 1)
+ unk = (IUnknown *)(ICompressCoder2 *)c;
+ else
+ 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)
+{
+ *outObject = NULL;
+
+ bool isFilter = false;
+ bool isCoder2 = false;
+ bool isCoder = (*iid == IID_ICompressCoder) != 0;
+ 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);
+ if (res != S_OK)
+ return res;
+ if (codecIndex < 0)
+ return CLASS_E_CLASSNOTAVAILABLE;
+
+ return CreateCoderMain(codecIndex, encode, outObject);
+}
+
+STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
+{
+ ::VariantClear((VARIANTARG *)value);
+ const CCodecInfo &codec = *g_Codecs[codecIndex];
+ switch (propID)
+ {
+ case NMethodPropID::kID:
+ value->uhVal.QuadPart = (UInt64)codec.Id;
+ value->vt = VT_UI8;
+ break;
+ case NMethodPropID::kName:
+ SetPropFromAscii(codec.Name, value);
+ break;
+ case NMethodPropID::kDecoder:
+ if (codec.CreateDecoder)
+ return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value);
+ break;
+ case NMethodPropID::kEncoder:
+ if (codec.CreateEncoder)
+ 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::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.EncoderFlags;
+ }
+ break;
+ */
+ }
+ return S_OK;
+}
+
+STDAPI GetNumberOfMethods(UINT32 *numCodecs)
+{
+ *numCodecs = g_NumCodecs;
+ return S_OK;
+}
+
+
+// ---------- Hashers ----------
+
+static int FindHasherClassId(const GUID *clsid) throw()
+{
+ 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);
+ for (unsigned i = 0; i < g_NumCodecs; i++)
+ if (id == g_Hashers[i]->Id)
+ return i;
+ return -1;
+}
+
+static HRESULT CreateHasher2(UInt32 index, IHasher **hasher)
+{
+ COM_TRY_BEGIN
+ *hasher = g_Hashers[index]->CreateHasher();
+ if (*hasher)
+ (*hasher)->AddRef();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDAPI CreateHasher(const GUID *clsid, IHasher **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ int index = FindHasherClassId(clsid);
+ if (index < 0)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ return CreateHasher2(index, outObject);
+ COM_TRY_END
+}
+
+STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
+{
+ ::VariantClear((VARIANTARG *)value);
+ const CHasherInfo &codec = *g_Hashers[codecIndex];
+ switch (propID)
+ {
+ case NMethodPropID::kID:
+ value->uhVal.QuadPart = (UInt64)codec.Id;
+ value->vt = VT_UI8;
+ break;
+ case NMethodPropID::kName:
+ SetPropFromAscii(codec.Name, value);
+ break;
+ case NMethodPropID::kEncoder:
+ if (codec.CreateHasher)
+ return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value);
+ break;
+ case NMethodPropID::kDigestSize:
+ value->ulVal = (ULONG)codec.DigestSize;
+ value->vt = VT_UI4;
+ break;
+ }
+ return S_OK;
+}
+
+class CHashers:
+ public IHashers,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(IHashers)
+
+ STDMETHOD_(UInt32, GetNumHashers)();
+ STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);
+};
+
+STDAPI GetHashers(IHashers **hashers)
+{
+ COM_TRY_BEGIN
+ *hashers = new CHashers;
+ if (*hashers)
+ (*hashers)->AddRef();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP_(UInt32) CHashers::GetNumHashers()
+{
+ return g_NumHashers;
+}
+
+STDMETHODIMP CHashers::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ return ::GetHasherProp(index, propID, value);
+}
+
+STDMETHODIMP CHashers::CreateHasher(UInt32 index, IHasher **hasher)
+{
+ return ::CreateHasher2(index, hasher);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.cpp
new file mode 100644
index 0000000000..89b5237659
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.cpp
@@ -0,0 +1,120 @@
+// Compress/CopyCoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "CopyCoder.h"
+
+namespace NCompress {
+
+static const UInt32 kBufSize = 1 << 17;
+
+CCopyCoder::~CCopyCoder()
+{
+ ::MidFree(_buf);
+}
+
+STDMETHODIMP CCopyCoder::SetFinishMode(UInt32 /* finishMode */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize,
+ ICompressProgressInfo *progress)
+{
+ if (!_buf)
+ {
+ _buf = (Byte *)::MidAlloc(kBufSize);
+ if (!_buf)
+ return E_OUTOFMEMORY;
+ }
+
+ TotalSize = 0;
+
+ for (;;)
+ {
+ UInt32 size = kBufSize;
+ if (outSize && size > *outSize - TotalSize)
+ size = (UInt32)(*outSize - TotalSize);
+ if (size == 0)
+ return S_OK;
+
+ HRESULT readRes = inStream->Read(_buf, size, &size);
+
+ if (size == 0)
+ return readRes;
+
+ if (outStream)
+ {
+ 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);
+ }
+ 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;
+ return S_OK;
+}
+
+HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
+{
+ CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;
+ return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+}
+
+HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)
+{
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+ RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress));
+ return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;
+}
+
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.h
new file mode 100644
index 0000000000..b2fa491e09
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.h
@@ -0,0 +1,49 @@
+// Compress/CopyCoder.h
+
+#ifndef __COMPRESS_COPY_CODER_H
+#define __COMPRESS_COPY_CODER_H
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+
+class CCopyCoder:
+ public ICompressCoder,
+ public ICompressSetInStream,
+ public ISequentialInStream,
+ public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize,
+ public CMyUnknownImp
+{
+ Byte *_buf;
+ CMyComPtr<ISequentialInStream> _inStream;
+public:
+ UInt64 TotalSize;
+
+ CCopyCoder(): _buf(0), TotalSize(0) {};
+ ~CCopyCoder();
+
+ MY_UNKNOWN_IMP5(
+ ICompressCoder,
+ ICompressSetInStream,
+ ISequentialInStream,
+ ICompressSetFinishMode,
+ 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(SetFinishMode)(UInt32 finishMode);
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+};
+
+HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
+HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress);
+
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/CopyRegister.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/CopyRegister.cpp
new file mode 100644
index 0000000000..1c59fe0c00
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/CopyRegister.cpp
@@ -0,0 +1,15 @@
+// CopyRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "CopyCoder.h"
+
+namespace NCompress {
+
+REGISTER_CODEC_CREATE(CreateCodec, CCopyCoder())
+
+REGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, "Copy")
+
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/DeltaFilter.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/DeltaFilter.cpp
new file mode 100644
index 0000000000..cdbd33d4c7
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/DeltaFilter.cpp
@@ -0,0 +1,128 @@
+// DeltaFilter.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Delta.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+#include "../Common/RegisterCodec.h"
+
+namespace NCompress {
+namespace NDelta {
+
+struct CDelta
+{
+ unsigned _delta;
+ Byte _state[DELTA_STATE_SIZE];
+
+ CDelta(): _delta(1) {}
+ void DeltaInit() { Delta_Init(_state); }
+};
+
+
+#ifndef EXTRACT_ONLY
+
+class CEncoder:
+ public ICompressFilter,
+ public ICompressSetCoderProperties,
+ public ICompressWriteCoderProperties,
+ CDelta,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP3(ICompressFilter, ICompressSetCoderProperties, ICompressWriteCoderProperties)
+ INTERFACE_ICompressFilter(;)
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+};
+
+STDMETHODIMP CEncoder::Init()
+{
+ DeltaInit();
+ return S_OK;
+}
+
+STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)
+{
+ Delta_Encode(_state, _delta, data, size);
+ return size;
+}
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
+{
+ UInt32 delta = _delta;
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = props[i];
+ PROPID propID = propIDs[i];
+ if (propID >= NCoderPropID::kReduceSize)
+ continue;
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ switch (propID)
+ {
+ case NCoderPropID::kDefaultProp:
+ delta = (UInt32)prop.ulVal;
+ if (delta < 1 || delta > 256)
+ return E_INVALIDARG;
+ break;
+ case NCoderPropID::kNumThreads: break;
+ case NCoderPropID::kLevel: break;
+ default: return E_INVALIDARG;
+ }
+ }
+ _delta = delta;
+ return S_OK;
+}
+
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+ Byte prop = (Byte)(_delta - 1);
+ return outStream->Write(&prop, 1, NULL);
+}
+
+#endif
+
+
+class CDecoder:
+ public ICompressFilter,
+ public ICompressSetDecoderProperties2,
+ CDelta,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP2(ICompressFilter, ICompressSetDecoderProperties2)
+ INTERFACE_ICompressFilter(;)
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+};
+
+STDMETHODIMP CDecoder::Init()
+{
+ DeltaInit();
+ return S_OK;
+}
+
+STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
+{
+ Delta_Decode(_state, _delta, data, size);
+ return size;
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)
+{
+ if (size != 1)
+ return E_INVALIDARG;
+ _delta = (unsigned)props[0] + 1;
+ return S_OK;
+}
+
+
+REGISTER_FILTER_E(Delta,
+ CDecoder(),
+ CEncoder(),
+ 3, "Delta")
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp
new file mode 100644
index 0000000000..bb631c5c59
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp
@@ -0,0 +1,265 @@
+// Lzma2Decoder.cpp
+
+#include "StdAfx.h"
+
+// #include <stdio.h>
+
+#include "../../../C/Alloc.h"
+// #include "../../../C/CpuTicks.h"
+
+#include "../Common/StreamUtils.h"
+
+#include "Lzma2Decoder.h"
+
+namespace NCompress {
+namespace NLzma2 {
+
+CDecoder::CDecoder():
+ _dec(NULL)
+ , _inProcessed(0)
+ , _prop(0xFF)
+ , _finishMode(false)
+ , _inBufSize(1 << 20)
+ , _outStep(1 << 20)
+ #ifndef _7ZIP_ST
+ , _tryMt(1)
+ , _numThreads(1)
+ , _memUsage((UInt64)(sizeof(size_t)) << 28)
+ #endif
+{}
+
+CDecoder::~CDecoder()
+{
+ if (_dec)
+ Lzma2DecMt_Destroy(_dec);
+}
+
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
+{
+ if (size != 1)
+ return E_NOTIMPL;
+ if (prop[0] > 40)
+ return E_NOTIMPL;
+ _prop = prop[0];
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
+{
+ _finishMode = (finishMode != 0);
+ return S_OK;
+}
+
+
+
+#ifndef _7ZIP_ST
+
+static UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)
+{
+ const UInt32 kMinSize = (UInt32)1 << 20;
+ const UInt32 kMaxSize = (UInt32)1 << 28;
+ UInt64 blockSize = (UInt64)dictSize << 2;
+ if (blockSize < kMinSize) blockSize = kMinSize;
+ if (blockSize > kMaxSize) blockSize = kMaxSize;
+ if (blockSize < dictSize) blockSize = dictSize;
+ blockSize += (kMinSize - 1);
+ blockSize &= ~(UInt64)(kMinSize - 1);
+ return blockSize;
+}
+
+#define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)))
+
+#endif
+
+#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ _inProcessed = 0;
+
+ if (!_dec)
+ {
+ _dec = Lzma2DecMt_Create(
+ // &g_AlignedAlloc,
+ &g_Alloc,
+ &g_MidAlloc);
+ if (!_dec)
+ return E_OUTOFMEMORY;
+ }
+
+ CLzma2DecMtProps props;
+ Lzma2DecMtProps_Init(&props);
+
+ props.inBufSize_ST = _inBufSize;
+ props.outStep_ST = _outStep;
+
+ #ifndef _7ZIP_ST
+ {
+ props.numThreads = 1;
+ UInt32 numThreads = _numThreads;
+
+ if (_tryMt && numThreads >= 1)
+ {
+ UInt64 useLimit = _memUsage;
+ UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop);
+ UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize);
+ size_t expectedBlockSize = (size_t)expectedBlockSize64;
+ size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16;
+ if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize)
+ {
+ props.outBlockMax = expectedBlockSize;
+ props.inBlockMax = inBlockMax;
+ const size_t kOverheadSize = props.inBufSize_MT + (1 << 16);
+ UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize);
+ if (numThreads > okThreads)
+ numThreads = (UInt32)okThreads;
+ if (numThreads == 0)
+ numThreads = 1;
+ props.numThreads = numThreads;
+ }
+ }
+ }
+ #endif
+
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res;
+
+ UInt64 inProcessed = 0;
+ int isMT = False;
+
+ #ifndef _7ZIP_ST
+ isMT = _tryMt;
+ #endif
+
+ // UInt64 cpuTicks = GetCpuTicks();
+
+ res = Lzma2DecMt_Decode(_dec, _prop, &props,
+ &outWrap.vt, outSize, _finishMode,
+ &inWrap.vt,
+ &inProcessed,
+ &isMT,
+ progress ? &progressWrap.vt : NULL);
+
+ /*
+ cpuTicks = GetCpuTicks() - cpuTicks;
+ printf("\n ticks = %10I64u\n", cpuTicks / 1000000);
+ */
+
+
+ #ifndef _7ZIP_ST
+ /* we reset _tryMt, only if p->props.numThreads was changed */
+ if (props.numThreads > 1)
+ _tryMt = isMT;
+ #endif
+
+ _inProcessed = inProcessed;
+
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
+
+ if (res == SZ_OK && _finishMode)
+ {
+ if (inSize && *inSize != inProcessed)
+ res = SZ_ERROR_DATA;
+ if (outSize && *outSize != outWrap.Processed)
+ res = SZ_ERROR_DATA;
+ }
+
+ return SResToHRESULT(res);
+}
+
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = _inProcessed;
+ return S_OK;
+}
+
+
+#ifndef _7ZIP_ST
+
+STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)
+{
+ _numThreads = numThreads;
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetMemLimit(UInt64 memUsage)
+{
+ _memUsage = memUsage;
+ return S_OK;
+}
+
+#endif
+
+
+#ifndef NO_READ_FROM_CODER
+
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+{
+ CLzma2DecMtProps props;
+ Lzma2DecMtProps_Init(&props);
+ props.inBufSize_ST = _inBufSize;
+ props.outStep_ST = _outStep;
+
+ _inProcessed = 0;
+
+ if (!_dec)
+ {
+ _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc);
+ if (!_dec)
+ return E_OUTOFMEMORY;
+ }
+
+ _inWrap.Init(_inStream);
+
+ SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt);
+
+ if (res != SZ_OK)
+ return SResToHRESULT(res);
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
+STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
+
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ size_t size2 = size;
+ UInt64 inProcessed = 0;
+
+ SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed);
+
+ _inProcessed += inProcessed;
+ if (processedSize)
+ *processedSize = (UInt32)size2;
+ if (res != SZ_OK)
+ return SResToHRESULT(res);
+ return S_OK;
+}
+
+#endif
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.h
new file mode 100644
index 0000000000..b56488e0d8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.h
@@ -0,0 +1,96 @@
+// Lzma2Decoder.h
+
+#ifndef __LZMA2_DECODER_H
+#define __LZMA2_DECODER_H
+
+#include "../../../C/Lzma2DecMt.h"
+
+#include "../Common/CWrappers.h"
+
+namespace NCompress {
+namespace NLzma2 {
+
+class CDecoder:
+ public ICompressCoder,
+ public ICompressSetDecoderProperties2,
+ public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize,
+ public ICompressSetBufSize,
+
+ #ifndef NO_READ_FROM_CODER
+ public ICompressSetInStream,
+ public ICompressSetOutStreamSize,
+ public ISequentialInStream,
+ #endif
+
+ #ifndef _7ZIP_ST
+ public ICompressSetCoderMt,
+ public ICompressSetMemLimit,
+ #endif
+
+ public CMyUnknownImp
+{
+ CLzma2DecMtHandle _dec;
+ UInt64 _inProcessed;
+ Byte _prop;
+ int _finishMode;
+ UInt32 _inBufSize;
+ UInt32 _outStep;
+
+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_QUERYINTERFACE_ENTRY(ICompressSetInStream)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
+ MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
+ #endif
+
+ #ifndef _7ZIP_ST
+ MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetMemLimit)
+ #endif
+
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ 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);
+
+ #ifndef _7ZIP_ST
+private:
+ int _tryMt;
+ UInt32 _numThreads;
+ UInt64 _memUsage;
+public:
+ STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
+ STDMETHOD(SetMemLimit)(UInt64 memUsage);
+ #endif
+
+ #ifndef NO_READ_FROM_CODER
+private:
+ CMyComPtr<ISequentialInStream> _inStream;
+ CSeqInStreamWrap _inWrap;
+public:
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+ STDMETHOD(ReleaseInStream)();
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ #endif
+
+ CDecoder();
+ virtual ~CDecoder();
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.cpp
new file mode 100644
index 0000000000..18f7d029d9
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.cpp
@@ -0,0 +1,122 @@
+// Lzma2Encoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../Common/CWrappers.h"
+#include "../Common/StreamUtils.h"
+
+#include "Lzma2Encoder.h"
+
+namespace NCompress {
+
+namespace NLzma {
+
+HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep);
+
+}
+
+namespace NLzma2 {
+
+CEncoder::CEncoder()
+{
+ _encoder = NULL;
+ _encoder = Lzma2Enc_Create(&g_AlignedAlloc, &g_BigAlloc);
+ if (!_encoder)
+ throw 1;
+}
+
+CEncoder::~CEncoder()
+{
+ if (_encoder)
+ Lzma2Enc_Destroy(_encoder);
+}
+
+
+HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props)
+{
+ switch (propID)
+ {
+ case NCoderPropID::kBlockSize:
+ {
+ if (prop.vt == VT_UI4)
+ lzma2Props.blockSize = prop.ulVal;
+ else if (prop.vt == VT_UI8)
+ lzma2Props.blockSize = prop.uhVal.QuadPart;
+ else
+ return E_INVALIDARG;
+ break;
+ }
+ case NCoderPropID::kNumThreads:
+ if (prop.vt != VT_UI4) return E_INVALIDARG; lzma2Props.numTotalThreads = (int)(prop.ulVal); break;
+ default:
+ RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps));
+ }
+ return S_OK;
+}
+
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ CLzma2EncProps lzma2Props;
+ Lzma2EncProps_Init(&lzma2Props);
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props));
+ }
+ return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));
+}
+
+
+STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ PROPID propID = propIDs[i];
+ if (propID == NCoderPropID::kExpectedDataSize)
+ if (prop.vt == VT_UI8)
+ Lzma2Enc_SetDataSize(_encoder, prop.uhVal.QuadPart);
+ }
+ return S_OK;
+}
+
+
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+ Byte prop = Lzma2Enc_WriteProperties(_encoder);
+ return WriteStream(outStream, &prop, 1);
+}
+
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
+{
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res = Lzma2Enc_Encode2(_encoder,
+ &outWrap.vt, NULL, NULL,
+ &inWrap.vt, NULL, 0,
+ progress ? &progressWrap.vt : NULL);
+
+ RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+
+ return SResToHRESULT(res);
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.h
new file mode 100644
index 0000000000..6539e73acf
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.h
@@ -0,0 +1,42 @@
+// Lzma2Encoder.h
+
+#ifndef __LZMA2_ENCODER_H
+#define __LZMA2_ENCODER_H
+
+#include "../../../C/Lzma2Enc.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NLzma2 {
+
+class CEncoder:
+ public ICompressCoder,
+ public ICompressSetCoderProperties,
+ public ICompressWriteCoderProperties,
+ public ICompressSetCoderPropertiesOpt,
+ public CMyUnknownImp
+{
+ CLzma2EncHandle _encoder;
+public:
+ MY_UNKNOWN_IMP4(
+ ICompressCoder,
+ ICompressSetCoderProperties,
+ ICompressWriteCoderProperties,
+ ICompressSetCoderPropertiesOpt)
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+ STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+
+ CEncoder();
+ virtual ~CEncoder();
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Register.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Register.cpp
new file mode 100644
index 0000000000..4367105635
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Register.cpp
@@ -0,0 +1,22 @@
+// Lzma2Register.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "Lzma2Decoder.h"
+
+#ifndef EXTRACT_ONLY
+#include "Lzma2Encoder.h"
+#endif
+
+namespace NCompress {
+namespace NLzma2 {
+
+REGISTER_CODEC_E(LZMA2,
+ CDecoder(),
+ CEncoder(),
+ 0x21,
+ "LZMA2")
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.cpp
new file mode 100644
index 0000000000..b6a8d3fbd3
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.cpp
@@ -0,0 +1,343 @@
+// LzmaDecoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../Common/StreamUtils.h"
+
+#include "LzmaDecoder.h"
+
+static HRESULT SResToHRESULT(SRes res)
+{
+ switch (res)
+ {
+ case SZ_OK: return S_OK;
+ case SZ_ERROR_MEM: return E_OUTOFMEMORY;
+ case SZ_ERROR_PARAM: return E_INVALIDARG;
+ case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
+ case SZ_ERROR_DATA: return S_FALSE;
+ }
+ return E_FAIL;
+}
+
+namespace NCompress {
+namespace NLzma {
+
+CDecoder::CDecoder():
+ _inBuf(NULL),
+ _lzmaStatus(LZMA_STATUS_NOT_SPECIFIED),
+ FinishStream(false),
+ _propsWereSet(false),
+ _outSizeDefined(false),
+ _outStep(1 << 20),
+ _inBufSize(0),
+ _inBufSizeNew(1 << 20)
+{
+ _inProcessed = 0;
+ _inPos = _inLim = 0;
+
+ /*
+ AlignOffsetAlloc_CreateVTable(&_alloc);
+ _alloc.numAlignBits = 7;
+ _alloc.offset = 0;
+ */
+ LzmaDec_Construct(&_state);
+}
+
+CDecoder::~CDecoder()
+{
+ LzmaDec_Free(&_state, &g_AlignedAlloc); // &_alloc.vt
+ MyFree(_inBuf);
+}
+
+STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }
+STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
+
+HRESULT CDecoder::CreateInputBuffer()
+{
+ if (!_inBuf || _inBufSizeNew != _inBufSize)
+ {
+ MyFree(_inBuf);
+ _inBufSize = 0;
+ _inBuf = (Byte *)MyAlloc(_inBufSizeNew);
+ if (!_inBuf)
+ return E_OUTOFMEMORY;
+ _inBufSize = _inBufSizeNew;
+ }
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
+{
+ RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_AlignedAlloc))) // &_alloc.vt
+ _propsWereSet = true;
+ return CreateInputBuffer();
+}
+
+
+void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)
+{
+ _outSizeDefined = (outSize != NULL);
+ _outSize = 0;
+ if (_outSizeDefined)
+ _outSize = *outSize;
+ _outProcessed = 0;
+ _lzmaStatus = LZMA_STATUS_NOT_SPECIFIED;
+
+ LzmaDec_Init(&_state);
+}
+
+
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+{
+ _inProcessed = 0;
+ _inPos = _inLim = 0;
+ SetOutStreamSizeResume(outSize);
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
+{
+ FinishStream = (finishMode != 0);
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = _inProcessed;
+ return S_OK;
+}
+
+
+HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
+{
+ if (!_inBuf || !_propsWereSet)
+ return S_FALSE;
+
+ const UInt64 startInProgress = _inProcessed;
+ SizeT wrPos = _state.dicPos;
+ HRESULT readRes = S_OK;
+
+ for (;;)
+ {
+ if (_inPos == _inLim && readRes == S_OK)
+ {
+ _inPos = _inLim = 0;
+ readRes = inStream->Read(_inBuf, _inBufSize, &_inLim);
+ }
+
+ const SizeT dicPos = _state.dicPos;
+ SizeT size;
+ {
+ SizeT next = _state.dicBufSize;
+ if (next - wrPos > _outStep)
+ next = wrPos + _outStep;
+ size = next - dicPos;
+ }
+
+ ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
+ if (_outSizeDefined)
+ {
+ const UInt64 rem = _outSize - _outProcessed;
+ if (size >= rem)
+ {
+ size = (SizeT)rem;
+ if (FinishStream)
+ finishMode = LZMA_FINISH_END;
+ }
+ }
+
+ SizeT inProcessed = _inLim - _inPos;
+ ELzmaStatus status;
+
+ SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status);
+
+ _lzmaStatus = status;
+ _inPos += (UInt32)inProcessed;
+ _inProcessed += inProcessed;
+ const SizeT outProcessed = _state.dicPos - dicPos;
+ _outProcessed += outProcessed;
+
+ // we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0)
+ bool outFinished = (_outSizeDefined && _outProcessed >= _outSize);
+
+ bool needStop = (res != 0
+ || (inProcessed == 0 && outProcessed == 0)
+ || status == LZMA_STATUS_FINISHED_WITH_MARK
+ || (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT));
+
+ if (needStop || outProcessed >= size)
+ {
+ HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos);
+
+ if (_state.dicPos == _state.dicBufSize)
+ _state.dicPos = 0;
+ wrPos = _state.dicPos;
+
+ RINOK(res2);
+
+ if (needStop)
+ {
+ if (res != 0)
+ return S_FALSE;
+
+ if (status == LZMA_STATUS_FINISHED_WITH_MARK)
+ {
+ if (FinishStream)
+ if (_outSizeDefined && _outSize != _outProcessed)
+ return S_FALSE;
+ return readRes;
+ }
+
+ if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)
+ if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
+ return readRes;
+
+ return S_FALSE;
+ }
+ }
+
+ if (progress)
+ {
+ const UInt64 inSize = _inProcessed - startInProgress;
+ RINOK(progress->SetRatioInfo(&inSize, &_outProcessed));
+ }
+ }
+}
+
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ if (!_inBuf)
+ return E_INVALIDARG;
+ SetOutStreamSize(outSize);
+ HRESULT res = CodeSpec(inStream, outStream, progress);
+ if (res == S_OK)
+ if (FinishStream && inSize && *inSize != _inProcessed)
+ res = S_FALSE;
+ return res;
+}
+
+
+#ifndef NO_READ_FROM_CODER
+
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
+STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
+
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+
+ ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
+ if (_outSizeDefined)
+ {
+ const UInt64 rem = _outSize - _outProcessed;
+ if (size >= rem)
+ {
+ size = (UInt32)rem;
+ if (FinishStream)
+ finishMode = LZMA_FINISH_END;
+ }
+ }
+
+ HRESULT readRes = S_OK;
+
+ for (;;)
+ {
+ if (_inPos == _inLim && readRes == S_OK)
+ {
+ _inPos = _inLim = 0;
+ readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
+ }
+
+ SizeT inProcessed = _inLim - _inPos;
+ SizeT outProcessed = size;
+ ELzmaStatus status;
+
+ SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
+ _inBuf + _inPos, &inProcessed, finishMode, &status);
+
+ _lzmaStatus = status;
+ _inPos += (UInt32)inProcessed;
+ _inProcessed += inProcessed;
+ _outProcessed += outProcessed;
+ size -= (UInt32)outProcessed;
+ data = (Byte *)data + outProcessed;
+ if (processedSize)
+ *processedSize += (UInt32)outProcessed;
+
+ if (res != 0)
+ return S_FALSE;
+
+ /*
+ if (status == LZMA_STATUS_FINISHED_WITH_MARK)
+ return readRes;
+
+ if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
+ {
+ if (FinishStream
+ && _outSizeDefined && _outProcessed >= _outSize
+ && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
+ return S_FALSE;
+ return readRes;
+ }
+ */
+
+ if (inProcessed == 0 && outProcessed == 0)
+ return readRes;
+ }
+}
+
+
+HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ SetOutStreamSizeResume(outSize);
+ return CodeSpec(_inStream, outStream, progress);
+}
+
+
+HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize)
+{
+ RINOK(CreateInputBuffer());
+
+ if (processedSize)
+ *processedSize = 0;
+
+ HRESULT readRes = S_OK;
+
+ while (size != 0)
+ {
+ if (_inPos == _inLim)
+ {
+ _inPos = _inLim = 0;
+ if (readRes == S_OK)
+ readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
+ if (_inLim == 0)
+ break;
+ }
+
+ UInt32 cur = _inLim - _inPos;
+ if (cur > size)
+ cur = size;
+ memcpy(data, _inBuf + _inPos, cur);
+ _inPos += cur;
+ _inProcessed += cur;
+ size -= cur;
+ data = (Byte *)data + cur;
+ if (processedSize)
+ *processedSize += cur;
+ }
+
+ return readRes;
+}
+
+#endif
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.h
new file mode 100644
index 0000000000..08b7c1bc30
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.h
@@ -0,0 +1,113 @@
+// LzmaDecoder.h
+
+#ifndef __LZMA_DECODER_H
+#define __LZMA_DECODER_H
+
+// #include "../../../C/Alloc.h"
+#include "../../../C/LzmaDec.h"
+
+#include "../../Common/MyCom.h"
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NLzma {
+
+class CDecoder:
+ public ICompressCoder,
+ public ICompressSetDecoderProperties2,
+ public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize,
+ public ICompressSetBufSize,
+ #ifndef NO_READ_FROM_CODER
+ public ICompressSetInStream,
+ public ICompressSetOutStreamSize,
+ public ISequentialInStream,
+ #endif
+ public CMyUnknownImp
+{
+ Byte *_inBuf;
+ UInt32 _inPos;
+ UInt32 _inLim;
+
+ ELzmaStatus _lzmaStatus;
+
+public:
+ bool FinishStream; // set it before decoding, if you need to decode full LZMA stream
+
+private:
+ bool _propsWereSet;
+ bool _outSizeDefined;
+ UInt64 _outSize;
+ UInt64 _inProcessed;
+ UInt64 _outProcessed;
+
+ UInt32 _outStep;
+ UInt32 _inBufSize;
+ UInt32 _inBufSizeNew;
+
+ // CAlignOffsetAlloc _alloc;
+
+ CLzmaDec _state;
+
+ HRESULT CreateInputBuffer();
+ HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
+ void SetOutStreamSizeResume(const UInt64 *outSize);
+
+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_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(SetDecoderProperties2)(const Byte *data, UInt32 size);
+ STDMETHOD(SetFinishMode)(UInt32 finishMode);
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+ STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
+ STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
+
+ #ifndef NO_READ_FROM_CODER
+
+private:
+ CMyComPtr<ISequentialInStream> _inStream;
+public:
+
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+ STDMETHOD(ReleaseInStream)();
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);
+ HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize);
+
+ #endif
+
+ UInt64 GetInputProcessedSize() const { return _inProcessed; }
+
+ CDecoder();
+ virtual ~CDecoder();
+
+ UInt64 GetOutputProcessedSize() const { return _outProcessed; }
+
+ bool NeedsMoreInput() const { return _lzmaStatus == LZMA_STATUS_NEEDS_MORE_INPUT; }
+
+ bool CheckFinishStatus(bool withEndMark) const
+ {
+ return _lzmaStatus == (withEndMark ?
+ LZMA_STATUS_FINISHED_WITH_MARK :
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK);
+ }
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.cpp
new file mode 100644
index 0000000000..3151c3d219
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.cpp
@@ -0,0 +1,182 @@
+// LzmaEncoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../Common/CWrappers.h"
+#include "../Common/StreamUtils.h"
+
+#include "LzmaEncoder.h"
+
+namespace NCompress {
+namespace NLzma {
+
+CEncoder::CEncoder()
+{
+ _encoder = NULL;
+ _encoder = LzmaEnc_Create(&g_AlignedAlloc);
+ if (!_encoder)
+ throw 1;
+}
+
+CEncoder::~CEncoder()
+{
+ if (_encoder)
+ LzmaEnc_Destroy(_encoder, &g_AlignedAlloc, &g_BigAlloc);
+}
+
+static inline wchar_t GetUpperChar(wchar_t c)
+{
+ if (c >= 'a' && c <= 'z')
+ c -= 0x20;
+ return c;
+}
+
+static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)
+{
+ wchar_t c = GetUpperChar(*s++);
+ if (c == L'H')
+ {
+ if (GetUpperChar(*s++) != L'C')
+ return 0;
+ int numHashBytesLoc = (int)(*s++ - L'0');
+ if (numHashBytesLoc < 4 || numHashBytesLoc > 4)
+ return 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;
+ if (*s != 0)
+ return 0;
+ *btMode = 1;
+ *numHashBytes = numHashBytesLoc;
+ return 1;
+}
+
+#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break;
+
+HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)
+{
+ if (propID == NCoderPropID::kMatchFinder)
+ {
+ if (prop.vt != VT_BSTR)
+ return E_INVALIDARG;
+ return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;
+ }
+
+ if (propID > NCoderPropID::kReduceSize)
+ return S_OK;
+
+ if (propID == NCoderPropID::kReduceSize)
+ {
+ if (prop.vt == VT_UI8)
+ ep.reduceSize = prop.uhVal.QuadPart;
+ else
+ return E_INVALIDARG;
+ return S_OK;
+ }
+
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 v = prop.ulVal;
+ switch (propID)
+ {
+ case NCoderPropID::kDefaultProp: if (v > 31) return E_INVALIDARG; ep.dictSize = (UInt32)1 << (unsigned)v; break;
+ SET_PROP_32(kLevel, level)
+ SET_PROP_32(kNumFastBytes, fb)
+ SET_PROP_32(kMatchFinderCycles, mc)
+ SET_PROP_32(kAlgorithm, algo)
+ SET_PROP_32(kDictionarySize, dictSize)
+ SET_PROP_32(kPosStateBits, pb)
+ SET_PROP_32(kLitPosBits, lp)
+ SET_PROP_32(kLitContextBits, lc)
+ SET_PROP_32(kNumThreads, numThreads)
+ default: return E_INVALIDARG;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ CLzmaEncProps props;
+ LzmaEncProps_Init(&props);
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ PROPID propID = propIDs[i];
+ switch (propID)
+ {
+ case NCoderPropID::kEndMarker:
+ if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal != VARIANT_FALSE); break;
+ default:
+ RINOK(SetLzmaProp(propID, prop, props));
+ }
+ }
+ return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));
+}
+
+
+STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ PROPID propID = propIDs[i];
+ if (propID == NCoderPropID::kExpectedDataSize)
+ if (prop.vt == VT_UI8)
+ LzmaEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);
+ }
+ return S_OK;
+}
+
+
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+ Byte props[LZMA_PROPS_SIZE];
+ size_t size = LZMA_PROPS_SIZE;
+ RINOK(LzmaEnc_WriteProperties(_encoder, props, &size));
+ return WriteStream(outStream, props, size);
+}
+
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
+{
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt,
+ progress ? &progressWrap.vt : NULL, &g_AlignedAlloc, &g_BigAlloc);
+
+ _inputProcessed = inWrap.Processed;
+
+ RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+
+ return SResToHRESULT(res);
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.h
new file mode 100644
index 0000000000..7b31c66d81
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.h
@@ -0,0 +1,46 @@
+// LzmaEncoder.h
+
+#ifndef __LZMA_ENCODER_H
+#define __LZMA_ENCODER_H
+
+#include "../../../C/LzmaEnc.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NLzma {
+
+class CEncoder:
+ public ICompressCoder,
+ public ICompressSetCoderProperties,
+ public ICompressWriteCoderProperties,
+ public ICompressSetCoderPropertiesOpt,
+ public CMyUnknownImp
+{
+ CLzmaEncHandle _encoder;
+ UInt64 _inputProcessed;
+public:
+ MY_UNKNOWN_IMP4(
+ ICompressCoder,
+ ICompressSetCoderProperties,
+ ICompressWriteCoderProperties,
+ ICompressSetCoderPropertiesOpt)
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+ STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+
+ CEncoder();
+ virtual ~CEncoder();
+
+ UInt64 GetInputProcessedSize() const { return _inputProcessed; }
+ bool IsWriteEndMark() const { return LzmaEnc_IsWriteEndMark(_encoder) != 0; }
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaRegister.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaRegister.cpp
new file mode 100644
index 0000000000..4397595081
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/LzmaRegister.cpp
@@ -0,0 +1,22 @@
+// LzmaRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "LzmaDecoder.h"
+
+#ifndef EXTRACT_ONLY
+#include "LzmaEncoder.h"
+#endif
+
+namespace NCompress {
+namespace NLzma {
+
+REGISTER_CODEC_E(LZMA,
+ CDecoder(),
+ CEncoder(),
+ 0x30101,
+ "LZMA")
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.cpp
new file mode 100644
index 0000000000..4820c0a7c0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.cpp
@@ -0,0 +1,170 @@
+// PpmdDecoder.cpp
+// 2009-03-11 : Igor Pavlov : Public domain
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+#include "../../../C/CpuArch.h"
+
+#include "../Common/StreamUtils.h"
+
+#include "PpmdDecoder.h"
+
+namespace NCompress {
+namespace NPpmd {
+
+static const UInt32 kBufSize = (1 << 20);
+
+enum
+{
+ kStatus_NeedInit,
+ kStatus_Normal,
+ kStatus_Finished,
+ kStatus_Error
+};
+
+CDecoder::~CDecoder()
+{
+ ::MidFree(_outBuf);
+ Ppmd7_Free(&_ppmd, &g_BigAlloc);
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)
+{
+ if (size < 5)
+ return E_INVALIDARG;
+ _order = props[0];
+ UInt32 memSize = GetUi32(props + 1);
+ if (_order < PPMD7_MIN_ORDER ||
+ _order > PPMD7_MAX_ORDER ||
+ memSize < PPMD7_MIN_MEM_SIZE ||
+ memSize > PPMD7_MAX_MEM_SIZE)
+ return E_NOTIMPL;
+ if (!_inStream.Alloc(1 << 20))
+ return E_OUTOFMEMORY;
+ if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc))
+ return E_OUTOFMEMORY;
+ return S_OK;
+}
+
+HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)
+{
+ switch (_status)
+ {
+ case kStatus_Finished: return S_OK;
+ case kStatus_Error: return S_FALSE;
+ case kStatus_NeedInit:
+ _inStream.Init();
+ if (!Ppmd7z_RangeDec_Init(&_rangeDec))
+ {
+ _status = kStatus_Error;
+ return S_FALSE;
+ }
+ _status = kStatus_Normal;
+ Ppmd7_Init(&_ppmd, _order);
+ break;
+ }
+ if (_outSizeDefined)
+ {
+ const UInt64 rem = _outSize - _processedSize;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+
+ UInt32 i;
+ int sym = 0;
+ for (i = 0; i != size; i++)
+ {
+ sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.vt);
+ if (_inStream.Extra || sym < 0)
+ break;
+ memStream[i] = (Byte)sym;
+ }
+
+ _processedSize += i;
+ if (_inStream.Extra)
+ {
+ _status = kStatus_Error;
+ return _inStream.Res;
+ }
+ if (sym < 0)
+ _status = (sym < -1) ? kStatus_Error : kStatus_Finished;
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ if (!_outBuf)
+ {
+ _outBuf = (Byte *)::MidAlloc(kBufSize);
+ if (!_outBuf)
+ return E_OUTOFMEMORY;
+ }
+
+ _inStream.Stream = inStream;
+ SetOutStreamSize(outSize);
+
+ do
+ {
+ const UInt64 startPos = _processedSize;
+ HRESULT res = CodeSpec(_outBuf, kBufSize);
+ size_t processed = (size_t)(_processedSize - startPos);
+ RINOK(WriteStream(outStream, _outBuf, processed));
+ RINOK(res);
+ if (_status == kStatus_Finished)
+ break;
+ if (progress)
+ {
+ UInt64 inSize = _inStream.GetProcessed();
+ RINOK(progress->SetRatioInfo(&inSize, &_processedSize));
+ }
+ }
+ while (!_outSizeDefined || _processedSize < _outSize);
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+{
+ _outSizeDefined = (outSize != NULL);
+ if (_outSizeDefined)
+ _outSize = *outSize;
+ _processedSize = 0;
+ _status = kStatus_NeedInit;
+ return S_OK;
+}
+
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = _inStream.GetProcessed();
+ return S_OK;
+}
+
+#ifndef NO_READ_FROM_CODER
+
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
+{
+ InSeqStream = inStream;
+ _inStream.Stream = inStream;
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::ReleaseInStream()
+{
+ InSeqStream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ const UInt64 startPos = _processedSize;
+ HRESULT res = CodeSpec((Byte *)data, size);
+ if (processedSize)
+ *processedSize = (UInt32)(_processedSize - startPos);
+ return res;
+}
+
+#endif
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.h
new file mode 100644
index 0000000000..3c2f493497
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.h
@@ -0,0 +1,86 @@
+// PpmdDecoder.h
+// 2009-03-11 : Igor Pavlov : Public domain
+
+#ifndef __COMPRESS_PPMD_DECODER_H
+#define __COMPRESS_PPMD_DECODER_H
+
+#include "../../../C/Ppmd7.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../Common/CWrappers.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NPpmd {
+
+class CDecoder :
+ public ICompressCoder,
+ public ICompressSetDecoderProperties2,
+ public ICompressGetInStreamProcessedSize,
+ #ifndef NO_READ_FROM_CODER
+ public ICompressSetInStream,
+ public ICompressSetOutStreamSize,
+ public ISequentialInStream,
+ #endif
+ public CMyUnknownImp
+{
+ Byte *_outBuf;
+ CPpmd7z_RangeDec _rangeDec;
+ CByteInBufWrap _inStream;
+ CPpmd7 _ppmd;
+
+ Byte _order;
+ bool _outSizeDefined;
+ int _status;
+ UInt64 _outSize;
+ UInt64 _processedSize;
+
+ HRESULT CodeSpec(Byte *memStream, UInt32 size);
+
+public:
+
+ #ifndef NO_READ_FROM_CODER
+ CMyComPtr<ISequentialInStream> InSeqStream;
+ #endif
+
+ MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
+ // MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
+ MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
+ #ifndef NO_READ_FROM_CODER
+ 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(SetDecoderProperties2)(const Byte *data, UInt32 size);
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+
+ STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+
+ #ifndef NO_READ_FROM_CODER
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+ STDMETHOD(ReleaseInStream)();
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ #endif
+
+ CDecoder(): _outBuf(NULL), _outSizeDefined(false)
+ {
+ Ppmd7z_RangeDec_CreateVTable(&_rangeDec);
+ _rangeDec.Stream = &_inStream.vt;
+ Ppmd7_Construct(&_ppmd);
+ }
+
+ ~CDecoder();
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.cpp
new file mode 100644
index 0000000000..0aef701d0e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.cpp
@@ -0,0 +1,152 @@
+// PpmdEncoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+#include "../../../C/CpuArch.h"
+
+#include "../Common/StreamUtils.h"
+
+#include "PpmdEncoder.h"
+
+namespace NCompress {
+namespace NPpmd {
+
+static const UInt32 kBufSize = (1 << 20);
+
+static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 };
+
+void CEncProps::Normalize(int level)
+{
+ if (level < 0) level = 5;
+ if (level > 9) level = 9;
+ if (MemSize == (UInt32)(Int32)-1)
+ MemSize = level >= 9 ? ((UInt32)192 << 20) : ((UInt32)1 << (level + 19));
+ const unsigned kMult = 16;
+ if (MemSize / kMult > ReduceSize)
+ {
+ for (unsigned i = 16; i <= 31; i++)
+ {
+ UInt32 m = (UInt32)1 << i;
+ if (ReduceSize <= m / kMult)
+ {
+ if (MemSize > m)
+ MemSize = m;
+ break;
+ }
+ }
+ }
+ if (Order == -1) Order = kOrders[(unsigned)level];
+}
+
+CEncoder::CEncoder():
+ _inBuf(NULL)
+{
+ _props.Normalize(-1);
+ _rangeEnc.Stream = &_outStream.vt;
+ Ppmd7_Construct(&_ppmd);
+}
+
+CEncoder::~CEncoder()
+{
+ ::MidFree(_inBuf);
+ Ppmd7_Free(&_ppmd, &g_BigAlloc);
+}
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ int level = -1;
+ CEncProps props;
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ PROPID propID = propIDs[i];
+ if (propID > NCoderPropID::kReduceSize)
+ continue;
+ if (propID == NCoderPropID::kReduceSize)
+ {
+ if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)
+ props.ReduceSize = (UInt32)prop.uhVal.QuadPart;
+ continue;
+ }
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ UInt32 v = (UInt32)prop.ulVal;
+ switch (propID)
+ {
+ case NCoderPropID::kUsedMemorySize:
+ if (v < (1 << 16) || v > PPMD7_MAX_MEM_SIZE || (v & 3) != 0)
+ return E_INVALIDARG;
+ props.MemSize = v;
+ break;
+ case NCoderPropID::kOrder:
+ if (v < 2 || v > 32)
+ return E_INVALIDARG;
+ props.Order = (Byte)v;
+ break;
+ case NCoderPropID::kNumThreads: break;
+ case NCoderPropID::kLevel: level = (int)v; break;
+ default: return E_INVALIDARG;
+ }
+ }
+ props.Normalize(level);
+ _props = props;
+ return S_OK;
+}
+
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+ const UInt32 kPropSize = 5;
+ Byte props[kPropSize];
+ props[0] = (Byte)_props.Order;
+ SetUi32(props + 1, _props.MemSize);
+ return WriteStream(outStream, props, kPropSize);
+}
+
+HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
+{
+ if (!_inBuf)
+ {
+ _inBuf = (Byte *)::MidAlloc(kBufSize);
+ if (!_inBuf)
+ return E_OUTOFMEMORY;
+ }
+ if (!_outStream.Alloc(1 << 20))
+ return E_OUTOFMEMORY;
+ if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc))
+ return E_OUTOFMEMORY;
+
+ _outStream.Stream = outStream;
+ _outStream.Init();
+
+ Ppmd7z_RangeEnc_Init(&_rangeEnc);
+ Ppmd7_Init(&_ppmd, _props.Order);
+
+ UInt64 processed = 0;
+ for (;;)
+ {
+ UInt32 size;
+ RINOK(inStream->Read(_inBuf, kBufSize, &size));
+ if (size == 0)
+ {
+ // We don't write EndMark in PPMD-7z.
+ // Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, -1);
+ Ppmd7z_RangeEnc_FlushData(&_rangeEnc);
+ return _outStream.Flush();
+ }
+ for (UInt32 i = 0; i < size; i++)
+ {
+ Ppmd7_EncodeSymbol(&_ppmd, &_rangeEnc, _inBuf[i]);
+ RINOK(_outStream.Res);
+ }
+ processed += size;
+ if (progress)
+ {
+ UInt64 outSize = _outStream.GetProcessed();
+ RINOK(progress->SetRatioInfo(&processed, &outSize));
+ }
+ }
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.h
new file mode 100644
index 0000000000..cdb0352b7b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.h
@@ -0,0 +1,58 @@
+// PpmdEncoder.h
+
+#ifndef __COMPRESS_PPMD_ENCODER_H
+#define __COMPRESS_PPMD_ENCODER_H
+
+#include "../../../C/Ppmd7.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+#include "../Common/CWrappers.h"
+
+namespace NCompress {
+namespace NPpmd {
+
+struct CEncProps
+{
+ UInt32 MemSize;
+ UInt32 ReduceSize;
+ int Order;
+
+ CEncProps()
+ {
+ MemSize = (UInt32)(Int32)-1;
+ ReduceSize = (UInt32)(Int32)-1;
+ Order = -1;
+ }
+ void Normalize(int level);
+};
+
+class CEncoder :
+ public ICompressCoder,
+ public ICompressSetCoderProperties,
+ public ICompressWriteCoderProperties,
+ public CMyUnknownImp
+{
+ Byte *_inBuf;
+ CByteOutBufWrap _outStream;
+ CPpmd7z_RangeEnc _rangeEnc;
+ CPpmd7 _ppmd;
+ CEncProps _props;
+public:
+ MY_UNKNOWN_IMP3(
+ ICompressCoder,
+ ICompressSetCoderProperties,
+ ICompressWriteCoderProperties)
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+ CEncoder();
+ ~CEncoder();
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdRegister.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdRegister.cpp
new file mode 100644
index 0000000000..c7486966cb
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/PpmdRegister.cpp
@@ -0,0 +1,22 @@
+// PpmdRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "PpmdDecoder.h"
+
+#ifndef EXTRACT_ONLY
+#include "PpmdEncoder.h"
+#endif
+
+namespace NCompress {
+namespace NPpmd {
+
+REGISTER_CODEC_E(PPMD,
+ CDecoder(),
+ CEncoder(),
+ 0x30401,
+ "PPMD")
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Compress/StdAfx.h
new file mode 100644
index 0000000000..42a088f121
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.cpp
new file mode 100644
index 0000000000..4fcd09fe82
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.cpp
@@ -0,0 +1,150 @@
+// XzDecoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../Common/CWrappers.h"
+
+#include "XzDecoder.h"
+
+namespace NCompress {
+namespace NXz {
+
+#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+static HRESULT SResToHRESULT_Code(SRes res) throw()
+{
+ if (res < 0)
+ return res;
+ switch (res)
+ {
+ case SZ_OK: return S_OK;
+ case SZ_ERROR_MEM: return E_OUTOFMEMORY;
+ case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
+ }
+ return S_FALSE;
+}
+
+
+HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
+ const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress)
+{
+ MainDecodeSRes = S_OK;
+ MainDecodeSRes_wasUsed = false;
+ XzStatInfo_Clear(&Stat);
+
+ if (!xz)
+ {
+ xz = XzDecMt_Create(&g_Alloc, &g_MidAlloc);
+ if (!xz)
+ return E_OUTOFMEMORY;
+ }
+
+ CXzDecMtProps props;
+ XzDecMtProps_Init(&props);
+
+ int isMT = False;
+
+ #ifndef _7ZIP_ST
+ {
+ props.numThreads = 1;
+ UInt32 numThreads = _numThreads;
+
+ if (_tryMt && numThreads > 1)
+ {
+ size_t memUsage = (size_t)_memUsage;
+ if (memUsage != _memUsage)
+ memUsage = (size_t)0 - 1;
+ props.memUseMax = memUsage;
+ isMT = (numThreads > 1);
+ }
+
+ props.numThreads = numThreads;
+ }
+ #endif
+
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(seqInStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res = XzDecMt_Decode(xz,
+ &props,
+ outSizeLimit, finishStream,
+ &outWrap.vt,
+ &inWrap.vt,
+ &Stat,
+ &isMT,
+ progress ? &progressWrap.vt : NULL);
+
+ MainDecodeSRes = res;
+
+ #ifndef _7ZIP_ST
+ // _tryMt = isMT;
+ #endif
+
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+ RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)
+
+ // return E_OUTOFMEMORY;
+
+ MainDecodeSRes_wasUsed = true;
+
+ if (res == SZ_OK && finishStream)
+ {
+ /*
+ if (inSize && *inSize != Stat.PhySize)
+ res = SZ_ERROR_DATA;
+ */
+ if (outSizeLimit && *outSizeLimit != outWrap.Processed)
+ res = SZ_ERROR_DATA;
+ }
+
+ return SResToHRESULT_Code(res);
+}
+
+
+HRESULT CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ return Decode(inStream, outStream, outSize, _finishStream, progress);
+}
+
+STDMETHODIMP CComDecoder::SetFinishMode(UInt32 finishMode)
+{
+ _finishStream = (finishMode != 0);
+ return S_OK;
+}
+
+STDMETHODIMP CComDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+ *value = Stat.InSize;
+ return S_OK;
+}
+
+#ifndef _7ZIP_ST
+
+STDMETHODIMP CComDecoder::SetNumberOfThreads(UInt32 numThreads)
+{
+ _numThreads = numThreads;
+ return S_OK;
+}
+
+STDMETHODIMP CComDecoder::SetMemLimit(UInt64 memUsage)
+{
+ _memUsage = memUsage;
+ return S_OK;
+}
+
+#endif
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.h
new file mode 100644
index 0000000000..76694eec07
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.h
@@ -0,0 +1,92 @@
+// XzDecoder.h
+
+#ifndef __XZ_DECODER_H
+#define __XZ_DECODER_H
+
+#include "../../../C/Xz.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NXz {
+
+struct CDecoder
+{
+ CXzDecMtHandle xz;
+ int _tryMt;
+ UInt32 _numThreads;
+ UInt64 _memUsage;
+
+ SRes MainDecodeSRes; // it's not HRESULT
+ bool MainDecodeSRes_wasUsed;
+ CXzStatInfo Stat;
+
+ CDecoder():
+ xz(NULL),
+ _tryMt(True),
+ _numThreads(1),
+ _memUsage((UInt64)(sizeof(size_t)) << 28),
+ MainDecodeSRes(SZ_OK),
+ MainDecodeSRes_wasUsed(false)
+ {}
+
+ ~CDecoder()
+ {
+ if (xz)
+ XzDecMt_Destroy(xz);
+ }
+
+ /* 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,
+ const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *compressProgress);
+};
+
+
+class CComDecoder:
+ public ICompressCoder,
+ public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize,
+
+ #ifndef _7ZIP_ST
+ public ICompressSetCoderMt,
+ public ICompressSetMemLimit,
+ #endif
+
+ public CMyUnknownImp,
+ public CDecoder
+{
+ bool _finishStream;
+
+public:
+ MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
+
+ MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
+ MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
+
+ #ifndef _7ZIP_ST
+ MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetMemLimit)
+ #endif
+
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetFinishMode)(UInt32 finishMode);
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+
+ #ifndef _7ZIP_ST
+ STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
+ STDMETHOD(SetMemLimit)(UInt64 memUsage);
+ #endif
+
+ CComDecoder(): _finishStream(false) {}
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.cpp b/other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.cpp
new file mode 100644
index 0000000000..458a928c99
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.cpp
@@ -0,0 +1,245 @@
+// XzEncoder.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+
+#include "../../Common/MyString.h"
+#include "../../Common/StringToInt.h"
+
+#include "../Common/CWrappers.h"
+#include "../Common/StreamUtils.h"
+
+#include "XzEncoder.h"
+
+namespace NCompress {
+
+namespace NLzma2 {
+
+HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
+
+}
+
+namespace NXz {
+
+void CEncoder::InitCoderProps()
+{
+ XzProps_Init(&xzProps);
+}
+
+CEncoder::CEncoder()
+{
+ XzProps_Init(&xzProps);
+ _encoder = NULL;
+ _encoder = XzEnc_Create(&g_Alloc, &g_BigAlloc);
+ if (!_encoder)
+ throw 1;
+}
+
+CEncoder::~CEncoder()
+{
+ if (_encoder)
+ XzEnc_Destroy(_encoder);
+}
+
+
+struct CMethodNamePair
+{
+ UInt32 Id;
+ const char *Name;
+};
+
+static const CMethodNamePair g_NamePairs[] =
+{
+ { XZ_ID_Delta, "Delta" },
+ { XZ_ID_X86, "BCJ" },
+ { XZ_ID_PPC, "PPC" },
+ { XZ_ID_IA64, "IA64" },
+ { XZ_ID_ARM, "ARM" },
+ { XZ_ID_ARMT, "ARMT" },
+ { XZ_ID_SPARC, "SPARC" }
+ // { XZ_ID_LZMA2, "LZMA2" }
+};
+
+static int FilterIdFromName(const wchar_t *name)
+{
+ for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++)
+ {
+ const CMethodNamePair &pair = g_NamePairs[i];
+ if (StringsAreEqualNoCase_Ascii(name, pair.Name))
+ return (int)pair.Id;
+ }
+ return -1;
+}
+
+
+HRESULT CEncoder::SetCheckSize(UInt32 checkSizeInBytes)
+{
+ unsigned id;
+ switch (checkSizeInBytes)
+ {
+ case 0: id = XZ_CHECK_NO; break;
+ case 4: id = XZ_CHECK_CRC32; break;
+ case 8: id = XZ_CHECK_CRC64; break;
+ case 32: id = XZ_CHECK_SHA256; break;
+ default: return E_INVALIDARG;
+ }
+ xzProps.checkId = id;
+ return S_OK;
+}
+
+
+HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop)
+{
+ if (propID == NCoderPropID::kNumThreads)
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ xzProps.numTotalThreads = (int)(prop.ulVal);
+ return S_OK;
+ }
+
+ if (propID == NCoderPropID::kCheckSize)
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ return SetCheckSize(prop.ulVal);
+ }
+
+ if (propID == NCoderPropID::kBlockSize2)
+ {
+ if (prop.vt == VT_UI4)
+ xzProps.blockSize = prop.ulVal;
+ else if (prop.vt == VT_UI8)
+ xzProps.blockSize = prop.uhVal.QuadPart;
+ else
+ return E_INVALIDARG;
+ return S_OK;
+ }
+
+ if (propID == NCoderPropID::kReduceSize)
+ {
+ if (prop.vt == VT_UI8)
+ xzProps.reduceSize = prop.uhVal.QuadPart;
+ else
+ return E_INVALIDARG;
+ return S_OK;
+ }
+
+ if (propID == NCoderPropID::kFilter)
+ {
+ if (prop.vt == VT_UI4)
+ {
+ UInt32 id32 = prop.ulVal;
+ if (id32 == XZ_ID_Delta)
+ return E_INVALIDARG;
+ xzProps.filterProps.id = prop.ulVal;
+ }
+ else
+ {
+ if (prop.vt != VT_BSTR)
+ return E_INVALIDARG;
+
+ const wchar_t *name = prop.bstrVal;
+ const wchar_t *end;
+
+ UInt32 id32 = ConvertStringToUInt32(name, &end);
+
+ if (end != name)
+ name = end;
+ else
+ {
+ if (IsString1PrefixedByString2_NoCase_Ascii(name, "Delta"))
+ {
+ name += 5; // strlen("Delta");
+ id32 = XZ_ID_Delta;
+ }
+ else
+ {
+ int filterId = FilterIdFromName(prop.bstrVal);
+ if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */)
+ return E_INVALIDARG;
+ id32 = filterId;
+ }
+ }
+
+ if (id32 == XZ_ID_Delta)
+ {
+ wchar_t c = *name;
+ if (c != '-' && c != ':')
+ return E_INVALIDARG;
+ name++;
+ UInt32 delta = ConvertStringToUInt32(name, &end);
+ if (end == name || *end != 0 || delta == 0 || delta > 256)
+ return E_INVALIDARG;
+ xzProps.filterProps.delta = delta;
+ }
+
+ xzProps.filterProps.id = id32;
+ }
+
+ return S_OK;
+ }
+
+ return NLzma2::SetLzma2Prop(propID, prop, xzProps.lzma2Props);
+}
+
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ XzProps_Init(&xzProps);
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ RINOK(SetCoderProp(propIDs[i], coderProps[i]));
+ }
+
+ return S_OK;
+ // return SResToHRESULT(XzEnc_SetProps(_encoder, &xzProps));
+}
+
+
+STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,
+ const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ PROPID propID = propIDs[i];
+ if (propID == NCoderPropID::kExpectedDataSize)
+ if (prop.vt == VT_UI8)
+ XzEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);
+ }
+ return S_OK;
+}
+
+
+#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \
+ if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;
+
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
+{
+ CSeqInStreamWrap inWrap;
+ CSeqOutStreamWrap outWrap;
+ CCompressProgressWrap progressWrap;
+
+ inWrap.Init(inStream);
+ outWrap.Init(outStream);
+ progressWrap.Init(progress);
+
+ SRes res = XzEnc_SetProps(_encoder, &xzProps);
+ if (res == SZ_OK)
+ res = XzEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL);
+
+ // SRes res = Xz_Encode(&outWrap.vt, &inWrap.vt, &xzProps, progress ? &progressWrap.vt : NULL);
+
+ RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)
+ RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)
+ RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)
+
+ return SResToHRESULT(res);
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.h b/other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.h
new file mode 100644
index 0000000000..79d81f7931
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.h
@@ -0,0 +1,46 @@
+// XzEncoder.h
+
+#ifndef __XZ_ENCODER_H
+#define __XZ_ENCODER_H
+
+#include "../../../C/XzEnc.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCompress {
+namespace NXz {
+
+
+class CEncoder:
+ public ICompressCoder,
+ public ICompressSetCoderProperties,
+ public ICompressSetCoderPropertiesOpt,
+ public CMyUnknownImp
+{
+ CXzEncHandle _encoder;
+public:
+ CXzProps xzProps;
+
+ MY_UNKNOWN_IMP3(
+ ICompressCoder,
+ ICompressSetCoderProperties,
+ ICompressSetCoderPropertiesOpt)
+
+ void InitCoderProps();
+ HRESULT SetCheckSize(UInt32 checkSizeInBytes);
+ HRESULT SetCoderProp(PROPID propID, const PROPVARIANT &prop);
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+ STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+
+ CEncoder();
+ virtual ~CEncoder();
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crc.mak b/other-licenses/7zstub/src/CPP/7zip/Crc.mak
new file mode 100644
index 0000000000..19a7f7b136
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crc.mak
@@ -0,0 +1,8 @@
+C_OBJS = $(C_OBJS) \
+ $O\7zCrc.obj
+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" || "$(CPU)" == "ARM64"
+C_OBJS = $(C_OBJS) \
+!ELSE
+ASM_OBJS = $(ASM_OBJS) \
+!ENDIF
+ $O\7zCrcOpt.obj
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crc64.mak b/other-licenses/7zstub/src/CPP/7zip/Crc64.mak
new file mode 100644
index 0000000000..1ac6a0ce6c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crc64.mak
@@ -0,0 +1,8 @@
+C_OBJS = $(C_OBJS) \
+ $O\XzCrc64.obj
+!IF "$(CPU)" == "IA64" || "$(CPU)" == "MIPS" || "$(CPU)" == "ARM" || "$(CPU)" == "ARM64"
+C_OBJS = $(C_OBJS) \
+!ELSE
+ASM_OBJS = $(ASM_OBJS) \
+!ENDIF
+ $O\XzCrc64Opt.obj
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.cpp b/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.cpp
new file mode 100644
index 0000000000..f412bf9d14
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.cpp
@@ -0,0 +1,280 @@
+// 7zAes.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Sha256.h"
+
+#include "../../Common/ComTry.h"
+
+#ifndef _7ZIP_ST
+#include "../../Windows/Synchronization.h"
+#endif
+
+#include "../Common/StreamUtils.h"
+
+#include "7zAes.h"
+#include "MyAes.h"
+
+#ifndef EXTRACT_ONLY
+#include "RandGen.h"
+#endif
+
+namespace NCrypto {
+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 (unsigned i = 0; i < SaltSize; i++)
+ if (Salt[i] != a.Salt[i])
+ return false;
+ return (Password == a.Password);
+}
+
+void CKeyInfo::CalcKey()
+{
+ if (NumCyclesPower == 0x3F)
+ {
+ unsigned pos;
+ for (pos = 0; pos < SaltSize; pos++)
+ Key[pos] = Salt[pos];
+ 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);
+
+ 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, buf, bufSize);
+ for (unsigned i = 0; i < 8; i++)
+ if (++(ctr[i]) != 0)
+ break;
+ }
+ while (--numRounds != 0);
+
+ Sha256_Final(&sha, Key);
+ }
+}
+
+bool CKeyInfoCache::GetKey(CKeyInfo &key)
+{
+ FOR_VECTOR (i, Keys)
+ {
+ const CKeyInfo &cached = Keys[i];
+ if (key.IsEqualTo(cached))
+ {
+ for (unsigned j = 0; j < kKeySize; j++)
+ key.Key[j] = cached.Key[j];
+ if (i != 0)
+ Keys.MoveToFront(i);
+ return true;
+ }
+ }
+ return false;
+}
+
+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 (Keys.Size() >= Size)
+ Keys.DeleteBack();
+ Keys.Insert(0, key);
+}
+
+static CKeyInfoCache g_GlobalKeyCache(32);
+
+#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 (unsigned i = 0; i < sizeof(_iv); i++)
+ _iv[i] = 0;
+}
+
+void CBase::PrepareKey()
+{
+ // BCJ2 threads use same password. So we use long lock.
+ MT_LOCK
+
+ bool finded = false;
+ if (!_cachedKeys.GetKey(_key))
+ {
+ finded = g_GlobalKeyCache.GetKey(_key);
+ if (!finded)
+ _key.CalcKey();
+ _cachedKeys.Add(_key);
+ }
+ if (!finded)
+ g_GlobalKeyCache.FindAndAdd(_key);
+}
+
+#ifndef EXTRACT_ONLY
+
+/*
+STDMETHODIMP CEncoder::ResetSalt()
+{
+ _key.SaltSize = 4;
+ g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
+ return S_OK;
+}
+*/
+
+STDMETHODIMP CEncoder::ResetInitVector()
+{
+ for (unsigned i = 0; i < sizeof(_iv); i++)
+ _iv[i] = 0;
+ _ivSize = 8;
+ g_RandomGenerator.Generate(_iv, _ivSize);
+ return S_OK;
+}
+
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+ Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)];
+ unsigned propsSize = 1;
+
+ props[0] = (Byte)(_key.NumCyclesPower
+ | (_key.SaltSize == 0 ? 0 : (1 << 7))
+ | (_ivSize == 0 ? 0 : (1 << 6)));
+
+ if (_key.SaltSize != 0 || _ivSize != 0)
+ {
+ 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;
+ }
+
+ return WriteStream(outStream, props, propsSize);
+}
+
+CEncoder::CEncoder()
+{
+ // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
+ // _key.NumCyclesPower = 0x3F;
+ _key.NumCyclesPower = 19;
+ _aesFilter = new CAesCbcEncoder(kKeySize);
+}
+
+#endif
+
+CDecoder::CDecoder()
+{
+ _aesFilter = new CAesCbcDecoder(kKeySize);
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
+{
+ _key.ClearProps();
+
+ _ivSize = 0;
+ unsigned i;
+ for (i = 0; i < sizeof(_iv); i++)
+ _iv[i] = 0;
+
+ if (size == 0)
+ return S_OK;
+
+ Byte b0 = data[0];
+
+ _key.NumCyclesPower = b0 & 0x3F;
+ if ((b0 & 0xC0) == 0)
+ return size == 1 ? S_OK : E_INVALIDARG;
+
+ if (size <= 1)
+ return E_INVALIDARG;
+
+ Byte b1 = data[1];
+
+ unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4);
+ unsigned ivSize = ((b0 >> 6) & 1) + (b1 & 0x0F);
+
+ if (size != 2 + saltSize + ivSize)
+ return E_INVALIDARG;
+ _key.SaltSize = saltSize;
+ data += 2;
+ for (i = 0; i < saltSize; i++)
+ _key.Salt[i] = *data++;
+ for (i = 0; i < ivSize; i++)
+ _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()
+{
+ COM_TRY_BEGIN
+
+ PrepareKey();
+ CMyComPtr<ICryptoProperties> cp;
+ RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
+ 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)
+{
+ return _aesFilter->Filter(data, size);
+}
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.h b/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.h
new file mode 100644
index 0000000000..5a09436079
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.h
@@ -0,0 +1,118 @@
+// 7zAes.h
+
+#ifndef __CRYPTO_7Z_AES_H
+#define __CRYPTO_7Z_AES_H
+
+#include "../../Common/MyBuffer.h"
+#include "../../Common/MyCom.h"
+#include "../../Common/MyVector.h"
+
+#include "../ICoder.h"
+#include "../IPassword.h"
+
+namespace NCrypto {
+namespace N7z {
+
+const unsigned kKeySize = 32;
+const unsigned kSaltSizeMax = 16;
+const unsigned kIvSizeMax = 16; // AES_BLOCK_SIZE;
+
+class CKeyInfo
+{
+public:
+ unsigned NumCyclesPower;
+ unsigned SaltSize;
+ Byte Salt[kSaltSizeMax];
+ CByteBuffer Password;
+ Byte Key[kKeySize];
+
+ bool IsEqualTo(const CKeyInfo &a) const;
+ void CalcKey();
+
+ CKeyInfo() { ClearProps(); }
+ void ClearProps()
+ {
+ NumCyclesPower = 0;
+ SaltSize = 0;
+ for (unsigned i = 0; i < sizeof(Salt); i++)
+ Salt[i] = 0;
+ }
+};
+
+class CKeyInfoCache
+{
+ unsigned Size;
+ CObjectVector<CKeyInfo> Keys;
+public:
+ CKeyInfoCache(unsigned size): Size(size) {}
+ bool GetKey(CKeyInfo &key);
+ void Add(const CKeyInfo &key);
+ void FindAndAdd(const CKeyInfo &key);
+};
+
+class CBase
+{
+ CKeyInfoCache _cachedKeys;
+protected:
+ CKeyInfo _key;
+ Byte _iv[kIvSizeMax];
+ unsigned _ivSize;
+
+ void PrepareKey();
+ CBase();
+};
+
+class CBaseCoder:
+ public ICompressFilter,
+ public ICryptoSetPassword,
+ public CMyUnknownImp,
+ public CBase
+{
+protected:
+ CMyComPtr<ICompressFilter> _aesFilter;
+
+public:
+ INTERFACE_ICompressFilter(;)
+
+ STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
+};
+
+#ifndef EXTRACT_ONLY
+
+class CEncoder:
+ public CBaseCoder,
+ public ICompressWriteCoderProperties,
+ // public ICryptoResetSalt,
+ public ICryptoResetInitVector
+{
+public:
+ MY_UNKNOWN_IMP4(
+ ICompressFilter,
+ ICryptoSetPassword,
+ ICompressWriteCoderProperties,
+ // ICryptoResetSalt,
+ ICryptoResetInitVector)
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+ // STDMETHOD(ResetSalt)();
+ STDMETHOD(ResetInitVector)();
+ CEncoder();
+};
+
+#endif
+
+class CDecoder:
+ public CBaseCoder,
+ public ICompressSetDecoderProperties2
+{
+public:
+ MY_UNKNOWN_IMP3(
+ ICompressFilter,
+ ICryptoSetPassword,
+ ICompressSetDecoderProperties2)
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+ CDecoder();
+};
+
+}}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAesRegister.cpp b/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAesRegister.cpp
new file mode 100644
index 0000000000..c0b2060939
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/7zAesRegister.cpp
@@ -0,0 +1,17 @@
+// 7zAesRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "7zAes.h"
+
+namespace NCrypto {
+namespace N7z {
+
+REGISTER_FILTER_E(7zAES,
+ CDecoder(),
+ CEncoder(),
+ 0x6F10701, "7zAES")
+
+}}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.cpp b/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.cpp
new file mode 100644
index 0000000000..1d399d707f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.cpp
@@ -0,0 +1,112 @@
+// Crypto/MyAes.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "MyAes.h"
+
+namespace NCrypto {
+
+static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit;
+
+CAesCbcCoder::CAesCbcCoder(bool encodeMode, unsigned keySize):
+ _keySize(keySize),
+ _keyIsSet(false),
+ _encodeMode(encodeMode)
+{
+ _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32);
+ memset(_iv, 0, AES_BLOCK_SIZE);
+ SetFunctions(0);
+}
+
+STDMETHODIMP CAesCbcCoder::Init()
+{
+ AesCbc_Init(_aes + _offset, _iv);
+ return _keyIsSet ? S_OK : E_FAIL;
+}
+
+STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size)
+{
+ if (!_keyIsSet)
+ return 0;
+ if (size == 0)
+ return 0;
+ if (size < AES_BLOCK_SIZE)
+ return AES_BLOCK_SIZE;
+ size >>= 4;
+ _codeFunc(_aes + _offset, data, size);
+ return size << 4;
+}
+
+STDMETHODIMP CAesCbcCoder::SetKey(const Byte *data, UInt32 size)
+{
+ if ((size & 0x7) != 0 || size < 16 || size > 32)
+ return E_INVALIDARG;
+ if (_keySize != 0 && size != _keySize)
+ return E_INVALIDARG;
+ AES_SET_KEY_FUNC setKeyFunc = _encodeMode ? Aes_SetKey_Enc : Aes_SetKey_Dec;
+ setKeyFunc(_aes + _offset + 4, data, size);
+ _keyIsSet = true;
+ return S_OK;
+}
+
+STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size)
+{
+ if (size != AES_BLOCK_SIZE)
+ return E_INVALIDARG;
+ memcpy(_iv, data, size);
+ CAesCbcCoder::Init(); // don't call virtual function here !!!
+ return S_OK;
+}
+
+EXTERN_C_BEGIN
+
+void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
+void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
+void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
+
+void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
+void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
+void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
+
+EXTERN_C_END
+
+bool CAesCbcCoder::SetFunctions(UInt32 algo)
+{
+ _codeFunc = _encodeMode ?
+ g_AesCbc_Encode :
+ g_AesCbc_Decode;
+ if (algo == 1)
+ {
+ _codeFunc = _encodeMode ?
+ AesCbc_Encode:
+ AesCbc_Decode;
+ }
+ if (algo == 2)
+ {
+ #ifdef MY_CPU_X86_OR_AMD64
+ if (g_AesCbc_Encode != AesCbc_Encode_Intel)
+ #endif
+ return false;
+ }
+ return true;
+}
+
+STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
+{
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ const PROPVARIANT &prop = coderProps[i];
+ if (propIDs[i] == NCoderPropID::kDefaultProp)
+ {
+ if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ if (!SetFunctions(prop.ulVal))
+ return E_NOTIMPL;
+ }
+ }
+ return S_OK;
+}
+
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.h b/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.h
new file mode 100644
index 0000000000..8d5ed98c3f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.h
@@ -0,0 +1,57 @@
+// Crypto/MyAes.h
+
+#ifndef __CRYPTO_MY_AES_H
+#define __CRYPTO_MY_AES_H
+
+#include "../../../C/Aes.h"
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+
+namespace NCrypto {
+
+class CAesCbcCoder:
+ public ICompressFilter,
+ public ICryptoProperties,
+ public ICompressSetCoderProperties,
+ public CMyUnknownImp
+{
+ AES_CODE_FUNC _codeFunc;
+ unsigned _offset;
+ unsigned _keySize;
+ bool _keyIsSet;
+ bool _encodeMode;
+ UInt32 _aes[AES_NUM_IVMRK_WORDS + 3];
+ Byte _iv[AES_BLOCK_SIZE];
+
+ bool SetFunctions(UInt32 algo);
+
+public:
+ CAesCbcCoder(bool encodeMode, unsigned keySize);
+
+ virtual ~CAesCbcCoder() {}; // we need virtual destructor for derived classes
+
+ MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties)
+
+ 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);
+};
+
+struct CAesCbcEncoder: public CAesCbcCoder
+{
+ CAesCbcEncoder(unsigned keySize = 0): CAesCbcCoder(true, keySize) {}
+};
+
+struct CAesCbcDecoder: public CAesCbcCoder
+{
+ CAesCbcDecoder(unsigned keySize = 0): CAesCbcCoder(false, keySize) {}
+};
+
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAesReg.cpp b/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAesReg.cpp
new file mode 100644
index 0000000000..3427ad6257
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/MyAesReg.cpp
@@ -0,0 +1,16 @@
+// MyAesReg.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/RegisterCodec.h"
+
+#include "MyAes.h"
+
+namespace NCrypto {
+
+REGISTER_FILTER_E(AES256CBC,
+ CAesCbcDecoder(32),
+ CAesCbcEncoder(32),
+ 0x6F00181, "AES256CBC")
+
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.cpp b/other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.cpp
new file mode 100644
index 0000000000..542f39bd56
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.cpp
@@ -0,0 +1,124 @@
+// RandGen.cpp
+
+#include "StdAfx.h"
+
+#ifndef _7ZIP_ST
+#include "../../Windows/Synchronization.h"
+#endif
+
+#include "RandGen.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#define USE_POSIX_TIME
+#define USE_POSIX_TIME2
+#endif
+
+#ifdef USE_POSIX_TIME
+#include <time.h>
+#ifdef USE_POSIX_TIME2
+#include <sys/time.h>
+#endif
+#endif
+
+// This is not very good random number generator.
+// Please use it only for salt.
+// First generated data block depends from timer and processID.
+// Other generated data blocks depend from previous state
+// Maybe it's possible to restore original timer value from generated value.
+
+#define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x));
+
+void CRandomGenerator::Init()
+{
+ CSha256 hash;
+ Sha256_Init(&hash);
+
+ #ifdef _WIN32
+ DWORD w = ::GetCurrentProcessId();
+ HASH_UPD(w);
+ w = ::GetCurrentThreadId();
+ HASH_UPD(w);
+ #else
+ pid_t pid = getpid();
+ HASH_UPD(pid);
+ pid = getppid();
+ HASH_UPD(pid);
+ #endif
+
+ for (unsigned i = 0; i <
+ #ifdef _DEBUG
+ 2;
+ #else
+ 1000;
+ #endif
+ i++)
+ {
+ #ifdef _WIN32
+ LARGE_INTEGER v;
+ if (::QueryPerformanceCounter(&v))
+ HASH_UPD(v.QuadPart);
+ #endif
+
+ #ifdef USE_POSIX_TIME
+ #ifdef USE_POSIX_TIME2
+ timeval v;
+ if (gettimeofday(&v, 0) == 0)
+ {
+ HASH_UPD(v.tv_sec);
+ HASH_UPD(v.tv_usec);
+ }
+ #endif
+ time_t v2 = time(NULL);
+ HASH_UPD(v2);
+ #endif
+
+ #ifdef _WIN32
+ DWORD tickCount = ::GetTickCount();
+ HASH_UPD(tickCount);
+ #endif
+
+ for (unsigned j = 0; j < 100; j++)
+ {
+ Sha256_Final(&hash, _buff);
+ Sha256_Init(&hash);
+ Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
+ }
+ }
+ Sha256_Final(&hash, _buff);
+ _needInit = false;
+}
+
+#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)
+{
+ MT_LOCK
+
+ if (_needInit)
+ Init();
+ while (size != 0)
+ {
+ CSha256 hash;
+
+ Sha256_Init(&hash);
+ Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
+ Sha256_Final(&hash, _buff);
+
+ Sha256_Init(&hash);
+ UInt32 salt = 0xF672ABD1;
+ HASH_UPD(salt);
+ 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--)
+ *data++ = buff[i];
+ }
+}
+
+CRandomGenerator g_RandomGenerator;
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.h b/other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.h
new file mode 100644
index 0000000000..ff44450f8f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.h
@@ -0,0 +1,21 @@
+// RandGen.h
+
+#ifndef __CRYPTO_RAND_GEN_H
+#define __CRYPTO_RAND_GEN_H
+
+#include "../../../C/Sha256.h"
+
+class CRandomGenerator
+{
+ Byte _buff[SHA256_DIGEST_SIZE];
+ bool _needInit;
+
+ void Init();
+public:
+ CRandomGenerator(): _needInit(true) {};
+ void Generate(Byte *data, unsigned size);
+};
+
+extern CRandomGenerator g_RandomGenerator;
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/Crypto/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/Crypto/StdAfx.h
new file mode 100644
index 0000000000..42a088f121
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Crypto/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/GuiCommon.rc b/other-licenses/7zstub/src/CPP/7zip/GuiCommon.rc
new file mode 100644
index 0000000000..565ee702ef
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/GuiCommon.rc
@@ -0,0 +1,84 @@
+#include <windows.h>
+
+// #include <winnt.h>
+// #include <WinUser.h>
+
+// for Windows CE:
+#include <CommCtrl.h>
+
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#undef m
+#undef bxs
+#undef bys
+#undef bxsDots
+#undef y
+#undef xc
+#undef yc
+#undef xs
+#undef ys
+#undef bx
+#undef bx1
+#undef bx2
+#undef bx3
+#undef by
+#undef by1
+#undef by2
+#undef by3
+#undef gSpace
+#undef gSize
+#undef marg2
+#undef marg3
+
+#undef MY_DIALOG
+#undef MY_RESIZE_DIALOG
+#undef MY_PAGE
+
+#define m 8
+#define bxs 64
+#define bys 16
+#define bxsDots 20
+
+#define xs (xc + m + m)
+#define ys (yc + m + m)
+
+#define bx1 (xs - m - bxs)
+#define bx2 (bx1 - m - bxs)
+#define bx3 (bx2 - m - bxs)
+#define bx bx1
+
+#define by1 (ys - m - bys)
+#define by2 (by1 - m - bys)
+#define by by1
+
+
+#define MY_MODAL_DIALOG_STYLE STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+
+#define MY_MODAL_RESIZE_DIALOG_STYLE MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_THICKFRAME
+
+#define MY_PAGE_STYLE STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+
+#define MY_FONT FONT 8, "MS Shell Dlg"
+
+#define SMALL_PAGE_SIZE_X 120
+
+// #define MY_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+// #define MY_RESIZE_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
+#define MY_PAGE DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
+
+#define OK_CANCEL \
+ DEFPUSHBUTTON "OK", IDOK, bx2, by, bxs, bys \
+ PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
+
+#define MY_BUTTON__CLOSE \
+ DEFPUSHBUTTON "&Close", IDCLOSE, bx1, by, bxs, bys
+
+
+#define MY_COMBO CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+#define MY_COMBO_SORTED MY_COMBO | CBS_SORT
+#define MY_COMBO_WITH_EDIT CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+
+#define MY_CHECKBOX "Button", BS_AUTOCHECKBOX | WS_TABSTOP
+
+#define MY_TEXT_NOPREFIX 8, SS_NOPREFIX
diff --git a/other-licenses/7zstub/src/CPP/7zip/Guid.txt b/other-licenses/7zstub/src/CPP/7zip/Guid.txt
new file mode 100644
index 0000000000..e5e06126f1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/Guid.txt
@@ -0,0 +1,220 @@
+{23170F69-40C1-278A-0000-00yy00xx0000}
+
+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
+
+03 IStream.h
+
+ 01 ISequentialInStream
+ 02 ISequentialOutStream
+ 03 IInStream
+ 04 IOutStream
+ 06 IStreamGetSize
+ 07 IOutStreamFinish
+ 08 IStreamGetProps
+ 09 IStreamGetProps2
+
+
+04 ICoder.h
+
+ 04 ICompressProgressInfo
+ 05 ICompressCoder
+ 18 ICompressCoder2
+ 1F ICompressSetCoderPropertiesOpt
+ 20 ICompressSetCoderProperties
+ 21 ICompressSetDecoderProperties //
+ 22 ICompressSetDecoderProperties2
+ 23 ICompressWriteCoderProperties
+ 24 ICompressGetInStreamProcessedSize
+ 25 ICompressSetCoderMt
+ 26 ICompressSetFinishMode
+ 27 ICompressGetInStreamProcessedSize2
+ 28 ICompressSetMemLimit
+
+ 30 ICompressGetSubStreamSize
+ 31 ICompressSetInStream
+ 32 ICompressSetOutStream
+// 33 ICompressSetInStreamSize
+ 34 ICompressSetOutStreamSize
+ 35 ICompressSetBufSize
+ 36 ICompressInitEncoder
+ 37 ICompressSetInStream2
+// 38 ICompressSetOutStream2
+// 39 SetInStreamSize2
+// 3A SetOutStreamSize2
+
+ 40 ICompressFilter
+ 60 ICompressCodecsInfo
+ 61 ISetCompressCodecsInfo
+ 80 ICryptoProperties
+ 88 ICryptoResetSalt
+ 8C ICryptoResetInitVector
+ 90 ICryptoSetPassword
+ A0 ICryptoSetCRC
+ C0 IHasher
+ C1 IHashers
+
+
+05 IPassword.h
+
+ 10 ICryptoGetTextPassword
+ 11 ICryptoGetTextPassword2
+
+
+06 IArchive.h
+
+ 03 ISetProperties
+ 04 IArchiveKeepModeForNextOpen
+ 05 IArchiveAllowTail
+
+ 10 IArchiveOpenCallback
+
+ 20 IArchiveExtractCallback
+ 21 IArchiveExtractCallbackMessage
+
+ 30 IArchiveOpenVolumeCallback
+ 40 IInArchiveGetStream
+ 50 IArchiveOpenSetSubArchiveName
+ 60 IInArchive
+ 61 IArchiveOpenSeq
+ 70 IArchiveGetRawProps
+ 71 IArchiveGetRootProps
+
+ 80 IArchiveUpdateCallback
+ 82 IArchiveUpdateCallback2
+ 83 IArchiveUpdateCallbackFile
+
+ A0 IOutArchive
+
+
+
+08 IFolder.h
+
+ 00 IFolderFolder
+ 01 IEnumProperties
+ 02 IFolderGetTypeID
+ 03 IFolderGetPath
+ 04 IFolderWasChanged
+ 05 // IFolderReload
+ 06 // IFolderOperations old
+ 07 IFolderGetSystemIconIndex
+ 08 IFolderGetItemFullSize
+ 09 IFolderClone
+ 0A IFolderSetFlatMode
+ 0B IFolderOperationsExtractCallback
+ 0C //
+ 0D //
+ 0E IFolderProperties
+ 0F
+ 10 IFolderArcProps
+ 11 IGetFolderArcProps
+ 12 // IFolderOperations
+ 13 IFolderOperations
+ 14 IFolderCalcItemFullSize
+ 15 IFolderCompare
+ 16 IFolderGetItemName
+ 17 IFolderAltStreams
+
+
+09 IFolder.h :: FOLDER_MANAGER_INTERFACE
+
+ 00 - 04 // old IFolderManager
+ 05 IFolderManager
+
+
+// 0A PluginInterface.h
+ 00 IInitContextMenu
+ 01 IPluginOptionsCallback
+ 02 IPluginOptions
+
+
+Handler GUIDs:
+
+{23170F69-40C1-278A-1000-000110xx0000}
+
+ 01 Zip
+ 02 BZip2
+ 03 Rar
+ 04 Arj
+ 05 Z
+ 06 Lzh
+ 07 7z
+ 08 Cab
+ 09 Nsis
+ 0A lzma
+ 0B lzma86
+ 0C xz
+ 0D ppmd
+
+ C6 COFF
+ C7 Ext
+ C8 VMDK
+ C9 VDI
+ CA Qcow
+ CB GPT
+ CC Rar5
+ CD IHex
+ CE Hxs
+ CF TE
+ D0 UEFIc
+ D1 UEFIs
+ D2 SquashFS
+ D3 CramFS
+ D4 APM
+ D5 Mslz
+ D6 Flv
+ D7 Swf
+ D8 Swfc
+ D9 Ntfs
+ DA Fat
+ DB Mbr
+ DC Vhd
+ DD Pe
+ DE Elf
+ DF Mach-O
+ E0 Udf
+ E1 Xar
+ E2 Mub
+ E3 Hfs
+ E4 Dmg
+ E5 Compound
+ E6 Wim
+ E7 Iso
+ E8
+ E9 Chm
+ EA Split
+ EB Rpm
+ EC Deb
+ ED Cpio
+ EE Tar
+ EF GZip
+
+{23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu
+
+// {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
+{23170F69-40C1-2792-id} Hashers
diff --git a/other-licenses/7zstub/src/CPP/7zip/ICoder.h b/other-licenses/7zstub/src/CPP/7zip/ICoder.h
new file mode 100644
index 0000000000..54b247653c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/ICoder.h
@@ -0,0 +1,399 @@
+// ICoder.h
+
+#ifndef __ICODER_H
+#define __ICODER_H
+
+#include "IStream.h"
+
+#define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x)
+
+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)
+{
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress) PURE;
+};
+
+CODER_INTERFACE(ICompressCoder2, 0x18)
+{
+ 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
+ E_NOTIMPL : unsupported encoding method (for decoders)
+ 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
+ {
+ kDefaultProp = 0,
+ kDictionarySize, // VT_UI4
+ kUsedMemorySize, // VT_UI4
+ kOrder, // VT_UI4
+ kBlockSize, // VT_UI4 or VT_UI8
+ kPosStateBits, // VT_UI4
+ kLitContextBits, // VT_UI4
+ kLitPosBits, // VT_UI4
+ kNumFastBytes, // VT_UI4
+ kMatchFinder, // VT_BSTR
+ kMatchFinderCycles, // VT_UI4
+ kNumPasses, // VT_UI4
+ kAlgorithm, // VT_UI4
+ kNumThreads, // VT_UI4
+ kEndMarker, // VT_BOOL
+ kLevel, // VT_UI4
+ kReduceSize, // VT_UI8 : it's estimated size of largest data stream that will be compressed
+ // encoder can use this value to reduce dictionary size and allocate data buffers
+
+ kExpectedDataSize, // VT_UI8 : for ICompressSetCoderPropertiesOpt :
+ // it's estimated size of current data stream
+ // real data size can differ from that size
+ // encoder can use this value to optimize encoder initialization
+
+ kBlockSize2, // VT_UI4 or VT_UI8
+ kCheckSize, // VT_UI4 : size of digest in bytes
+ kFilter, // VT_BSTR
+ kMemUse // VT_UI8
+ };
+}
+
+CODER_INTERFACE(ICompressSetCoderPropertiesOpt, 0x1F)
+{
+ STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
+};
+
+CODER_INTERFACE(ICompressSetCoderProperties, 0x20)
+{
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
+};
+
+/*
+CODER_INTERFACE(ICompressSetCoderProperties, 0x21)
+{
+ STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;
+};
+*/
+
+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;
+};
+
+CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)
+{
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE;
+};
+
+CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)
+{
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;
+};
+
+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(ICompressGetInStreamProcessedSize2, 0x27)
+{
+ STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value) PURE;
+};
+
+CODER_INTERFACE(ICompressSetMemLimit, 0x28)
+{
+ STDMETHOD(SetMemLimit)(UInt64 memUsage) PURE;
+};
+
+
+
+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)
+{
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;
+ STDMETHOD(ReleaseInStream)() PURE;
+};
+
+CODER_INTERFACE(ICompressSetOutStream, 0x32)
+{
+ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;
+ 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)
+{
+ STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE;
+ 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)
+{
+ INTERFACE_ICompressFilter(PURE);
+};
+
+
+CODER_INTERFACE(ICompressCodecsInfo, 0x60)
+{
+ 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;
+};
+
+CODER_INTERFACE(ICryptoProperties, 0x80)
+{
+ STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;
+ STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;
+};
+
+/*
+CODER_INTERFACE(ICryptoResetSalt, 0x88)
+{
+ STDMETHOD(ResetSalt)() PURE;
+};
+*/
+
+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)
+{
+ STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;
+};
+
+CODER_INTERFACE(ICryptoSetCRC, 0xA0)
+{
+ STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;
+};
+
+
+namespace NMethodPropID
+{
+ enum EEnum
+ {
+ kID,
+ kName,
+ kDecoder,
+ kEncoder,
+ kPackStreams,
+ kUnpackStreams,
+ kDescription,
+ kDecoderIsAssigned,
+ kEncoderIsAssigned,
+ kDigestSize
+ };
+}
+
+
+#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)
+{
+ INTERFACE_IHasher(PURE)
+};
+
+CODER_INTERFACE(IHashers, 0xC1)
+{
+ STDMETHOD_(UInt32, GetNumHashers)() PURE;
+ STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
+ STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher) PURE;
+};
+
+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/other-licenses/7zstub/src/CPP/7zip/IDecl.h b/other-licenses/7zstub/src/CPP/7zip/IDecl.h
new file mode 100644
index 0000000000..5a34b0e441
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/IDecl.h
@@ -0,0 +1,28 @@
+// IDecl.h
+
+#ifndef __IDECL_H
+#define __IDECL_H
+
+#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, \
+ 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)
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/IPassword.h b/other-licenses/7zstub/src/CPP/7zip/IPassword.h
new file mode 100644
index 0000000000..e366007041
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/IPassword.h
@@ -0,0 +1,23 @@
+// IPassword.h
+
+#ifndef __IPASSWORD_H
+#define __IPASSWORD_H
+
+#include "../Common/MyTypes.h"
+#include "../Common/MyUnknown.h"
+
+#include "IDecl.h"
+
+#define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x)
+
+PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10)
+{
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE;
+};
+
+PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11)
+{
+ STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE;
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/IProgress.h b/other-licenses/7zstub/src/CPP/7zip/IProgress.h
new file mode 100644
index 0000000000..d54529ca80
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/IProgress.h
@@ -0,0 +1,19 @@
+// IProgress.h
+
+#ifndef __IPROGRESS_H
+#define __IPROGRESS_H
+
+#include "../Common/MyTypes.h"
+
+#include "IDecl.h"
+
+#define INTERFACE_IProgress(x) \
+ STDMETHOD(SetTotal)(UInt64 total) x; \
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \
+
+DECL_INTERFACE(IProgress, 0, 5)
+{
+ INTERFACE_IProgress(PURE)
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/IStream.h b/other-licenses/7zstub/src/CPP/7zip/IStream.h
new file mode 100644
index 0000000000..436e91987f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/IStream.h
@@ -0,0 +1,127 @@
+// IStream.h
+
+#ifndef __ISTREAM_H
+#define __ISTREAM_H
+
+#include "../Common/MyTypes.h"
+#include "../Common/MyWindows.h"
+
+#include "IDecl.h"
+
+#define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x)
+#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x)
+
+STREAM_INTERFACE(ISequentialInStream, 0x01)
+{
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
+
+ /*
+ The requirement for caller: (processedSize != NULL).
+ The callee can allow (processedSize == NULL) for compatibility reasons.
+
+ if (size == 0), this function returns S_OK and (*processedSize) is set to 0.
+
+ if (size != 0)
+ {
+ Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size),
+ where (avail_size) is the size of remaining bytes in stream.
+ If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0).
+ You must call Read() in loop, if you need to read exact amount of data.
+ }
+
+ If seek pointer before Read() call was changed to position past the end of stream:
+ if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0.
+
+ ERROR CASES:
+ If the function returns error code, then (*processedSize) is size of
+ data written to (data) buffer (it can be data before error or data with errors).
+ The recommended way for callee to work with reading errors:
+ 1) write part of data before error to (data) buffer and return S_OK.
+ 2) return error code for further calls of Read().
+ */
+};
+
+STREAM_INTERFACE(ISequentialOutStream, 0x02)
+{
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
+
+ /*
+ The requirement for caller: (processedSize != NULL).
+ The callee can allow (processedSize == NULL) for compatibility reasons.
+
+ if (size != 0)
+ {
+ Partial write is allowed: (*processedSize <= size),
+ but this function must write at least 1 byte: (*processedSize > 0).
+ You must call Write() in loop, if you need to write exact amount of data.
+ }
+
+ ERROR CASES:
+ If the function returns error code, then (*processedSize) is size of
+ data written from (data) buffer.
+ */
+};
+
+#ifdef __HRESULT_FROM_WIN32
+#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)
+#else
+#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)
+#endif
+
+/* Seek() Function
+ If you seek before the beginning of the stream, Seek() function returns error code:
+ Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK).
+ or STG_E_INVALIDFUNCTION
+
+ It is allowed to seek past the end of the stream.
+
+
+ if Seek() returns error, then the value of *newPosition is undefined.
+*/
+
+STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)
+{
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
+};
+
+STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)
+{
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
+ STDMETHOD(SetSize)(UInt64 newSize) PURE;
+};
+
+STREAM_INTERFACE(IStreamGetSize, 0x06)
+{
+ STDMETHOD(GetSize)(UInt64 *size) PURE;
+};
+
+STREAM_INTERFACE(IOutStreamFinish, 0x07)
+{
+ STDMETHOD(OutStreamFinish)() PURE;
+};
+
+
+STREAM_INTERFACE(IStreamGetProps, 0x08)
+{
+ STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) PURE;
+};
+
+struct CStreamFileProps
+{
+ UInt64 Size;
+ UInt64 VolID;
+ UInt64 FileID_Low;
+ UInt64 FileID_High;
+ UInt32 NumLinks;
+ UInt32 Attrib;
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+};
+
+STREAM_INTERFACE(IStreamGetProps2, 0x09)
+{
+ STDMETHOD(GetProps2)(CStreamFileProps *props) PURE;
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/LzmaDec.mak b/other-licenses/7zstub/src/CPP/7zip/LzmaDec.mak
new file mode 100644
index 0000000000..3c0e7c5baa
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/LzmaDec.mak
@@ -0,0 +1,5 @@
+!IF "$(CPU)" == "AMD64"
+CFLAGS_C_SPEC = -D_LZMA_DEC_OPT
+ASM_OBJS = $(ASM_OBJS) \
+ $O\LzmaDecOpt.obj
+!ENDIF
diff --git a/other-licenses/7zstub/src/CPP/7zip/MyVersion.h b/other-licenses/7zstub/src/CPP/7zip/MyVersion.h
new file mode 100644
index 0000000000..0d50f94269
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/MyVersion.h
@@ -0,0 +1,2 @@
+#define USE_COPYRIGHT_CR
+#include "../../C/7zVersion.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/MyVersionInfo.rc b/other-licenses/7zstub/src/CPP/7zip/MyVersionInfo.rc
new file mode 100644
index 0000000000..eddf8935c8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/MyVersionInfo.rc
@@ -0,0 +1,2 @@
+#include "MyVersion.h"
+#include "..\..\C\7zVersion.rc"
diff --git a/other-licenses/7zstub/src/CPP/7zip/PropID.h b/other-licenses/7zstub/src/CPP/7zip/PropID.h
new file mode 100644
index 0000000000..126af67857
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/PropID.h
@@ -0,0 +1,127 @@
+// PropID.h
+
+#ifndef __7ZIP_PROP_ID_H
+#define __7ZIP_PROP_ID_H
+
+#include "../Common/MyTypes.h"
+
+enum
+{
+ kpidNoProperty = 0,
+ kpidMainSubfile,
+ kpidHandlerItemIndex,
+ kpidPath,
+ kpidName,
+ kpidExtension,
+ kpidIsDir,
+ kpidSize,
+ kpidPackSize,
+ kpidAttrib,
+ kpidCTime,
+ kpidATime,
+ kpidMTime,
+ kpidSolid,
+ kpidCommented,
+ kpidEncrypted,
+ kpidSplitBefore,
+ kpidSplitAfter,
+ kpidDictionarySize,
+ kpidCRC,
+ kpidType,
+ kpidIsAnti,
+ kpidMethod,
+ kpidHostOS,
+ kpidFileSystem,
+ kpidUser,
+ kpidGroup,
+ kpidBlock,
+ kpidComment,
+ kpidPosition,
+ kpidPrefix,
+ kpidNumSubDirs,
+ kpidNumSubFiles,
+ kpidUnpackVer,
+ kpidVolume,
+ kpidIsVolume,
+ kpidOffset,
+ kpidLinks,
+ kpidNumBlocks,
+ kpidNumVolumes,
+ kpidTimeType,
+ kpidBit64,
+ kpidBigEndian,
+ kpidCpu,
+ kpidPhySize,
+ kpidHeadersSize,
+ kpidChecksum,
+ kpidCharacts,
+ kpidVa,
+ kpidId,
+ kpidShortName,
+ kpidCreatorApp,
+ kpidSectorSize,
+ kpidPosixAttrib,
+ kpidSymLink,
+ kpidError,
+ kpidTotalSize,
+ kpidFreeSpace,
+ kpidClusterSize,
+ kpidVolumeName,
+ kpidLocalName,
+ kpidProvider,
+ kpidNtSecure,
+ kpidIsAltStream,
+ kpidIsAux,
+ kpidIsDeleted,
+ kpidIsTree,
+ kpidSha1,
+ kpidSha256,
+ kpidErrorType,
+ kpidNumErrors,
+ kpidErrorFlags,
+ kpidWarningFlags,
+ kpidWarning,
+ kpidNumStreams,
+ kpidNumAltStreams,
+ kpidAltStreamsSize,
+ kpidVirtualSize,
+ kpidUnpackSize,
+ kpidTotalPhySize,
+ kpidVolumeIndex,
+ kpidSubType,
+ kpidShortComment,
+ kpidCodePage,
+ kpidIsNotArcType,
+ kpidPhySizeCantBeDetected,
+ kpidZerosTailIsAllowed,
+ kpidTailSize,
+ kpidEmbeddedStubSize,
+ kpidNtReparse,
+ kpidHardLink,
+ kpidINode,
+ kpidStreamId,
+ kpidReadOnly,
+ kpidOutName,
+ kpidCopyLink,
+
+ kpid_NUM_DEFINED,
+
+ kpidUserDefined = 0x10000
+};
+
+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;
+const UInt32 kpv_ErrorFlags_EncryptedHeadersError = 1 << 2;
+const UInt32 kpv_ErrorFlags_UnavailableStart = 1 << 3;
+const UInt32 kpv_ErrorFlags_UnconfirmedStart = 1 << 4;
+const UInt32 kpv_ErrorFlags_UnexpectedEnd = 1 << 5;
+const UInt32 kpv_ErrorFlags_DataAfterEnd = 1 << 6;
+const UInt32 kpv_ErrorFlags_UnsupportedMethod = 1 << 7;
+const UInt32 kpv_ErrorFlags_UnsupportedFeature = 1 << 8;
+const UInt32 kpv_ErrorFlags_DataError = 1 << 9;
+const UInt32 kpv_ErrorFlags_CrcError = 1 << 10;
+// const UInt32 kpv_ErrorFlags_Unsupported = 1 << 11;
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/SubBuild.mak b/other-licenses/7zstub/src/CPP/7zip/SubBuild.mak
new file mode 100644
index 0000000000..0c49d3b712
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/SubBuild.mak
@@ -0,0 +1,3 @@
+ cd $(@D)
+ $(MAKE) -nologo $(TARGETS)
+ cd ..
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.cpp
new file mode 100644
index 0000000000..9a06cdc1d1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -0,0 +1,993 @@
+// Client7z.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "../../../Common/MyWindows.h"
+
+#include "../../../Common/Defs.h"
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/NtCheck.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
+
+#include "../../Common/FileStreams.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "../../IPassword.h"
+#include "../../../../C/7zVersion.h"
+
+#ifdef _WIN32
+HINSTANCE g_hInstance = 0;
+#endif
+
+// 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;
+using namespace NDir;
+
+#define kDllName "7z.dll"
+
+static const char * const kCopyrightString =
+ "\n"
+ "7-Zip"
+ " (" kDllName " client)"
+ " " MY_VERSION
+ " : " MY_COPYRIGHT_DATE
+ "\n";
+
+static const char * const kHelpString =
+"Usage: 7zcl.exe [a | l | x] archive.7z [fileName ...]\n"
+"Examples:\n"
+" 7zcl.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n"
+" 7zcl.exe l archive.7z : List contents of archive.7z\n"
+" 7zcl.exe x archive.7z : eXtract files from archive.7z\n";
+
+
+static void Convert_UString_to_AString(const UString &s, AString &temp)
+{
+ int codePage = CP_OEMCP;
+ /*
+ int g_CodePage = -1;
+ int codePage = g_CodePage;
+ if (codePage == -1)
+ codePage = CP_OEMCP;
+ if (codePage == CP_UTF8)
+ ConvertUnicodeToUTF8(s, temp);
+ else
+ */
+ UnicodeStringToMultiByte2(temp, s, (UINT)codePage);
+}
+
+static FString CmdStringToFString(const char *s)
+{
+ return us2fs(GetUnicodeString(s));
+}
+
+static void Print(const char *s)
+{
+ fputs(s, stdout);
+}
+
+static void Print(const AString &s)
+{
+ Print(s.Ptr());
+}
+
+static void Print(const UString &s)
+{
+ AString as;
+ Convert_UString_to_AString(s, as);
+ Print(as);
+}
+
+static void Print(const wchar_t *s)
+{
+ Print(UString(s));
+}
+
+static void PrintNewLine()
+{
+ Print("\n");
+}
+
+static void PrintStringLn(const char *s)
+{
+ Print(s);
+ PrintNewLine();
+}
+
+static void PrintError(const char *message)
+{
+ Print("Error: ");
+ PrintNewLine();
+ Print(message);
+ PrintNewLine();
+}
+
+static void PrintError(const char *message, const FString &name)
+{
+ PrintError(message);
+ Print(name);
+}
+
+
+static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
+{
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_BOOL)
+ result = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt == VT_EMPTY)
+ result = false;
+ else
+ return E_FAIL;
+ return S_OK;
+}
+
+static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
+{
+ return IsArchiveItemProp(archive, index, kpidIsDir, result);
+}
+
+
+static const wchar_t * const kEmptyFileAlias = L"[Content]";
+
+
+//////////////////////////////////////////////////////////////
+// Archive Open callback class
+
+
+class CArchiveOpenCallback:
+ public IArchiveOpenCallback,
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+
+ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
+ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
+
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+ bool PasswordIsDefined;
+ UString Password;
+
+ CArchiveOpenCallback() : PasswordIsDefined(false) {}
+};
+
+STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ // You can ask real password here from user
+ // Password = GetPassword(OutStream);
+ // PasswordIsDefined = true;
+ PrintError("Password is not defined");
+ return E_ABORT;
+ }
+ return StringToBstr(Password, password);
+}
+
+
+
+static const char * const kIncorrectCommand = "incorrect command";
+
+//////////////////////////////////////////////////////////////
+// Archive Extracting callback class
+
+static const char * const kTestingString = "Testing ";
+static const char * const kExtractingString = "Extracting ";
+static const char * const kSkippingString = "Skipping ";
+
+static const char * const kUnsupportedMethod = "Unsupported Method";
+static const char * const kCRCFailed = "CRC Failed";
+static const char * const kDataError = "Data Error";
+static const char * const kUnavailableData = "Unavailable data";
+static const char * const kUnexpectedEnd = "Unexpected end of data";
+static const char * const kDataAfterEnd = "There are some data after the end of the payload data";
+static const char * const kIsNotArc = "Is not archive";
+static const char * const kHeadersError = "Headers Error";
+
+
+class CArchiveExtractCallback:
+ public IArchiveExtractCallback,
+ public ICryptoGetTextPassword,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+
+ // IProgress
+ STDMETHOD(SetTotal)(UInt64 size);
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+ // IArchiveExtractCallback
+ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);
+ STDMETHOD(PrepareOperation)(Int32 askExtractMode);
+ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
+
+ // ICryptoGetTextPassword
+ STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
+
+private:
+ CMyComPtr<IInArchive> _archiveHandler;
+ FString _directoryPath; // Output directory
+ UString _filePath; // name inside arcvhive
+ FString _diskFilePath; // full path to file on disk
+ bool _extractMode;
+ struct CProcessedFileInfo
+ {
+ FILETIME MTime;
+ UInt32 Attrib;
+ bool isDir;
+ bool AttribDefined;
+ bool MTimeDefined;
+ } _processedFileInfo;
+
+ COutFileStream *_outFileStreamSpec;
+ CMyComPtr<ISequentialOutStream> _outFileStream;
+
+public:
+ void Init(IInArchive *archiveHandler, const FString &directoryPath);
+
+ UInt64 NumErrors;
+ bool PasswordIsDefined;
+ UString Password;
+
+ CArchiveExtractCallback() : PasswordIsDefined(false) {}
+};
+
+void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const FString &directoryPath)
+{
+ NumErrors = 0;
+ _archiveHandler = archiveHandler;
+ _directoryPath = directoryPath;
+ NName::NormalizeDirPathPrefix(_directoryPath);
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,
+ ISequentialOutStream **outStream, Int32 askExtractMode)
+{
+ *outStream = 0;
+ _outFileStream.Release();
+
+ {
+ // Get Name
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));
+
+ UString fullPath;
+ if (prop.vt == VT_EMPTY)
+ fullPath = kEmptyFileAlias;
+ else
+ {
+ if (prop.vt != VT_BSTR)
+ return E_FAIL;
+ fullPath = prop.bstrVal;
+ }
+ _filePath = fullPath;
+ }
+
+ if (askExtractMode != NArchive::NExtract::NAskMode::kExtract)
+ return S_OK;
+
+ {
+ // Get Attrib
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
+ if (prop.vt == VT_EMPTY)
+ {
+ _processedFileInfo.Attrib = 0;
+ _processedFileInfo.AttribDefined = false;
+ }
+ else
+ {
+ if (prop.vt != VT_UI4)
+ return E_FAIL;
+ _processedFileInfo.Attrib = prop.ulVal;
+ _processedFileInfo.AttribDefined = true;
+ }
+ }
+
+ RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir));
+
+ {
+ // Get Modified Time
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));
+ _processedFileInfo.MTimeDefined = false;
+ switch (prop.vt)
+ {
+ case VT_EMPTY:
+ // _processedFileInfo.MTime = _utcMTimeDefault;
+ break;
+ case VT_FILETIME:
+ _processedFileInfo.MTime = prop.filetime;
+ _processedFileInfo.MTimeDefined = true;
+ break;
+ default:
+ return E_FAIL;
+ }
+
+ }
+ {
+ // Get Size
+ NCOM::CPropVariant prop;
+ RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));
+ UInt64 newFileSize;
+ /* bool newFileSizeDefined = */ ConvertPropVariantToUInt64(prop, newFileSize);
+ }
+
+
+ {
+ // Create folders for file
+ int slashPos = _filePath.ReverseFind_PathSepar();
+ if (slashPos >= 0)
+ CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos)));
+ }
+
+ FString fullProcessedPath = _directoryPath + us2fs(_filePath);
+ _diskFilePath = fullProcessedPath;
+
+ if (_processedFileInfo.isDir)
+ {
+ CreateComplexDir(fullProcessedPath);
+ }
+ else
+ {
+ NFind::CFileInfo fi;
+ if (fi.Find(fullProcessedPath))
+ {
+ if (!DeleteFileAlways(fullProcessedPath))
+ {
+ PrintError("Can not delete output file", fullProcessedPath);
+ return E_ABORT;
+ }
+ }
+
+ _outFileStreamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
+ if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS))
+ {
+ PrintError("Can not open output file", fullProcessedPath);
+ return E_ABORT;
+ }
+ _outFileStream = outStreamLoc;
+ *outStream = outStreamLoc.Detach();
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
+{
+ _extractMode = false;
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break;
+ };
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract: Print(kExtractingString); break;
+ case NArchive::NExtract::NAskMode::kTest: Print(kTestingString); break;
+ case NArchive::NExtract::NAskMode::kSkip: Print(kSkippingString); break;
+ };
+ Print(_filePath);
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
+{
+ switch (operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kOK:
+ break;
+ default:
+ {
+ NumErrors++;
+ Print(" : ");
+ const char *s = NULL;
+ switch (operationResult)
+ {
+ case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
+ s = kUnsupportedMethod;
+ break;
+ case NArchive::NExtract::NOperationResult::kCRCError:
+ s = kCRCFailed;
+ break;
+ case NArchive::NExtract::NOperationResult::kDataError:
+ s = 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)
+ {
+ Print("Error : ");
+ Print(s);
+ }
+ else
+ {
+ char temp[16];
+ ConvertUInt32ToString(operationResult, temp);
+ Print("Error #");
+ Print(temp);
+ }
+ }
+ }
+
+ if (_outFileStream)
+ {
+ if (_processedFileInfo.MTimeDefined)
+ _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
+ RINOK(_outFileStreamSpec->Close());
+ }
+ _outFileStream.Release();
+ if (_extractMode && _processedFileInfo.AttribDefined)
+ SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib);
+ PrintNewLine();
+ return S_OK;
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ // You can ask real password here from user
+ // Password = GetPassword(OutStream);
+ // PasswordIsDefined = true;
+ PrintError("Password is not defined");
+ return E_ABORT;
+ }
+ return StringToBstr(Password, password);
+}
+
+
+
+//////////////////////////////////////////////////////////////
+// Archive Creating callback class
+
+struct CDirItem
+{
+ UInt64 Size;
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+ UString Name;
+ FString FullPath;
+ UInt32 Attrib;
+
+ bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
+};
+
+class CArchiveUpdateCallback:
+ public IArchiveUpdateCallback2,
+ public ICryptoGetTextPassword2,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
+
+ // IProgress
+ STDMETHOD(SetTotal)(UInt64 size);
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+ // IUpdateCallback2
+ STDMETHOD(GetUpdateItemInfo)(UInt32 index,
+ Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
+ STDMETHOD(SetOperationResult)(Int32 operationResult);
+ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
+ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
+
+ STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
+
+public:
+ CRecordVector<UInt64> VolumesSizes;
+ UString VolName;
+ UString VolExt;
+
+ FString DirPrefix;
+ const CObjectVector<CDirItem> *DirItems;
+
+ bool PasswordIsDefined;
+ UString Password;
+ bool AskPassword;
+
+ bool m_NeedBeClosed;
+
+ FStringVector FailedFiles;
+ CRecordVector<HRESULT> FailedCodes;
+
+ CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {};
+
+ ~CArchiveUpdateCallback() { Finilize(); }
+ HRESULT Finilize();
+
+ void Init(const CObjectVector<CDirItem> *dirItems)
+ {
+ DirItems = dirItems;
+ m_NeedBeClosed = false;
+ FailedFiles.Clear();
+ FailedCodes.Clear();
+ }
+};
+
+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,
+ Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
+{
+ if (newData)
+ *newData = BoolToInt(true);
+ if (newProperties)
+ *newProperties = BoolToInt(true);
+ if (indexInArchive)
+ *indexInArchive = (UInt32)(Int32)-1;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant prop;
+
+ if (propID == kpidIsAnti)
+ {
+ prop = false;
+ prop.Detach(value);
+ return S_OK;
+ }
+
+ {
+ const CDirItem &dirItem = (*DirItems)[index];
+ switch (propID)
+ {
+ case kpidPath: prop = dirItem.Name; break;
+ case kpidIsDir: prop = dirItem.isDir(); break;
+ case kpidSize: prop = dirItem.Size; break;
+ case kpidAttrib: prop = dirItem.Attrib; break;
+ case kpidCTime: prop = dirItem.CTime; break;
+ case kpidATime: prop = dirItem.ATime; break;
+ case kpidMTime: prop = dirItem.MTime; break;
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+HRESULT CArchiveUpdateCallback::Finilize()
+{
+ if (m_NeedBeClosed)
+ {
+ PrintNewLine();
+ m_NeedBeClosed = false;
+ }
+ return S_OK;
+}
+
+static void GetStream2(const wchar_t *name)
+{
+ Print("Compressing ");
+ if (name[0] == 0)
+ name = kEmptyFileAlias;
+ Print(name);
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
+{
+ RINOK(Finilize());
+
+ const CDirItem &dirItem = (*DirItems)[index];
+ GetStream2(dirItem.Name);
+
+ if (dirItem.isDir())
+ return S_OK;
+
+ {
+ CInFileStream *inStreamSpec = new CInFileStream;
+ CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+ FString path = DirPrefix + dirItem.FullPath;
+ if (!inStreamSpec->Open(path))
+ {
+ DWORD sysError = ::GetLastError();
+ FailedCodes.Add(sysError);
+ FailedFiles.Add(path);
+ // if (systemError == ERROR_SHARING_VIOLATION)
+ {
+ PrintNewLine();
+ PrintError("WARNING: can't open file");
+ // Print(NError::MyFormatMessageW(systemError));
+ return S_FALSE;
+ }
+ // return sysError;
+ }
+ *inStream = inStreamLoc.Detach();
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */)
+{
+ m_NeedBeClosed = true;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
+{
+ if (VolumesSizes.Size() == 0)
+ return S_FALSE;
+ if (index >= (UInt32)VolumesSizes.Size())
+ index = VolumesSizes.Size() - 1;
+ *size = VolumesSizes[index];
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
+{
+ wchar_t temp[16];
+ ConvertUInt32ToString(index + 1, temp);
+ UString res = temp;
+ while (res.Len() < 2)
+ res.InsertAtFront(L'0');
+ UString fileName = VolName;
+ fileName += '.';
+ fileName += res;
+ fileName += VolExt;
+ COutFileStream *streamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
+ if (!streamSpec->Create(us2fs(fileName), false))
+ return ::GetLastError();
+ *volumeStream = streamLoc.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+ if (!PasswordIsDefined)
+ {
+ if (AskPassword)
+ {
+ // You can ask real password here from user
+ // Password = GetPassword(OutStream);
+ // PasswordIsDefined = true;
+ PrintError("Password is not defined");
+ return E_ABORT;
+ }
+ }
+ *passwordIsDefined = BoolToInt(PasswordIsDefined);
+ return StringToBstr(Password, password);
+}
+
+
+// Main function
+
+#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1;
+
+int MY_CDECL main(int numArgs, const char *args[])
+{
+ NT_CHECK
+
+ PrintStringLn(kCopyrightString);
+
+ if (numArgs < 2)
+ {
+ PrintStringLn(kHelpString);
+ return 0;
+ }
+
+ if (numArgs < 3)
+ {
+ PrintError(kIncorrectCommand);
+ return 1;
+ }
+
+
+ NDLL::CLibrary lib;
+ if (!lib.Load(NDLL::GetModuleDirPrefix() + FTEXT(kDllName)))
+ {
+ PrintError("Can not load 7-zip library");
+ return 1;
+ }
+
+ Func_CreateObject createObjectFunc = (Func_CreateObject)lib.GetProc("CreateObject");
+ if (!createObjectFunc)
+ {
+ PrintError("Can not get CreateObject");
+ return 1;
+ }
+
+ char c;
+ {
+ AString command (args[1]);
+ if (command.Len() != 1)
+ {
+ PrintError(kIncorrectCommand);
+ return 1;
+ }
+ c = (char)MyCharLower_Ascii(command[0]);
+ }
+
+ FString archiveName = CmdStringToFString(args[2]);
+
+ if (c == 'a')
+ {
+ // create archive command
+ if (numArgs < 4)
+ {
+ PrintError(kIncorrectCommand);
+ return 1;
+ }
+ CObjectVector<CDirItem> dirItems;
+ {
+ int i;
+ for (i = 3; i < numArgs; i++)
+ {
+ CDirItem di;
+ FString name = CmdStringToFString(args[i]);
+
+ NFind::CFileInfo fi;
+ if (!fi.Find(name))
+ {
+ PrintError("Can't find file", name);
+ return 1;
+ }
+
+ di.Attrib = fi.Attrib;
+ di.Size = fi.Size;
+ di.CTime = fi.CTime;
+ di.ATime = fi.ATime;
+ di.MTime = fi.MTime;
+ di.Name = fs2us(name);
+ di.FullPath = name;
+ dirItems.Add(di);
+ }
+ }
+
+ COutFileStream *outFileStreamSpec = new COutFileStream;
+ CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
+ if (!outFileStreamSpec->Create(archiveName, false))
+ {
+ PrintError("can't create archive file");
+ return 1;
+ }
+
+ CMyComPtr<IOutArchive> outArchive;
+ if (createObjectFunc(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK)
+ {
+ PrintError("Can not get class object");
+ return 1;
+ }
+
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);
+ updateCallbackSpec->Init(&dirItems);
+ // updateCallbackSpec->PasswordIsDefined = true;
+ // updateCallbackSpec->Password = L"1";
+
+ /*
+ {
+ const wchar_t *names[] =
+ {
+ L"s",
+ L"x"
+ };
+ const unsigned kNumProps = ARRAY_SIZE(names);
+ NCOM::CPropVariant values[kNumProps] =
+ {
+ false, // solid mode OFF
+ (UInt32)9 // compression level = 9 - ultra
+ };
+ CMyComPtr<ISetProperties> setProperties;
+ outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties);
+ if (!setProperties)
+ {
+ PrintError("ISetProperties unsupported");
+ return 1;
+ }
+ RINOK(setProperties->SetProperties(names, values, kNumProps));
+ }
+ */
+
+ HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);
+
+ updateCallbackSpec->Finilize();
+
+ if (result != S_OK)
+ {
+ PrintError("Update Error");
+ return 1;
+ }
+
+ FOR_VECTOR (i, updateCallbackSpec->FailedFiles)
+ {
+ PrintNewLine();
+ PrintError("Error for file", updateCallbackSpec->FailedFiles[i]);
+ }
+
+ if (updateCallbackSpec->FailedFiles.Size() != 0)
+ return 1;
+ }
+ else
+ {
+ if (numArgs != 3)
+ {
+ PrintError(kIncorrectCommand);
+ return 1;
+ }
+
+ bool listCommand;
+
+ if (c == 'l')
+ listCommand = true;
+ else if (c == 'x')
+ listCommand = false;
+ else
+ {
+ PrintError(kIncorrectCommand);
+ return 1;
+ }
+
+ CMyComPtr<IInArchive> archive;
+ if (createObjectFunc(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK)
+ {
+ PrintError("Can not get class object");
+ return 1;
+ }
+
+ CInFileStream *fileSpec = new CInFileStream;
+ CMyComPtr<IInStream> file = fileSpec;
+
+ if (!fileSpec->Open(archiveName))
+ {
+ PrintError("Can not open archive file", archiveName);
+ return 1;
+ }
+
+ {
+ CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback;
+ CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);
+ openCallbackSpec->PasswordIsDefined = false;
+ // openCallbackSpec->PasswordIsDefined = true;
+ // openCallbackSpec->Password = L"1";
+
+ const UInt64 scanSize = 1 << 23;
+ if (archive->Open(file, &scanSize, openCallback) != S_OK)
+ {
+ PrintError("Can not open file as archive", archiveName);
+ return 1;
+ }
+ }
+
+ if (listCommand)
+ {
+ // List command
+ UInt32 numItems = 0;
+ archive->GetNumberOfItems(&numItems);
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ {
+ // Get uncompressed size of file
+ NCOM::CPropVariant prop;
+ archive->GetProperty(i, kpidSize, &prop);
+ char s[32];
+ ConvertPropVariantToShortString(prop, s);
+ Print(s);
+ Print(" ");
+ }
+ {
+ // Get name of file
+ NCOM::CPropVariant prop;
+ archive->GetProperty(i, kpidPath, &prop);
+ if (prop.vt == VT_BSTR)
+ Print(prop.bstrVal);
+ else if (prop.vt != VT_EMPTY)
+ Print("ERROR!");
+ }
+ PrintNewLine();
+ }
+ }
+ else
+ {
+ // Extract command
+ CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
+ extractCallbackSpec->Init(archive, FString()); // second parameter is output folder path
+ extractCallbackSpec->PasswordIsDefined = false;
+ // extractCallbackSpec->PasswordIsDefined = true;
+ // extractCallbackSpec->Password = "1";
+
+ /*
+ const wchar_t *names[] =
+ {
+ L"mt",
+ L"mtf"
+ };
+ const unsigned kNumProps = sizeof(names) / sizeof(names[0]);
+ NCOM::CPropVariant values[kNumProps] =
+ {
+ (UInt32)1,
+ false
+ };
+ CMyComPtr<ISetProperties> setProperties;
+ archive->QueryInterface(IID_ISetProperties, (void **)&setProperties);
+ if (setProperties)
+ setProperties->SetProperties(names, values, kNumProps);
+ */
+
+ HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);
+
+ if (result != S_OK)
+ {
+ PrintError("Extract Error");
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsp b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsp
new file mode 100644
index 0000000000..d9ec4caf63
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsp
@@ -0,0 +1,235 @@
+# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Client7z - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Client7z.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Client7z - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 /machine:I386 /out:"Release/7zcl.exe"
+
+!ELSEIF "$(CFG)" == "Client7z - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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 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:"Debug/7zcl.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Client7z - Win32 Release"
+# Name "Client7z - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConv.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConv.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\Client7z.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sort.h
+# End Source File
+# End Target
+# End Project
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsw b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsw
new file mode 100644
index 0000000000..4c26851183
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Client7z"=.\Client7z.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/makefile b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/makefile
new file mode 100644
index 0000000000..9f68f16720
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/makefile
@@ -0,0 +1,28 @@
+PROG = 7zcl.exe
+MY_CONSOLE = 1
+
+CURRENT_OBJS = \
+ $O\Client7z.obj \
+
+COMMON_OBJS = \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\MyString.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\MyVector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileName.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConv.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\FileStreams.obj \
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/resource.rc b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/resource.rc
new file mode 100644
index 0000000000..701a783e01
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Client7z/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_APP("7-Zip client" , "7zcl")
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
new file mode 100644
index 0000000000..f14aafbafa
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -0,0 +1,1281 @@
+// ArchiveCommandLine.cpp
+
+#include "StdAfx.h"
+#undef printf
+#undef sprintf
+
+#ifdef _WIN32
+#ifndef UNDER_CE
+#include <io.h>
+#endif
+#else
+// for isatty()
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef _7ZIP_LARGE_PAGES
+#include "../../../../C/Alloc.h"
+#endif
+
+#include "../../../Common/ListFileUtils.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
+#ifdef _WIN32
+#include "../../../Windows/FileMapping.h"
+#include "../../../Windows/MemoryLock.h"
+#include "../../../Windows/Synchronization.h"
+#endif
+
+#include "ArchiveCommandLine.h"
+#include "EnumDirItems.h"
+#include "Update.h"
+#include "UpdateAction.h"
+
+extern bool g_CaseSensitive;
+extern bool g_PathTrailReplaceMode;
+
+bool g_LargePagesMode = false;
+
+#ifdef UNDER_CE
+
+#define MY_IS_TERMINAL(x) false;
+
+#else
+
+#if _MSC_VER >= 1400
+#define MY_isatty_fileno(x) _isatty(_fileno(x))
+#else
+#define MY_isatty_fileno(x) isatty(fileno(x))
+#endif
+
+#define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0);
+
+#endif
+
+using namespace NCommandLineParser;
+using namespace NWindows;
+using namespace NFile;
+
+static bool StringToUInt32(const wchar_t *s, UInt32 &v)
+{
+ if (*s == 0)
+ return false;
+ const wchar_t *end;
+ v = ConvertStringToUInt32(s, &end);
+ return *end == 0;
+}
+
+
+int g_CodePage = -1;
+
+namespace NKey {
+enum Enum
+{
+ kHelp1 = 0,
+ kHelp2,
+ kHelp3,
+
+ kDisableHeaders,
+ kDisablePercents,
+ kShowTime,
+ kLogLevel,
+
+ kOutStream,
+ kErrStream,
+ kPercentStream,
+
+ kYes,
+
+ kShowDialog,
+ kOverwrite,
+
+ kArchiveType,
+ kExcludedArcType,
+
+ kProperty,
+ kOutputDir,
+ kWorkingDir,
+
+ kInclude,
+ kExclude,
+ kArInclude,
+ kArExclude,
+ kNoArName,
+
+ kUpdate,
+ kVolume,
+ kRecursed,
+
+ kAffinity,
+ kSfx,
+ kEmail,
+ kHash,
+
+ kStdIn,
+ kStdOut,
+
+ kLargePages,
+ kListfileCharSet,
+ kConsoleCharSet,
+ kTechMode,
+
+ kShareForWrite,
+ kStopAfterOpenError,
+ kCaseSensitive,
+ kArcNameMode,
+
+ kDisableWildcardParsing,
+ kElimDup,
+ kFullPathMode,
+
+ kHardLinks,
+ kSymLinks,
+ kNtSecurity,
+
+ kAltStreams,
+ kReplaceColonForAltStream,
+ kWriteToAltStreamIfColon,
+
+ kNameTrailReplace,
+
+ kDeleteAfterCompressing,
+ kSetArcMTime
+
+ #ifndef _NO_CRYPTO
+ , kPassword
+ #endif
+};
+
+}
+
+
+static const wchar_t kRecursedIDChar = 'r';
+static const char * const kRecursedPostCharSet = "0-";
+
+static const char * const k_ArcNameMode_PostCharSet = "sea";
+
+static const char * const k_Stream_PostCharSet = "012";
+
+static inline const EArcNameMode ParseArcNameMode(int postCharIndex)
+{
+ switch (postCharIndex)
+ {
+ case 1: return k_ArcNameMode_Exact;
+ case 2: return k_ArcNameMode_Add;
+ default: return k_ArcNameMode_Smart;
+ }
+}
+
+namespace NRecursedPostCharIndex {
+ enum EEnum
+ {
+ kWildcardRecursionOnly = 0,
+ kNoRecursion = 1
+ };
+}
+
+static const char kImmediateNameID = '!';
+static const char kMapNameID = '#';
+static const char kFileListID = '@';
+
+static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
+static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
+
+static const char * const kOverwritePostCharSet = "asut";
+
+static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
+{
+ NExtract::NOverwriteMode::kOverwrite,
+ NExtract::NOverwriteMode::kSkip,
+ NExtract::NOverwriteMode::kRename,
+ NExtract::NOverwriteMode::kRenameExisting
+};
+
+static const CSwitchForm kSwitchForms[] =
+{
+ { "?" },
+ { "h" },
+ { "-help" },
+
+ { "ba" },
+ { "bd" },
+ { "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" },
+
+ { "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" },
+
+ { "slp", NSwitchType::kString },
+ { "scs", NSwitchType::kString },
+ { "scc", NSwitchType::kString },
+ { "slt" },
+
+ { "ssw" },
+ { "sse" },
+ { "ssc", NSwitchType::kMinus },
+ { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet },
+
+ { "spd" },
+ { "spe", NSwitchType::kMinus },
+ { "spf", NSwitchType::kString, false, 0 },
+
+ { "snh", NSwitchType::kMinus },
+ { "snl", NSwitchType::kMinus },
+ { "sni" },
+
+ { "sns", NSwitchType::kMinus },
+ { "snr" },
+ { "snc" },
+
+ { "snt", NSwitchType::kMinus },
+
+ { "sdel" },
+ { "stl" }
+
+ #ifndef _NO_CRYPTO
+ , { "p", NSwitchType::kString }
+ #endif
+};
+
+static const char * const kUniversalWildcard = "*";
+static const unsigned kMinNonSwitchWords = 1;
+static const unsigned kCommandIndex = 0;
+
+// static const char * const kUserErrorMessage = "Incorrect command line";
+static const char * const kCannotFindListFile = "Cannot find listfile";
+static const char * const kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";
+static const char * const kTerminalOutError = "I won't write compressed data to a terminal";
+static const char * const kSameTerminalError = "I won't write data and program's messages to same stream";
+static const char * const kEmptyFilePath = "Empty file path";
+
+bool CArcCommand::IsFromExtractGroup() const
+{
+ switch (CommandType)
+ {
+ case NCommandType::kTest:
+ case NCommandType::kExtract:
+ case NCommandType::kExtractFull:
+ return true;
+ }
+ return false;
+}
+
+NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const
+{
+ switch (CommandType)
+ {
+ case NCommandType::kTest:
+ case NCommandType::kExtractFull:
+ return NExtract::NPathMode::kFullPaths;
+ }
+ return NExtract::NPathMode::kNoPaths;
+}
+
+bool CArcCommand::IsFromUpdateGroup() const
+{
+ switch (CommandType)
+ {
+ case NCommandType::kAdd:
+ case NCommandType::kUpdate:
+ case NCommandType::kDelete:
+ case NCommandType::kRename:
+ return true;
+ }
+ return false;
+}
+
+static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)
+{
+ switch (index)
+ {
+ case NRecursedPostCharIndex::kWildcardRecursionOnly:
+ return NRecursedType::kWildcardOnlyRecursed;
+ case NRecursedPostCharIndex::kNoRecursion:
+ return NRecursedType::kNonRecursed;
+ default:
+ return NRecursedType::kRecursed;
+ }
+}
+
+static const char *g_Commands = "audtexlbih";
+
+static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command)
+{
+ UString s (commandString);
+ s.MakeLower_Ascii();
+ if (s.Len() == 1)
+ {
+ if (s[0] > 0x7F)
+ return false;
+ int index = FindCharPosInString(g_Commands, (char)s[0]);
+ if (index < 0)
+ return false;
+ command.CommandType = (NCommandType::EEnum)index;
+ return true;
+ }
+ if (s.Len() == 2 && s[0] == 'r' && s[1] == 'n')
+ {
+ command.CommandType = (NCommandType::kRename);
+ return true;
+ }
+ return false;
+}
+
+// ------------------------------------------------------------------
+// filenames functions
+
+static void AddNameToCensor(NWildcard::CCensor &censor,
+ const UString &name, bool include, NRecursedType::EEnum type, bool wildcardMatching)
+{
+ bool recursed = false;
+
+ switch (type)
+ {
+ case NRecursedType::kWildcardOnlyRecursed:
+ recursed = DoesNameContainWildcard(name);
+ break;
+ case NRecursedType::kRecursed:
+ recursed = true;
+ break;
+ }
+ censor.AddPreItem(include, name, recursed, wildcardMatching);
+}
+
+static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs,
+ const UString &oldName, const UString &newName, NRecursedType::EEnum type,
+ bool wildcardMatching)
+{
+ CRenamePair &pair = renamePairs->AddNew();
+ pair.OldName = oldName;
+ pair.NewName = newName;
+ pair.RecursedType = type;
+ pair.WildcardParsing = wildcardMatching;
+
+ if (!pair.Prepare())
+ {
+ UString val;
+ val += pair.OldName;
+ val.Add_LF();
+ val += pair.NewName;
+ val.Add_LF();
+ if (type == NRecursedType::kRecursed)
+ val += "-r";
+ else if (type == NRecursedType::kWildcardOnlyRecursed)
+ val += "-r0";
+ throw CArcCmdLineException("Unsupported rename command:", val);
+ }
+}
+
+static void AddToCensorFromListFile(
+ CObjectVector<CRenamePair> *renamePairs,
+ NWildcard::CCensor &censor,
+ LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, Int32 codePage)
+{
+ UStringVector names;
+ if (!NFind::DoesFileExist(us2fs(fileName)))
+ throw CArcCmdLineException(kCannotFindListFile, fileName);
+ if (!ReadNamesFromListFile(us2fs(fileName), names, codePage))
+ throw CArcCmdLineException(kIncorrectListFile, fileName);
+ if (renamePairs)
+ {
+ if ((names.Size() & 1) != 0)
+ throw CArcCmdLineException(kIncorrectListFile, fileName);
+ for (unsigned i = 0; i < names.Size(); i += 2)
+ {
+ // change type !!!!
+ AddRenamePair(renamePairs, names[i], names[i + 1], type, wildcardMatching);
+ }
+ }
+ else
+ FOR_VECTOR (i, names)
+ AddNameToCensor(censor, names[i], include, type, wildcardMatching);
+}
+
+static void AddToCensorFromNonSwitchesStrings(
+ CObjectVector<CRenamePair> *renamePairs,
+ unsigned startIndex,
+ NWildcard::CCensor &censor,
+ const UStringVector &nonSwitchStrings,
+ int stopSwitchIndex,
+ NRecursedType::EEnum type,
+ bool wildcardMatching,
+ bool thereAreSwitchIncludes, Int32 codePage)
+{
+ if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes)
+ AddNameToCensor(censor, UString(kUniversalWildcard), true, type,
+ true // wildcardMatching
+ );
+
+ int oldIndex = -1;
+
+ if (stopSwitchIndex < 0)
+ stopSwitchIndex = nonSwitchStrings.Size();
+
+ for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++)
+ {
+ const UString &s = nonSwitchStrings[i];
+ if (s.IsEmpty())
+ throw CArcCmdLineException(kEmptyFilePath);
+ if (i < (unsigned)stopSwitchIndex && s[0] == kFileListID)
+ AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage);
+ else if (renamePairs)
+ {
+ if (oldIndex == -1)
+ oldIndex = i;
+ else
+ {
+ // NRecursedType::EEnum type is used for global wildcard (-i! switches)
+ AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching);
+ // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type);
+ oldIndex = -1;
+ }
+ }
+ else
+ AddNameToCensor(censor, s, true, type, wildcardMatching);
+ }
+
+ if (oldIndex != -1)
+ {
+ throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[oldIndex]);
+ }
+}
+
+#ifdef _WIN32
+
+struct CEventSetEnd
+{
+ UString Name;
+
+ CEventSetEnd(const wchar_t *name): Name(name) {}
+ ~CEventSetEnd()
+ {
+ NSynchronization::CManualResetEvent event;
+ if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(Name)) == 0)
+ event.Set();
+ }
+};
+
+static const char * const k_IncorrectMapCommand = "Incorrect Map command";
+
+static const char *ParseMapWithPaths(
+ NWildcard::CCensor &censor,
+ const UString &s2, bool include,
+ NRecursedType::EEnum commonRecursedType,
+ bool wildcardMatching)
+{
+ UString s (s2);
+ int pos = s.Find(L':');
+ if (pos < 0)
+ return k_IncorrectMapCommand;
+ int pos2 = s.Find(L':', pos + 1);
+ if (pos2 < 0)
+ return k_IncorrectMapCommand;
+
+ CEventSetEnd eventSetEnd((const wchar_t *)s + ((unsigned)pos2 + 1));
+ s.DeleteFrom(pos2);
+ UInt32 size;
+ if (!StringToUInt32(s.Ptr(pos + 1), size)
+ || size < sizeof(wchar_t)
+ || size > ((UInt32)1 << 31)
+ || size % sizeof(wchar_t) != 0)
+ return "Unsupported Map data size";
+
+ s.DeleteFrom(pos);
+ CFileMapping map;
+ if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0)
+ return "Can not open mapping";
+ LPVOID data = map.Map(FILE_MAP_READ, 0, size);
+ if (!data)
+ return "MapViewOfFile error";
+ CFileUnmapper unmapper(data);
+
+ UString name;
+ const wchar_t *p = (const wchar_t *)data;
+ if (*p != 0) // data format marker
+ return "Unsupported Map data";
+ UInt32 numChars = size / sizeof(wchar_t);
+ for (UInt32 i = 1; i < numChars; i++)
+ {
+ wchar_t c = p[i];
+ if (c == 0)
+ {
+ // MessageBoxW(0, name, L"7-Zip", 0);
+ AddNameToCensor(censor, name, include, commonRecursedType, wildcardMatching);
+ name.Empty();
+ }
+ else
+ name += c;
+ }
+ if (!name.IsEmpty())
+ return "Map data error";
+
+ return NULL;
+}
+
+#endif
+
+static void AddSwitchWildcardsToCensor(
+ NWildcard::CCensor &censor,
+ const UStringVector &strings, bool include,
+ NRecursedType::EEnum commonRecursedType,
+ bool wildcardMatching,
+ Int32 codePage)
+{
+ const char *errorMessage = NULL;
+ unsigned i;
+ for (i = 0; i < strings.Size(); i++)
+ {
+ const UString &name = strings[i];
+ NRecursedType::EEnum recursedType;
+ unsigned pos = 0;
+
+ if (name.Len() < kSomeCludePostStringMinSize)
+ {
+ errorMessage = "Too short switch";
+ break;
+ }
+
+ if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar)
+ {
+ pos++;
+ wchar_t c = name[pos];
+ int index = -1;
+ if (c <= 0x7F)
+ index = FindCharPosInString(kRecursedPostCharSet, (char)c);
+ recursedType = GetRecursedTypeFromIndex(index);
+ if (index >= 0)
+ pos++;
+ }
+ else
+ recursedType = commonRecursedType;
+
+ if (name.Len() < pos + kSomeCludeAfterRecursedPostStringMinSize)
+ {
+ errorMessage = "Too short switch";
+ break;
+ }
+
+ const UString tail = name.Ptr(pos + 1);
+
+ if (name[pos] == kImmediateNameID)
+ AddNameToCensor(censor, tail, include, recursedType, wildcardMatching);
+ else if (name[pos] == kFileListID)
+ AddToCensorFromListFile(NULL, censor, tail, include, recursedType, wildcardMatching, codePage);
+ #ifdef _WIN32
+ else if (name[pos] == kMapNameID)
+ {
+ errorMessage = ParseMapWithPaths(censor, tail, include, recursedType, wildcardMatching);
+ if (errorMessage)
+ break;
+ }
+ #endif
+ else
+ {
+ errorMessage = "Incorrect wildcard type marker";
+ break;
+ }
+ }
+ if (i != strings.Size())
+ throw CArcCmdLineException(errorMessage, strings[i]);
+}
+
+/*
+static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
+{
+ switch (i)
+ {
+ case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore;
+ case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy;
+ case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress;
+ case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti;
+ }
+ throw 98111603;
+}
+*/
+
+static const char * const kUpdatePairStateIDSet = "pqrxyzw";
+static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
+
+static const unsigned kNumUpdatePairActions = 4;
+static const char * const kUpdateIgnoreItselfPostStringID = "-";
+static const wchar_t kUpdateNewArchivePostCharID = '!';
+
+
+static bool ParseUpdateCommandString2(const UString &command,
+ NUpdateArchive::CActionSet &actionSet, UString &postString)
+{
+ for (unsigned i = 0; i < command.Len();)
+ {
+ wchar_t c = MyCharLower_Ascii(command[i]);
+ int statePos = FindCharPosInString(kUpdatePairStateIDSet, (char)c);
+ if (c > 0x7F || statePos < 0)
+ {
+ postString = command.Ptr(i);
+ return true;
+ }
+ i++;
+ if (i >= command.Len())
+ return false;
+ c = command[i];
+ if (c < '0' || c >= '0' + kNumUpdatePairActions)
+ return false;
+ unsigned actionPos = c - '0';
+ actionSet.StateActions[(unsigned)statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos);
+ if (kUpdatePairStateNotSupportedActions[(unsigned)statePos] == (int)actionPos)
+ return false;
+ i++;
+ }
+ postString.Empty();
+ return true;
+}
+
+static void ParseUpdateCommandString(CUpdateOptions &options,
+ const UStringVector &updatePostStrings,
+ const NUpdateArchive::CActionSet &defaultActionSet)
+{
+ const char *errorMessage = "incorrect update switch command";
+ unsigned i;
+ for (i = 0; i < updatePostStrings.Size(); i++)
+ {
+ const UString &updateString = updatePostStrings[i];
+ if (updateString.IsEqualTo(kUpdateIgnoreItselfPostStringID))
+ {
+ if (options.UpdateArchiveItself)
+ {
+ options.UpdateArchiveItself = false;
+ options.Commands.Delete(0);
+ }
+ }
+ else
+ {
+ NUpdateArchive::CActionSet actionSet = defaultActionSet;
+
+ UString postString;
+ if (!ParseUpdateCommandString2(updateString, actionSet, postString))
+ break;
+ if (postString.IsEmpty())
+ {
+ if (options.UpdateArchiveItself)
+ options.Commands[0].ActionSet = actionSet;
+ }
+ else
+ {
+ if (postString[0] != kUpdateNewArchivePostCharID)
+ break;
+ CUpdateArchiveCommand uc;
+ UString archivePath = postString.Ptr(1);
+ if (archivePath.IsEmpty())
+ break;
+ uc.UserArchivePath = archivePath;
+ uc.ActionSet = actionSet;
+ options.Commands.Add(uc);
+ }
+ }
+ }
+ if (i != updatePostStrings.Size())
+ throw CArcCmdLineException(errorMessage, updatePostStrings[i]);
+}
+
+bool ParseComplexSize(const wchar_t *s, UInt64 &result);
+
+static void SetAddCommandOptions(
+ NCommandType::EEnum commandType,
+ const CParser &parser,
+ CUpdateOptions &options)
+{
+ NUpdateArchive::CActionSet defaultActionSet;
+ switch (commandType)
+ {
+ case NCommandType::kAdd:
+ defaultActionSet = NUpdateArchive::k_ActionSet_Add;
+ break;
+ case NCommandType::kDelete:
+ defaultActionSet = NUpdateArchive::k_ActionSet_Delete;
+ break;
+ default:
+ defaultActionSet = NUpdateArchive::k_ActionSet_Update;
+ }
+
+ options.UpdateArchiveItself = true;
+
+ options.Commands.Clear();
+ CUpdateArchiveCommand updateMainCommand;
+ updateMainCommand.ActionSet = defaultActionSet;
+ options.Commands.Add(updateMainCommand);
+ if (parser[NKey::kUpdate].ThereIs)
+ ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings,
+ defaultActionSet);
+ if (parser[NKey::kWorkingDir].ThereIs)
+ {
+ const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];
+ if (postString.IsEmpty())
+ NDir::MyGetTempPath(options.WorkingDir);
+ else
+ options.WorkingDir = us2fs(postString);
+ }
+ options.SfxMode = parser[NKey::kSfx].ThereIs;
+ if (options.SfxMode)
+ options.SfxModule = us2fs(parser[NKey::kSfx].PostStrings[0]);
+
+ if (parser[NKey::kVolume].ThereIs)
+ {
+ const UStringVector &sv = parser[NKey::kVolume].PostStrings;
+ FOR_VECTOR (i, sv)
+ {
+ UInt64 size;
+ if (!ParseComplexSize(sv[i], size) || size == 0)
+ throw CArcCmdLineException("Incorrect volume size:", sv[i]);
+ options.VolumesSizes.Add(size);
+ }
+ }
+}
+
+static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties)
+{
+ if (parser[NKey::kProperty].ThereIs)
+ {
+ FOR_VECTOR (i, parser[NKey::kProperty].PostStrings)
+ {
+ CProperty prop;
+ prop.Name = parser[NKey::kProperty].PostStrings[i];
+ int index = prop.Name.Find(L'=');
+ if (index >= 0)
+ {
+ prop.Value = prop.Name.Ptr(index + 1);
+ prop.Name.DeleteFrom(index);
+ }
+ properties.Add(prop);
+ }
+ }
+}
+
+
+static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res)
+{
+ if (sw.ThereIs)
+ res = sw.PostCharIndex;
+}
+
+
+void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
+ CArcCmdLineOptions &options)
+{
+ if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings))
+ throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine);
+
+ 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.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)
+ {
+ g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus;
+ options.CaseSensitiveChange = true;
+ options.CaseSensitive = g_CaseSensitive;
+ }
+
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ NSecurity::EnablePrivilege_SymLink();
+ #endif
+
+ // options.LargePages = false;
+
+ if (parser[NKey::kLargePages].ThereIs)
+ {
+ unsigned slp = 0;
+ const UString &s = parser[NKey::kLargePages].PostStrings[0];
+ if (s.IsEmpty())
+ slp = 1;
+ else if (s != L"-")
+ {
+ if (!StringToUInt32(s, slp))
+ throw CArcCmdLineException("Unsupported switch postfix for -slp", s);
+ }
+
+ #ifdef _7ZIP_LARGE_PAGES
+ if (slp >
+ #ifndef UNDER_CE
+ (unsigned)NSecurity::Get_LargePages_RiskLevel()
+ #else
+ 0
+ #endif
+ )
+ {
+ SetLargePageSize();
+ // note: this process also can inherit that Privilege from parent process
+ g_LargePagesMode =
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ NSecurity::EnablePrivilege_LockMemory();
+ #else
+ true;
+ #endif
+ }
+ #endif
+ }
+
+
+ #ifndef UNDER_CE
+
+ if (parser[NKey::kAffinity].ThereIs)
+ {
+ const UString &s = 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
+}
+
+struct CCodePagePair
+{
+ const char *Name;
+ Int32 CodePage;
+};
+
+static const unsigned kNumByteOnlyCodePages = 3;
+
+static const CCodePagePair g_CodePagePairs[] =
+{
+ { "utf-8", CP_UTF8 },
+ { "win", CP_ACP },
+ { "dos", CP_OEMCP },
+ { "utf-16le", MY__CP_UTF16 },
+ { "utf-16be", MY__CP_UTF16BE }
+};
+
+static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned keyIndex,
+ bool byteOnlyCodePages, Int32 defaultVal)
+{
+ if (!parser[keyIndex].ThereIs)
+ return defaultVal;
+
+ UString name (parser[keyIndex].PostStrings.Back());
+ UInt32 v;
+ if (StringToUInt32(name, v))
+ if (v < ((UInt32)1 << 16))
+ return (Int32)v;
+ name.MakeLower_Ascii();
+ unsigned num = byteOnlyCodePages ? kNumByteOnlyCodePages : ARRAY_SIZE(g_CodePagePairs);
+ for (unsigned i = 0;; i++)
+ {
+ if (i == num) // to disable warnings from different compilers
+ throw CArcCmdLineException("Unsupported charset:", name);
+ const CCodePagePair &pair = g_CodePagePairs[i];
+ if (name.IsEqualTo(pair.Name))
+ return pair.CodePage;
+ }
+}
+
+
+static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp)
+{
+ bp.Def = parser[switchID].ThereIs;
+ if (bp.Def)
+ bp.Val = !parser[switchID].WithMinus;
+}
+
+void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
+{
+ const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
+ const unsigned numNonSwitchStrings = nonSwitchStrings.Size();
+ if (numNonSwitchStrings < kMinNonSwitchWords)
+ throw CArcCmdLineException("The command must be specified");
+
+ if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
+ throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]);
+
+ if (parser[NKey::kHash].ThereIs)
+ options.HashMethods = parser[NKey::kHash].PostStrings;
+
+ if (parser[NKey::kElimDup].ThereIs)
+ {
+ options.ExtractOptions.ElimDup.Def = true;
+ options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus;
+ }
+
+ NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath;
+ bool fullPathMode = parser[NKey::kFullPathMode].ThereIs;
+ if (fullPathMode)
+ {
+ censorPathMode = NWildcard::k_AbsPath;
+ const UString &s = parser[NKey::kFullPathMode].PostStrings[0];
+ if (!s.IsEmpty())
+ {
+ if (s == L"2")
+ censorPathMode = NWildcard::k_FullPath;
+ else
+ throw CArcCmdLineException("Unsupported -spf:", s);
+ }
+ }
+
+ if (parser[NKey::kNameTrailReplace].ThereIs)
+ g_PathTrailReplaceMode = !parser[NKey::kNameTrailReplace].WithMinus;
+
+ NRecursedType::EEnum recursedType;
+ if (parser[NKey::kRecursed].ThereIs)
+ recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
+ else
+ recursedType = NRecursedType::kNonRecursed;
+
+ bool wildcardMatching = true;
+ if (parser[NKey::kDisableWildcardParsing].ThereIs)
+ wildcardMatching = false;
+
+ g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1);
+ Int32 codePage = FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8);
+
+ bool thereAreSwitchIncludes = false;
+
+ if (parser[NKey::kInclude].ThereIs)
+ {
+ thereAreSwitchIncludes = true;
+ AddSwitchWildcardsToCensor(options.Censor,
+ parser[NKey::kInclude].PostStrings, true, recursedType, wildcardMatching, codePage);
+ }
+
+ if (parser[NKey::kExclude].ThereIs)
+ AddSwitchWildcardsToCensor(options.Censor,
+ parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage);
+
+ unsigned curCommandIndex = kCommandIndex + 1;
+ bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&
+ options.Command.CommandType != NCommandType::kBenchmark &&
+ options.Command.CommandType != NCommandType::kInfo &&
+ options.Command.CommandType != NCommandType::kHash;
+
+ bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+ bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList;
+ bool isRename = options.Command.CommandType == NCommandType::kRename;
+
+ if ((isExtractOrList || isRename) && options.StdInMode)
+ thereIsArchiveName = false;
+
+ if (parser[NKey::kArcNameMode].ThereIs)
+ options.UpdateOptions.ArcNameMode = ParseArcNameMode(parser[NKey::kArcNameMode].PostCharIndex);
+
+ if (thereIsArchiveName)
+ {
+ if (curCommandIndex >= numNonSwitchStrings)
+ throw CArcCmdLineException("Cannot find archive name");
+ 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,
+ curCommandIndex, options.Censor,
+ nonSwitchStrings, parser.StopSwitchIndex,
+ recursedType, wildcardMatching,
+ thereAreSwitchIncludes, codePage);
+
+ options.YesToAll = parser[NKey::kYes].ThereIs;
+
+
+ #ifndef _NO_CRYPTO
+ options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
+ if (options.PasswordEnabled)
+ options.Password = parser[NKey::kPassword].PostStrings[0];
+ #endif
+
+ options.ShowDialog = parser[NKey::kShowDialog].ThereIs;
+
+ if (parser[NKey::kArchiveType].ThereIs)
+ options.ArcType = parser[NKey::kArchiveType].PostStrings[0];
+
+ options.ExcludedArcTypes = parser[NKey::kExcludedArcType].PostStrings;
+
+ SetMethodOptions(parser, options.Properties);
+
+ if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue();
+
+ SetBoolPair(parser, NKey::kAltStreams, options.AltStreams);
+ SetBoolPair(parser, NKey::kHardLinks, options.HardLinks);
+ SetBoolPair(parser, NKey::kSymLinks, options.SymLinks);
+
+ if (isExtractOrList)
+ {
+ CExtractOptionsBase &eo = options.ExtractOptions;
+
+ {
+ CExtractNtOptions &nt = eo.NtOptions;
+ nt.NtSecurity = options.NtSecurity;
+
+ nt.AltStreams = options.AltStreams;
+ if (!options.AltStreams.Def)
+ nt.AltStreams.Val = true;
+
+ nt.HardLinks = options.HardLinks;
+ if (!options.HardLinks.Def)
+ nt.HardLinks.Val = true;
+
+ nt.SymLinks = options.SymLinks;
+ if (!options.SymLinks.Def)
+ nt.SymLinks.Val = true;
+
+ nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;
+ nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;
+ }
+
+ options.Censor.AddPathsToCensor(NWildcard::k_AbsPath);
+ options.Censor.ExtendExclude();
+
+ // are there paths that look as non-relative (!Prefix.IsEmpty())
+ if (!options.Censor.AllAreRelative())
+ throw CArcCmdLineException("Cannot use absolute pathnames for this command");
+
+ NWildcard::CCensor &arcCensor = options.arcCensor;
+
+ if (parser[NKey::kArInclude].ThereIs)
+ AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage);
+ if (parser[NKey::kArExclude].ThereIs)
+ AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, wildcardMatching, codePage);
+
+ if (thereIsArchiveName)
+ AddNameToCensor(arcCensor, options.ArchiveName, true, NRecursedType::kNonRecursed, wildcardMatching);
+
+ arcCensor.AddPathsToCensor(NWildcard::k_RelatPath);
+
+ #ifdef _WIN32
+ ConvertToLongNames(arcCensor);
+ #endif
+
+ arcCensor.ExtendExclude();
+
+ if (options.StdInMode)
+ options.ArcName_for_StdInMode = parser[NKey::kStdIn].PostStrings.Front();
+
+ if (isExtractGroupCommand)
+ {
+ if (options.StdOutMode)
+ {
+ if (
+ options.Number_for_Percents == k_OutStream_stdout
+ // || options.Number_for_Out == k_OutStream_stdout
+ // || options.Number_for_Errors == k_OutStream_stdout
+ ||
+ (
+ (options.IsStdOutTerminal && options.IsStdErrTerminal)
+ &&
+ (
+ options.Number_for_Percents != k_OutStream_disabled
+ // || options.Number_for_Out != k_OutStream_disabled
+ // || options.Number_for_Errors != k_OutStream_disabled
+ )
+ )
+ )
+ throw CArcCmdLineException(kSameTerminalError);
+ }
+
+ if (parser[NKey::kOutputDir].ThereIs)
+ {
+ eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);
+ NFile::NName::NormalizeDirPathPrefix(eo.OutputDir);
+ }
+
+ eo.OverwriteMode = NExtract::NOverwriteMode::kAsk;
+ if (parser[NKey::kOverwrite].ThereIs)
+ {
+ eo.OverwriteMode = k_OverwriteModes[(unsigned)parser[NKey::kOverwrite].PostCharIndex];
+ eo.OverwriteMode_Force = true;
+ }
+ else if (options.YesToAll)
+ {
+ eo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite;
+ eo.OverwriteMode_Force = true;
+ }
+ }
+
+ eo.PathMode = options.Command.GetPathMode();
+ if (censorPathMode == NWildcard::k_AbsPath)
+ {
+ eo.PathMode = NExtract::NPathMode::kAbsPaths;
+ eo.PathMode_Force = true;
+ }
+ else if (censorPathMode == NWildcard::k_FullPath)
+ {
+ eo.PathMode = NExtract::NPathMode::kFullPaths;
+ eo.PathMode_Force = true;
+ }
+ }
+ else if (options.Command.IsFromUpdateGroup())
+ {
+ if (parser[NKey::kArInclude].ThereIs)
+ throw CArcCmdLineException("-ai switch is not supported for this command");
+
+ CUpdateOptions &updateOptions = options.UpdateOptions;
+
+ SetAddCommandOptions(options.Command.CommandType, parser, updateOptions);
+
+ updateOptions.MethodMode.Properties = options.Properties;
+
+ if (parser[NKey::kShareForWrite].ThereIs)
+ updateOptions.OpenShareForWrite = true;
+ if (parser[NKey::kStopAfterOpenError].ThereIs)
+ updateOptions.StopAfterOpenError = true;
+
+ updateOptions.PathMode = censorPathMode;
+
+ updateOptions.AltStreams = options.AltStreams;
+ updateOptions.NtSecurity = options.NtSecurity;
+ updateOptions.HardLinks = options.HardLinks;
+ updateOptions.SymLinks = options.SymLinks;
+
+ updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
+ if (updateOptions.EMailMode)
+ {
+ updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
+ if (updateOptions.EMailAddress.Len() > 0)
+ if (updateOptions.EMailAddress[0] == L'.')
+ {
+ updateOptions.EMailRemoveAfter = true;
+ updateOptions.EMailAddress.Delete(0);
+ }
+ }
+
+ updateOptions.StdOutMode = options.StdOutMode;
+ updateOptions.StdInMode = options.StdInMode;
+
+ updateOptions.DeleteAfterCompressing = parser[NKey::kDeleteAfterCompressing].ThereIs;
+ updateOptions.SetArcMTime = parser[NKey::kSetArcMTime].ThereIs;
+
+ if (updateOptions.StdOutMode && updateOptions.EMailMode)
+ throw CArcCmdLineException("stdout mode and email mode cannot be combined");
+
+ if (updateOptions.StdOutMode)
+ {
+ if (options.IsStdOutTerminal)
+ throw CArcCmdLineException(kTerminalOutError);
+
+ if (options.Number_for_Percents == k_OutStream_stdout
+ || options.Number_for_Out == k_OutStream_stdout
+ || options.Number_for_Errors == k_OutStream_stdout)
+ throw CArcCmdLineException(kSameTerminalError);
+ }
+
+ if (updateOptions.StdInMode)
+ updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();
+
+ if (options.Command.CommandType == NCommandType::kRename)
+ if (updateOptions.Commands.Size() != 1)
+ throw CArcCmdLineException("Only one archive can be created with rename command");
+ }
+ else if (options.Command.CommandType == NCommandType::kBenchmark)
+ {
+ options.NumIterations = 1;
+ if (curCommandIndex < numNonSwitchStrings)
+ {
+ if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations))
+ throw CArcCmdLineException("Incorrect Number of benmchmark iterations", nonSwitchStrings[curCommandIndex]);
+ curCommandIndex++;
+ }
+ }
+ else if (options.Command.CommandType == NCommandType::kHash)
+ {
+ options.Censor.AddPathsToCensor(censorPathMode);
+ options.Censor.ExtendExclude();
+
+ CHashOptions &hashOptions = options.HashOptions;
+ hashOptions.PathMode = censorPathMode;
+ hashOptions.Methods = options.HashMethods;
+ if (parser[NKey::kShareForWrite].ThereIs)
+ hashOptions.OpenShareForWrite = true;
+ hashOptions.StdInMode = options.StdInMode;
+ hashOptions.AltStreamsMode = options.AltStreams.Val;
+ }
+ else if (options.Command.CommandType == NCommandType::kInfo)
+ {
+ }
+ else
+ throw 20150919;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.h
new file mode 100644
index 0000000000..bba3c98aa6
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -0,0 +1,136 @@
+// ArchiveCommandLine.h
+
+#ifndef __ARCHIVE_COMMAND_LINE_H
+#define __ARCHIVE_COMMAND_LINE_H
+
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/Wildcard.h"
+
+#include "EnumDirItems.h"
+
+#include "Extract.h"
+#include "HashCalc.h"
+#include "Update.h"
+
+typedef CMessagePathException CArcCmdLineException;
+
+namespace NCommandType { enum EEnum
+{
+ kAdd = 0,
+ kUpdate,
+ kDelete,
+ kTest,
+ kExtract,
+ kExtractFull,
+ kList,
+ kBenchmark,
+ kInfo,
+ kHash,
+ kRename
+};}
+
+struct CArcCommand
+{
+ NCommandType::EEnum CommandType;
+
+ bool IsFromExtractGroup() const;
+ bool IsFromUpdateGroup() const;
+ bool IsTestCommand() const { return CommandType == NCommandType::kTest; }
+ NExtract::NPathMode::EEnum GetPathMode() const;
+};
+
+enum
+{
+ k_OutStream_disabled = 0,
+ k_OutStream_stdout = 1,
+ k_OutStream_stderr = 2
+};
+
+struct CArcCmdLineOptions
+{
+ bool HelpMode;
+
+ // bool LargePages;
+ bool CaseSensitiveChange;
+ bool CaseSensitive;
+
+ bool IsInTerminal;
+ bool IsStdOutTerminal;
+ bool IsStdErrTerminal;
+ bool StdInMode;
+ bool StdOutMode;
+ bool EnableHeaders;
+
+ bool YesToAll;
+ bool ShowDialog;
+ NWildcard::CCensor Censor;
+
+ CArcCommand Command;
+ UString ArchiveName;
+
+ #ifndef _NO_CRYPTO
+ bool PasswordEnabled;
+ UString Password;
+ #endif
+
+ bool TechMode;
+ bool ShowTime;
+
+ UStringVector HashMethods;
+
+ bool AppendName;
+ // UStringVector ArchivePathsSorted;
+ // UStringVector ArchivePathsFullSorted;
+ NWildcard::CCensor arcCensor;
+ UString ArcName_for_StdInMode;
+
+ CObjectVector<CProperty> Properties;
+
+ CExtractOptionsBase ExtractOptions;
+
+ CBoolPair NtSecurity;
+ CBoolPair AltStreams;
+ CBoolPair HardLinks;
+ CBoolPair SymLinks;
+
+ CUpdateOptions UpdateOptions;
+ CHashOptions HashOptions;
+ UString ArcType;
+ UStringVector ExcludedArcTypes;
+
+ 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),
+
+ Number_for_Out(k_OutStream_stdout),
+ Number_for_Errors(k_OutStream_stderr),
+ Number_for_Percents(k_OutStream_stdout),
+
+ LogLevel(0)
+ {
+ };
+};
+
+class CArcCmdLineParser
+{
+ NCommandLineParser::CParser parser;
+public:
+ void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options);
+ void Parse2(CArcCmdLineOptions &options);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
new file mode 100644
index 0000000000..1119d1b43e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -0,0 +1,1691 @@
+// ArchiveExtractCallback.cpp
+
+#include "StdAfx.h"
+
+#undef sprintf
+#undef printf
+
+// #include <stdio.h>
+// #include "../../../../C/CpuTicks.h"
+
+#include "../../../../C/Alloc.h"
+#include "../../../../C/CpuArch.h"
+
+
+#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"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
+
+#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
+#define _USE_SECURITY_CODE
+#include "../../../Windows/SecurityUtils.h"
+#endif
+
+#include "../../Common/FilePathAutoRename.h"
+// #include "../../Common/StreamUtils.h"
+
+#include "../Common/ExtractingFilePath.h"
+#include "../Common/PropIDUtils.h"
+
+#include "ArchiveExtractCallback.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+static const char * const kCantAutoRename = "Can not create file with auto name";
+static const char * const kCantRenameFile = "Can not rename existing file";
+static const char * const kCantDeleteOutputFile = "Can not delete output file";
+static const char * const kCantDeleteOutputDir = "Can not delete output folder";
+static const char * const kCantCreateHardLink = "Can not create hard link";
+static const char * const kCantCreateSymLink = "Can not create symbolic link";
+static const char * const kCantOpenOutFile = "Can not open output file";
+static const char * const kCantSetFileLen = "Can not set length for output file";
+
+
+#ifndef _SFX
+
+STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ if (_calculate)
+ _hash->Update(data, size);
+ _size += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
+}
+
+#endif
+
+#ifdef _USE_SECURITY_CODE
+bool InitLocalPrivileges()
+{
+ NSecurity::CAccessToken token;
+ if (!token.OpenProcessToken(GetCurrentProcess(),
+ TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))
+ return false;
+
+ TOKEN_PRIVILEGES tp;
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid))
+ return false;
+ if (!token.AdjustPrivileges(&tp))
+ return false;
+ return (GetLastError() == ERROR_SUCCESS);
+}
+#endif
+
+#ifdef SUPPORT_LINKS
+
+int CHardLinkNode::Compare(const CHardLinkNode &a) const
+{
+ if (StreamId < a.StreamId) return -1;
+ if (StreamId > a.StreamId) return 1;
+ return MyCompare(INode, a.INode);
+}
+
+static HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)
+{
+ h.INode = 0;
+ h.StreamId = (UInt64)(Int64)-1;
+ defined = false;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidINode, &prop));
+ if (!ConvertPropVariantToUInt64(prop, h.INode))
+ return S_OK;
+ }
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidStreamId, &prop));
+ ConvertPropVariantToUInt64(prop, h.StreamId);
+ }
+ defined = true;
+ return S_OK;
+}
+
+
+HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *realIndices)
+{
+ _hardLinks.Clear();
+
+ if (!_arc->Ask_INode)
+ return S_OK;
+
+ IInArchive *archive = _arc->Archive;
+ CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs;
+
+ {
+ UInt32 numItems;
+ if (realIndices)
+ numItems = realIndices->Size();
+ else
+ {
+ RINOK(archive->GetNumberOfItems(&numItems));
+ }
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ CHardLinkNode h;
+ bool defined;
+ UInt32 realIndex = realIndices ? (*realIndices)[i] : i;
+
+ RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined));
+ if (defined)
+ {
+ bool isAltStream = false;
+ RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream));
+ if (!isAltStream)
+ hardIDs.Add(h);
+ }
+ }
+ }
+
+ hardIDs.Sort2();
+
+ {
+ // wee keep only items that have 2 or more items
+ unsigned k = 0;
+ unsigned numSame = 1;
+ for (unsigned i = 1; i < hardIDs.Size(); i++)
+ {
+ if (hardIDs[i].Compare(hardIDs[i - 1]) != 0)
+ numSame = 1;
+ else if (++numSame == 2)
+ {
+ if (i - 1 != k)
+ hardIDs[k] = hardIDs[i - 1];
+ k++;
+ }
+ }
+ hardIDs.DeleteFrom(k);
+ }
+
+ _hardLinks.PrepareLinks();
+ return S_OK;
+}
+
+#endif
+
+CArchiveExtractCallback::CArchiveExtractCallback():
+ _arc(NULL),
+ WriteCTime(true),
+ WriteATime(true),
+ WriteMTime(true),
+ _multiArchives(false)
+{
+ LocalProgressSpec = new CLocalProgress();
+ _localProgress = LocalProgressSpec;
+
+ #ifdef _USE_SECURITY_CODE
+ _saclEnabled = InitLocalPrivileges();
+ #endif
+}
+
+void CArchiveExtractCallback::Init(
+ const CExtractNtOptions &ntOptions,
+ const NWildcard::CCensorNode *wildcardCensor,
+ const CArc *arc,
+ IFolderArchiveExtractCallback *extractCallback2,
+ bool stdOutMode, bool testMode,
+ const FString &directoryPath,
+ const UStringVector &removePathParts, bool removePartsForAltStreams,
+ UInt64 packSize)
+{
+ ClearExtractedDirsInfo();
+ _outFileStream.Release();
+
+ #ifdef SUPPORT_LINKS
+ _hardLinks.Clear();
+ #endif
+
+ #ifdef SUPPORT_ALT_STREAMS
+ _renamedFiles.Clear();
+ #endif
+
+ _ntOptions = ntOptions;
+ _wildcardCensor = wildcardCensor;
+
+ _stdOutMode = stdOutMode;
+ _testMode = testMode;
+
+ // _progressTotal = 0;
+ // _progressTotal_Defined = false;
+
+ _packTotal = packSize;
+ _progressTotal = packSize;
+ _progressTotal_Defined = true;
+
+ _extractCallback2 = extractCallback2;
+ _compressProgress.Release();
+ _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
+ _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage, &_callbackMessage);
+ _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2);
+
+ #ifndef _SFX
+
+ _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback);
+ if (ExtractToStreamCallback)
+ {
+ Int32 useStreams = 0;
+ if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)
+ useStreams = 0;
+ if (useStreams == 0)
+ ExtractToStreamCallback.Release();
+ }
+
+ #endif
+
+ LocalProgressSpec->Init(extractCallback2, true);
+ LocalProgressSpec->SendProgress = false;
+
+ _removePathParts = removePathParts;
+ _removePartsForAltStreams = removePartsForAltStreams;
+
+ #ifndef _SFX
+ _baseParentFolder = (UInt32)(Int32)-1;
+ _use_baseParentFolder_mode = false;
+ #endif
+
+ _arc = arc;
+ _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
+ _progressTotal = size;
+ _progressTotal_Defined = true;
+ if (!_multiArchives && _extractCallback2)
+ return _extractCallback2->SetTotal(size);
+ return S_OK;
+ COM_TRY_END
+}
+
+static void NormalizeVals(UInt64 &v1, UInt64 &v2)
+{
+ const UInt64 kMax = (UInt64)1 << 31;
+ while (v1 > kMax)
+ {
+ v1 >>= 1;
+ v2 >>= 1;
+ }
+}
+
+static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)
+{
+ NormalizeVals(packTotal, unpTotal);
+ NormalizeVals(unpCur, unpTotal);
+ if (unpTotal == 0)
+ unpTotal = 1;
+ return unpCur * packTotal / unpTotal;
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
+{
+ COM_TRY_BEGIN
+
+ if (!_extractCallback2)
+ return S_OK;
+
+ UInt64 packCur;
+ if (_multiArchives)
+ {
+ packCur = LocalProgressSpec->InSize;
+ if (completeValue && _progressTotal_Defined)
+ packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal);
+ completeValue = &packCur;
+ }
+ return _extractCallback2->SetCompleted(completeValue);
+
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ COM_TRY_BEGIN
+ return _localProgress->SetRatioInfo(inSize, outSize);
+ COM_TRY_END
+}
+
+void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)
+{
+ bool isAbsPath = false;
+
+ if (!dirPathParts.IsEmpty())
+ {
+ const UString &s = dirPathParts[0];
+ if (s.IsEmpty())
+ isAbsPath = true;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ else
+ {
+ if (NName::IsDrivePath2(s))
+ isAbsPath = true;
+ }
+ #endif
+ }
+
+ if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath)
+ fullPath.Empty();
+ else
+ fullPath = _dirPathPrefix;
+
+ FOR_VECTOR (i, dirPathParts)
+ {
+ if (i != 0)
+ fullPath.Add_PathSepar();
+ const UString &s = dirPathParts[i];
+ fullPath += us2fs(s);
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (_pathMode == NExtract::NPathMode::kAbsPaths)
+ if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s))
+ continue;
+ #endif
+ CreateDir(fullPath);
+ }
+}
+
+HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
+{
+ filetimeIsDefined = false;
+ filetime.dwLowDateTime = 0;
+ filetime.dwHighDateTime = 0;
+ NCOM::CPropVariant prop;
+ RINOK(_arc->Archive->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ filetime = prop.filetime;
+ filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+HRESULT CArchiveExtractCallback::GetUnpackSize()
+{
+ return _arc->GetItemSize(_index, _curSize, _curSizeDefined);
+}
+
+static void AddPathToMessage(UString &s, const FString &path)
+{
+ s += " : ";
+ s += fs2us(path);
+}
+
+HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)
+{
+ UString s (message);
+ AddPathToMessage(s, path);
+ return _extractCallback2->MessageError(s);
+}
+
+HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)
+{
+ DWORD errorCode = GetLastError();
+ UString s (message);
+ if (errorCode != 0)
+ {
+ s += " : ";
+ s += NError::MyFormatMessage(errorCode);
+ }
+ AddPathToMessage(s, path);
+ return _extractCallback2->MessageError(s);
+}
+
+HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2)
+{
+ UString s (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;
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+ }
+ */
+ return Arc->Archive->GetProperty(IndexInArc, propID, value);
+}
+
+#endif
+
+
+#ifdef SUPPORT_LINKS
+
+static UString GetDirPrefixOf(const UString &src)
+{
+ UString s (src);
+ if (!s.IsEmpty())
+ {
+ if (IsPathSepar(s.Back()))
+ s.DeleteBack();
+ int pos = s.ReverseFind_PathSepar();
+ s.DeleteFrom(pos + 1);
+ }
+ return s;
+}
+
+#endif
+
+
+bool IsSafePath(const UString &path)
+{
+ if (NName::IsAbsolutePath(path))
+ return false;
+
+ UStringVector parts;
+ SplitPathToParts(path, parts);
+ unsigned level = 0;
+
+ FOR_VECTOR (i, parts)
+ {
+ const UString &s = parts[i];
+ if (s.IsEmpty())
+ {
+ if (i == 0)
+ return false;
+ continue;
+ }
+ if (s == L".")
+ continue;
+ if (s == L"..")
+ {
+ if (level == 0)
+ return false;
+ level--;
+ }
+ else
+ level++;
+ }
+
+ return level > 0;
+}
+
+
+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 += ':';
+ 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;
+}
+
+
+/*
+#ifdef SUPPORT_LINKS
+
+struct CTempMidBuffer
+{
+ void *Buf;
+
+ CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); }
+ ~CTempMidBuffer() { ::MidFree(Buf); }
+};
+
+HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream)
+{
+ const size_t kBufSize = 1 << 16;
+ CTempMidBuffer buf(kBufSize);
+ if (!buf.Buf)
+ return E_OUTOFMEMORY;
+
+ NIO::CInFile inFile;
+ NIO::COutFile outFile;
+
+ if (!inFile.Open(_CopyFile_Path))
+ return SendMessageError_with_LastError("Open error", _CopyFile_Path);
+
+ for (;;)
+ {
+ UInt32 num;
+
+ if (!inFile.Read(buf.Buf, kBufSize, num))
+ return SendMessageError_with_LastError("Read error", _CopyFile_Path);
+
+ if (num == 0)
+ return S_OK;
+
+
+ RINOK(WriteStream(outStream, buf.Buf, num));
+ }
+}
+
+#endif
+*/
+
+
+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
+{
+ COM_TRY_BEGIN
+
+ *outStream = NULL;
+
+ #ifndef _SFX
+ if (_hashStream)
+ _hashStreamSpec->ReleaseStream();
+ _hashStreamWasUsed = false;
+ #endif
+
+ _outFileStream.Release();
+
+ _encrypted = false;
+ _position = 0;
+ _isSplit = false;
+
+ _curSize = 0;
+ _curSizeDefined = false;
+ _fileLengthWasSet = false;
+ _index = index;
+
+ _diskFilePath.Empty();
+
+ // _fi.Clear();
+
+ #ifdef SUPPORT_LINKS
+ // _CopyFile_Path.Empty();
+ linkPath.Empty();
+ #endif
+
+ IInArchive *archive = _arc->Archive;
+
+ #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;
+ RINOK(archive->GetProperty(index, kpidPosition, &prop));
+ if (prop.vt != VT_EMPTY)
+ {
+ if (prop.vt != VT_UI8)
+ return E_FAIL;
+ _position = prop.uhVal.QuadPart;
+ _isSplit = true;
+ }
+ }
+
+ #ifdef SUPPORT_LINKS
+
+ // bool isCopyLink = false;
+ bool isHardLink = false;
+ bool isJunction = false;
+ bool isRelative = false;
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidHardLink, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ isHardLink = true;
+ // isCopyLink = false;
+ isRelative = false; // RAR5, TAR: hard links are from root folder of archive
+ linkPath.SetFromBstr(prop.bstrVal);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ }
+
+ /*
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidCopyLink, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ isHardLink = false;
+ isCopyLink = true;
+ isRelative = false; // RAR5: copy links are from root folder of archive
+ linkPath.SetFromBstr(prop.bstrVal);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ }
+ */
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidSymLink, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ isHardLink = false;
+ // isCopyLink = false;
+ isRelative = true; // RAR5, TAR: symbolic links can be relative
+ linkPath.SetFromBstr(prop.bstrVal);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ }
+
+
+ bool isOkReparse = false;
+
+ if (linkPath.IsEmpty() && _arc->GetRawProps)
+ {
+ const void *data;
+ UInt32 dataSize;
+ UInt32 propType;
+
+ _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
+
+ if (dataSize != 0)
+ {
+ if (propType != NPropDataType::kRaw)
+ return E_FAIL;
+ UString s;
+ CReparseAttr reparse;
+ DWORD errorCode = 0;
+ isOkReparse = reparse.Parse((const Byte *)data, dataSize, errorCode);
+ if (isOkReparse)
+ {
+ isHardLink = false;
+ // isCopyLink = false;
+ linkPath = reparse.GetPath();
+ isJunction = reparse.IsMountPoint();
+ isRelative = reparse.IsRelative();
+ #ifndef _WIN32
+ linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR);
+ #endif
+ }
+ }
+ }
+
+ if (!linkPath.IsEmpty())
+ {
+ #ifdef _WIN32
+ linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR);
+ #endif
+
+ // rar5 uses "\??\" prefix for absolute links
+ if (linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR))
+ {
+ isRelative = false;
+ linkPath.DeleteFrontal(4);
+ }
+
+ for (;;)
+ // while (NName::IsAbsolutePath(linkPath))
+ {
+ unsigned n = NName::GetRootPrefixSize(linkPath);
+ if (n == 0)
+ break;
+ isRelative = false;
+ linkPath.DeleteFrontal(n);
+ }
+ }
+
+ if (!linkPath.IsEmpty() && !isRelative && _removePathParts.Size() != 0)
+ {
+ UStringVector pathParts;
+ SplitPathToParts(linkPath, pathParts);
+ bool badPrefix = false;
+ FOR_VECTOR (i, _removePathParts)
+ {
+ if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)
+ {
+ badPrefix = true;
+ break;
+ }
+ }
+ if (!badPrefix)
+ pathParts.DeleteFrontal(_removePathParts.Size());
+ linkPath = MakePathFromParts(pathParts);
+ }
+
+ #endif
+
+ RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted));
+
+ RINOK(GetUnpackSize());
+
+ #ifdef SUPPORT_ALT_STREAMS
+
+ if (!_ntOptions.AltStreams.Val && _item.IsAltStream)
+ return S_OK;
+
+ #endif
+
+
+ UStringVector &pathParts = _item.PathParts;
+
+ if (_wildcardCensor)
+ {
+ if (!CensorNode_CheckPath(*_wildcardCensor, _item))
+ return S_OK;
+ }
+
+ #ifndef _SFX
+ if (_use_baseParentFolder_mode)
+ {
+ 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
+ {
+ if (pathParts.IsEmpty())
+ {
+ 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())
+ 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 (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)
+ {
+ badPrefix = true;
+ break;
+ }
+ }
+ }
+
+ if (badPrefix)
+ {
+ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
+ return E_FAIL;
+ }
+ else
+ numRemovePathParts = _removePathParts.Size();
+ break;
+ }
+
+ case NExtract::NPathMode::kNoPaths:
+ {
+ 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;
+ }
+ /*
+ case NExtract::NPathMode::kFullPaths:
+ case NExtract::NPathMode::kAbsPaths:
+ break;
+ */
+ }
+
+ pathParts.DeleteFrontal(numRemovePathParts);
+ }
+
+ #ifndef _SFX
+
+ if (ExtractToStreamCallback)
+ {
+ if (!GetProp)
+ {
+ GetProp_Spec = new CGetProp;
+ GetProp = GetProp_Spec;
+ }
+ GetProp_Spec->Arc = _arc;
+ GetProp_Spec->IndexInArc = index;
+ UString name (MakePathFromParts(pathParts));
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if (_item.IsAltStream)
+ {
+ if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt))
+ name += ':';
+ name += _item.AltStreamName;
+ }
+ #endif
+
+ return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp);
+ }
+
+ #endif
+
+ CMyComPtr<ISequentialOutStream> outStreamLoc;
+
+if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
+{
+ if (_stdOutMode)
+ {
+ outStreamLoc = new CStdOutFileStream;
+ }
+ else
+ {
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidAttrib, &prop));
+ if (prop.vt == VT_UI4)
+ {
+ _fi.Attrib = prop.ulVal;
+ _fi.AttribDefined = true;
+ }
+ else if (prop.vt == VT_EMPTY)
+ _fi.AttribDefined = false;
+ else
+ return E_FAIL;
+ }
+
+ RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined));
+ RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined));
+ RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined));
+
+ bool isAnti = false;
+ RINOK(_arc->IsItemAnti(index, isAnti));
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if (!_item.IsAltStream
+ || !pathParts.IsEmpty()
+ || !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt))
+ #endif
+ Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir);
+
+ #ifdef SUPPORT_ALT_STREAMS
+
+ if (_item.IsAltStream)
+ {
+ UString s (_item.AltStreamName);
+ Correct_AltStream_Name(s);
+ bool needColon = true;
+
+ if (pathParts.IsEmpty())
+ {
+ pathParts.AddNew();
+ if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt)
+ needColon = false;
+ }
+ else if (_pathMode == NExtract::NPathMode::kAbsPaths &&
+ NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size())
+ pathParts.AddNew();
+
+ UString &name = pathParts.Back();
+ if (needColon)
+ name += (char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':');
+ name += s;
+ }
+
+ #endif
+
+ UString processedPath (MakePathFromParts(pathParts));
+
+ if (!isAnti)
+ {
+ if (!_item.IsDir)
+ {
+ if (!pathParts.IsEmpty())
+ pathParts.DeleteBack();
+ }
+
+ if (!pathParts.IsEmpty())
+ {
+ FString fullPathNew;
+ CreateComplexDirectory(pathParts, fullPathNew);
+
+ if (_item.IsDir)
+ {
+ CDirPathTime &pt = _extractedFolders.AddNew();
+
+ pt.CTime = _fi.CTime;
+ pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined);
+
+ pt.ATime = _fi.ATime;
+ pt.ATimeDefined = (WriteATime && _fi.ATimeDefined);
+
+ pt.MTimeDefined = false;
+
+ if (WriteMTime)
+ {
+ if (_fi.MTimeDefined)
+ {
+ pt.MTime = _fi.MTime;
+ pt.MTimeDefined = true;
+ }
+ else if (_arc->MTimeDefined)
+ {
+ pt.MTime = _arc->MTime;
+ pt.MTimeDefined = true;
+ }
+ }
+
+ pt.Path = fullPathNew;
+
+ pt.SetDirTime();
+ }
+ }
+ }
+
+
+ FString fullProcessedPath (us2fs(processedPath));
+ if (_pathMode != NExtract::NPathMode::kAbsPaths
+ || !NName::IsAbsolutePath(processedPath))
+ {
+ fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath);
+ }
+
+ #ifdef SUPPORT_ALT_STREAMS
+
+ if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1)
+ {
+ int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex));
+ if (renIndex >= 0)
+ {
+ const CIndexToPathPair &pair = _renamedFiles[renIndex];
+ fullProcessedPath = pair.Path;
+ fullProcessedPath += ':';
+ UString s (_item.AltStreamName);
+ Correct_AltStream_Name(s);
+ fullProcessedPath += us2fs(s);
+ }
+ }
+
+ #endif
+
+ bool isRenamed = false;
+
+ if (_item.IsDir)
+ {
+ _diskFilePath = fullProcessedPath;
+ if (isAnti)
+ RemoveDir(_diskFilePath);
+ #ifdef SUPPORT_LINKS
+ if (linkPath.IsEmpty())
+ #endif
+ return S_OK;
+ }
+ else if (!_isSplit)
+ {
+
+ // ----- Is file (not split) -----
+ NFind::CFileInfo fileInfo;
+ if (fileInfo.Find(fullProcessedPath))
+ {
+ switch (_overwriteMode)
+ {
+ case NExtract::NOverwriteMode::kSkip:
+ return S_OK;
+ case NExtract::NOverwriteMode::kAsk:
+ {
+ int slashPos = fullProcessedPath.ReverseFind_PathSepar();
+ FString realFullProcessedPath (fullProcessedPath.Left(slashPos + 1) + fileInfo.Name);
+
+ Int32 overwriteResult;
+ RINOK(_extractCallback2->AskOverwrite(
+ fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path,
+ _fi.MTimeDefined ? &_fi.MTime : NULL,
+ _curSizeDefined ? &_curSize : NULL,
+ &overwriteResult))
+
+ switch (overwriteResult)
+ {
+ case NOverwriteAnswer::kCancel: return E_ABORT;
+ case NOverwriteAnswer::kNo: return S_OK;
+ case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK;
+ case NOverwriteAnswer::kYes: break;
+ case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kOverwrite; break;
+ case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kRename; break;
+ default:
+ return E_FAIL;
+ }
+ }
+ }
+ if (_overwriteMode == NExtract::NOverwriteMode::kRename)
+ {
+ if (!AutoRenamePath(fullProcessedPath))
+ {
+ RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
+ return E_FAIL;
+ }
+ isRenamed = true;
+ }
+ else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)
+ {
+ FString existPath (fullProcessedPath);
+ if (!AutoRenamePath(existPath))
+ {
+ RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
+ return E_FAIL;
+ }
+ // MyMoveFile can raname folders. So it's OK to use it for folders too
+ if (!MyMoveFile(fullProcessedPath, existPath))
+ {
+ RINOK(SendMessageError2(kCantRenameFile, existPath, fullProcessedPath));
+ return E_FAIL;
+ }
+ }
+ else
+ {
+ if (fileInfo.IsDir())
+ {
+ // do we need to delete all files in folder?
+ if (!RemoveDir(fullProcessedPath))
+ {
+ RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath));
+ return S_OK;
+ }
+ }
+ else
+ {
+ 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;
+
+
+ if (!isAnti)
+ {
+ #ifdef SUPPORT_LINKS
+
+ if (!linkPath.IsEmpty())
+ {
+ #ifndef UNDER_CE
+
+ UString relatPath;
+ if (isRelative)
+ relatPath = GetDirPrefixOf(_item.Path);
+ relatPath += linkPath;
+
+ if (!IsSafePath(relatPath))
+ {
+ RINOK(SendMessageError("Dangerous link path was ignored", us2fs(relatPath)));
+ }
+ else
+ {
+ FString existPath;
+ if (isHardLink /* || isCopyLink */ || !isRelative)
+ {
+ if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))
+ {
+ RINOK(SendMessageError("Incorrect path", us2fs(relatPath)));
+ }
+ }
+ else
+ {
+ existPath = us2fs(linkPath);
+ }
+
+ if (!existPath.IsEmpty())
+ {
+ if (isHardLink /* || isCopyLink */)
+ {
+ // if (isHardLink)
+ {
+ if (!MyCreateHardLink(fullProcessedPath, existPath))
+ {
+ RINOK(SendMessageError2(kCantCreateHardLink, fullProcessedPath, existPath));
+ // return S_OK;
+ }
+ }
+ /*
+ else
+ {
+ NFind::CFileInfo fi;
+ if (!fi.Find(existPath))
+ {
+ RINOK(SendMessageError2("Can not find the file for copying", existPath, fullProcessedPath));
+ }
+ else
+ {
+ if (_curSizeDefined && _curSize == fi.Size)
+ _CopyFile_Path = existPath;
+ else
+ {
+ RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath));
+ }
+
+ // RINOK(MyCopyFile(existPath, fullProcessedPath));
+ }
+ }
+ */
+ }
+ else if (_ntOptions.SymLinks.Val)
+ {
+ // bool isSymLink = true; // = false for junction
+ if (_item.IsDir && !isRelative)
+ {
+ // if it's before Vista we use Junction Point
+ // isJunction = true;
+ // convertToAbs = true;
+ }
+
+ CByteBuffer data;
+ if (FillLinkData(data, fs2us(existPath), !isJunction))
+ {
+ CReparseAttr attr;
+ DWORD errorCode = 0;
+ if (!attr.Parse(data, data.Size(), errorCode))
+ {
+ RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path)));
+ // return E_FAIL;
+ }
+ else
+ if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size()))
+ {
+ RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath));
+ }
+ }
+ }
+ }
+ }
+
+ #endif
+ }
+
+ if (linkPath.IsEmpty() /* || !_CopyFile_Path.IsEmpty() */)
+ #endif // SUPPORT_LINKS
+ {
+ bool needWriteFile = true;
+
+ #ifdef SUPPORT_LINKS
+ if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream)
+ {
+ CHardLinkNode h;
+ bool defined;
+ RINOK(Archive_Get_HardLinkNode(archive, index, h, defined));
+ if (defined)
+ {
+ {
+ int linkIndex = _hardLinks.IDs.FindInSorted2(h);
+ if (linkIndex >= 0)
+ {
+ FString &hl = _hardLinks.Links[linkIndex];
+ if (hl.IsEmpty())
+ hl = fullProcessedPath;
+ else
+ {
+ if (!MyCreateHardLink(fullProcessedPath, hl))
+ {
+ RINOK(SendMessageError2(kCantCreateHardLink, fullProcessedPath, hl));
+ return S_OK;
+ }
+ needWriteFile = false;
+ }
+ }
+ }
+ }
+ }
+ #endif
+
+ if (needWriteFile)
+ {
+ _outFileStreamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> outStreamLoc2(_outFileStreamSpec);
+ if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))
+ {
+ // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
+ {
+ RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath));
+ return S_OK;
+ }
+ }
+
+ if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSizeDefined && _curSize > (1 << 12))
+ {
+ // UInt64 ticks = GetCpuTicks();
+ bool res = _outFileStreamSpec->File.SetLength(_curSize);
+ _fileLengthWasSet = res;
+ _outFileStreamSpec->File.SeekToBegin();
+ // ticks = GetCpuTicks() - ticks;
+ // printf("\nticks = %10d\n", (unsigned)ticks);
+ if (!res)
+ {
+ RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath));
+ }
+ }
+
+ #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));
+ }
+
+ _outFileStream = outStreamLoc2;
+ }
+ }
+ }
+
+ outStreamLoc = _outFileStream;
+ }
+}
+
+ #ifndef _SFX
+
+ if (_hashStream)
+ {
+ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract ||
+ askExtractMode == NArchive::NExtract::NAskMode::kTest)
+ {
+ _hashStreamSpec->SetStream(outStreamLoc);
+ outStreamLoc = _hashStream;
+ _hashStreamSpec->Init(true);
+ _hashStreamWasUsed = true;
+ }
+ }
+
+ #endif
+
+
+ if (outStreamLoc)
+ {
+ /*
+ #ifdef SUPPORT_LINKS
+
+ if (!_CopyFile_Path.IsEmpty())
+ {
+ RINOK(PrepareOperation(askExtractMode));
+ RINOK(MyCopyFile(outStreamLoc));
+ return SetOperationResult(NArchive::NExtract::NOperationResult::kOK);
+ }
+
+ if (isCopyLink && _testMode)
+ return S_OK;
+
+ #endif
+ */
+
+ *outStream = outStreamLoc.Detach();
+ }
+
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
+{
+ COM_TRY_BEGIN
+
+ #ifndef _SFX
+ if (ExtractToStreamCallback)
+ return ExtractToStreamCallback->PrepareOperation7(askExtractMode);
+ #endif
+
+ _extractMode = false;
+
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract:
+ if (_testMode)
+ askExtractMode = NArchive::NExtract::NAskMode::kTest;
+ else
+ _extractMode = true;
+ break;
+ };
+
+ return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir),
+ askExtractMode, _isSplit ? &_position: 0);
+
+ COM_TRY_END
+}
+
+
+HRESULT CArchiveExtractCallback::CloseFile()
+{
+ if (!_outFileStream)
+ return S_OK;
+
+ HRESULT hres = S_OK;
+ _outFileStreamSpec->SetTime(
+ (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
+ (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
+ (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+
+ const UInt64 processedSize = _outFileStreamSpec->ProcessedSize;
+ if (_fileLengthWasSet && _curSize > processedSize)
+ {
+ bool res = _outFileStreamSpec->File.SetLength(processedSize);
+ _fileLengthWasSet = res;
+ if (!res)
+ hres = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path));
+ }
+ _curSize = processedSize;
+ _curSizeDefined = true;
+ RINOK(_outFileStreamSpec->Close());
+ _outFileStream.Release();
+ return hres;
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
+{
+ COM_TRY_BEGIN
+
+ #ifndef _SFX
+ if (ExtractToStreamCallback)
+ return ExtractToStreamCallback->SetOperationResult7(opRes, BoolToInt(_encrypted));
+ #endif
+
+ #ifndef _SFX
+
+ if (_hashStreamWasUsed)
+ {
+ _hashStreamSpec->_hash->Final(_item.IsDir,
+ #ifdef SUPPORT_ALT_STREAMS
+ _item.IsAltStream
+ #else
+ false
+ #endif
+ , _item.Path);
+ _curSize = _hashStreamSpec->GetSize();
+ _curSizeDefined = true;
+ _hashStreamSpec->ReleaseStream();
+ _hashStreamWasUsed = false;
+ }
+
+ #endif
+
+ RINOK(CloseFile());
+
+ #ifdef _USE_SECURITY_CODE
+ if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)
+ {
+ const void *data;
+ UInt32 dataSize;
+ UInt32 propType;
+ _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType);
+ if (dataSize != 0)
+ {
+ if (propType != NPropDataType::kRaw)
+ return E_FAIL;
+ if (CheckNtSecure((const Byte *)data, dataSize))
+ {
+ SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION;
+ if (_saclEnabled)
+ securInfo |= SACL_SECURITY_INFORMATION;
+ ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)data);
+ }
+ }
+ }
+ #endif
+
+ if (!_curSizeDefined)
+ GetUnpackSize();
+
+ if (_curSizeDefined)
+ {
+ #ifdef SUPPORT_ALT_STREAMS
+ if (_item.IsAltStream)
+ AltStreams_UnpackSize += _curSize;
+ else
+ #endif
+ UnpackSize += _curSize;
+ }
+
+ if (_item.IsDir)
+ NumFolders++;
+ #ifdef SUPPORT_ALT_STREAMS
+ else if (_item.IsAltStream)
+ NumAltStreams++;
+ #endif
+ else
+ NumFiles++;
+
+ if (!_stdOutMode && _extractMode && _fi.AttribDefined)
+ SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib);
+
+ RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
+
+ return S_OK;
+
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)
+{
+ if (_folderArchiveExtractCallback2)
+ {
+ bool isEncrypted = false;
+ UString s;
+
+ if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1)
+ {
+ CReadArcItem item;
+ RINOK(_arc->GetItem(index, item));
+ s = item.Path;
+ RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted));
+ }
+ else
+ {
+ s = '#';
+ s.Add_UInt32(index);
+ // if (indexType == NArchive::NEventIndexType::kBlockIndex) {}
+ }
+
+ return _folderArchiveExtractCallback2->ReportExtractResult(opRes, isEncrypted, s);
+ }
+
+ return S_OK;
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+ if (!_cryptoGetTextPassword)
+ {
+ RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,
+ &_cryptoGetTextPassword));
+ }
+ return _cryptoGetTextPassword->CryptoGetTextPassword(password);
+ COM_TRY_END
+}
+
+
+void CDirPathSortPair::SetNumSlashes(const FChar *s)
+{
+ for (unsigned numSlashes = 0;;)
+ {
+ FChar c = *s++;
+ if (c == 0)
+ {
+ Len = numSlashes;
+ return;
+ }
+ if (IS_PATH_SEPAR(c))
+ numSlashes++;
+ }
+}
+
+
+bool CDirPathTime::SetDirTime()
+{
+ return NDir::SetDirTime(Path,
+ CTimeDefined ? &CTime : NULL,
+ ATimeDefined ? &ATime : NULL,
+ MTimeDefined ? &MTime : NULL);
+}
+
+
+HRESULT CArchiveExtractCallback::SetDirsTimes()
+{
+ if (!_arc)
+ return S_OK;
+
+ CRecordVector<CDirPathSortPair> pairs;
+ pairs.ClearAndSetSize(_extractedFolders.Size());
+ unsigned i;
+
+ for (i = 0; i < _extractedFolders.Size(); i++)
+ {
+ CDirPathSortPair &pair = pairs[i];
+ pair.Index = i;
+ pair.SetNumSlashes(_extractedFolders[i].Path);
+ }
+
+ pairs.Sort2();
+
+ for (i = 0; i < pairs.Size(); i++)
+ {
+ _extractedFolders[pairs[i].Index].SetDirTime();
+ // if (!) return GetLastError();
+ }
+
+ ClearExtractedDirsInfo();
+ return S_OK;
+}
+
+
+HRESULT CArchiveExtractCallback::CloseArc()
+{
+ HRESULT res = CloseFile();
+ HRESULT res2 = SetDirsTimes();
+ if (res == S_OK)
+ res = res2;
+ _arc = NULL;
+ return res;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.h
new file mode 100644
index 0000000000..af38f13c3b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -0,0 +1,403 @@
+// ArchiveExtractCallback.h
+
+#ifndef __ARCHIVE_EXTRACT_CALLBACK_H
+#define __ARCHIVE_EXTRACT_CALLBACK_H
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../IPassword.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/ProgressUtils.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "ExtractMode.h"
+#include "IFileExtractCallback.h"
+#include "OpenArchive.h"
+
+#include "HashCalc.h"
+
+#ifndef _SFX
+
+class COutStreamWithHash:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+ bool _calculate;
+public:
+ IHashCalc *_hash;
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init(bool calculate = true)
+ {
+ InitCRC();
+ _size = 0;
+ _calculate = calculate;
+ }
+ void EnableCalc(bool calculate) { _calculate = calculate; }
+ void InitCRC() { _hash->InitForNewFile(); }
+ UInt64 GetSize() const { return _size; }
+};
+
+#endif
+
+struct CExtractNtOptions
+{
+ CBoolPair NtSecurity;
+ CBoolPair SymLinks;
+ CBoolPair HardLinks;
+ CBoolPair AltStreams;
+ bool ReplaceColonForAltStream;
+ bool WriteToAltStreamIfColon;
+
+ bool PreAllocateOutFile;
+
+ CExtractNtOptions():
+ ReplaceColonForAltStream(false),
+ WriteToAltStreamIfColon(false)
+ {
+ SymLinks.Val = true;
+ HardLinks.Val = true;
+ AltStreams.Val = true;
+
+ PreAllocateOutFile =
+ #ifdef _WIN32
+ true;
+ #else
+ false;
+ #endif
+ }
+};
+
+#ifndef _SFX
+
+class CGetProp:
+ public IGetProp,
+ public CMyUnknownImp
+{
+public:
+ const CArc *Arc;
+ UInt32 IndexInArc;
+ // UString Name; // relative path
+
+ MY_UNKNOWN_IMP1(IGetProp)
+ INTERFACE_IGetProp(;)
+};
+
+#endif
+
+#ifndef _SFX
+#ifndef UNDER_CE
+
+#define SUPPORT_LINKS
+
+#endif
+#endif
+
+
+#ifdef SUPPORT_LINKS
+
+struct CHardLinkNode
+{
+ UInt64 StreamId;
+ UInt64 INode;
+
+ int Compare(const CHardLinkNode &a) const;
+};
+
+class CHardLinks
+{
+public:
+ CRecordVector<CHardLinkNode> IDs;
+ CObjectVector<FString> Links;
+
+ void Clear()
+ {
+ IDs.Clear();
+ Links.Clear();
+ }
+
+ void PrepareLinks()
+ {
+ while (Links.Size() < IDs.Size())
+ Links.AddNew();
+ }
+};
+
+#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
+
+
+
+struct CDirPathTime
+{
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+
+ bool CTimeDefined;
+ bool ATimeDefined;
+ bool MTimeDefined;
+
+ FString Path;
+
+ bool SetDirTime();
+};
+
+
+
+class CArchiveExtractCallback:
+ public IArchiveExtractCallback,
+ public IArchiveExtractCallbackMessage,
+ public ICryptoGetTextPassword,
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+ const CArc *_arc;
+ CExtractNtOptions _ntOptions;
+
+ const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
+ CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
+ CMyComPtr<ICompressProgressInfo> _compressProgress;
+ CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
+ CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage;
+ CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
+
+ FString _dirPathPrefix;
+ FString _dirPathPrefix_Full;
+ NExtract::NPathMode::EEnum _pathMode;
+ NExtract::NOverwriteMode::EEnum _overwriteMode;
+ bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
+
+ #ifndef _SFX
+
+ CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
+ CGetProp *GetProp_Spec;
+ CMyComPtr<IGetProp> GetProp;
+
+ #endif
+
+ CReadArcItem _item;
+ FString _diskFilePath;
+ UInt64 _position;
+ bool _isSplit;
+
+ bool _extractMode;
+
+ bool WriteCTime;
+ bool WriteATime;
+ bool WriteMTime;
+
+ bool _encrypted;
+
+ struct CProcessedFileInfo
+ {
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+ UInt32 Attrib;
+
+ bool CTimeDefined;
+ bool ATimeDefined;
+ bool MTimeDefined;
+ bool AttribDefined;
+ } _fi;
+
+ UInt32 _index;
+ UInt64 _curSize;
+ bool _curSizeDefined;
+ bool _fileLengthWasSet;
+ COutFileStream *_outFileStreamSpec;
+ CMyComPtr<ISequentialOutStream> _outFileStream;
+
+ #ifndef _SFX
+
+ COutStreamWithHash *_hashStreamSpec;
+ CMyComPtr<ISequentialOutStream> _hashStream;
+ bool _hashStreamWasUsed;
+
+ #endif
+
+ bool _removePartsForAltStreams;
+ UStringVector _removePathParts;
+
+ #ifndef _SFX
+ bool _use_baseParentFolder_mode;
+ UInt32 _baseParentFolder;
+ #endif
+
+ bool _stdOutMode;
+ bool _testMode;
+ bool _multiArchives;
+
+ CMyComPtr<ICompressProgressInfo> _localProgress;
+ UInt64 _packTotal;
+
+ UInt64 _progressTotal;
+ bool _progressTotal_Defined;
+
+ CObjectVector<CDirPathTime> _extractedFolders;
+
+ #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
+ bool _saclEnabled;
+ #endif
+
+ void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
+ HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
+ 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:
+
+ CLocalProgress *LocalProgressSpec;
+
+ UInt64 NumFolders;
+ UInt64 NumFiles;
+ UInt64 NumAltStreams;
+ UInt64 UnpackSize;
+ UInt64 AltStreams_UnpackSize;
+
+ MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)
+
+ INTERFACE_IArchiveExtractCallback(;)
+ INTERFACE_IArchiveExtractCallbackMessage(;)
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+ CArchiveExtractCallback();
+
+ void InitForMulti(bool multiArchives,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ bool keepAndReplaceEmptyDirPrefixes)
+ {
+ _multiArchives = multiArchives;
+ _pathMode = pathMode;
+ _overwriteMode = overwriteMode;
+ _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
+ NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
+ }
+
+ #ifndef _SFX
+
+ void SetHashMethods(IHashCalc *hash)
+ {
+ if (!hash)
+ return;
+ _hashStreamSpec = new COutStreamWithHash;
+ _hashStream = _hashStreamSpec;
+ _hashStreamSpec->_hash = hash;
+ }
+
+ #endif
+
+ void Init(
+ const CExtractNtOptions &ntOptions,
+ const NWildcard::CCensorNode *wildcardCensor,
+ const CArc *arc,
+ IFolderArchiveExtractCallback *extractCallback2,
+ bool stdOutMode, bool testMode,
+ const FString &directoryPath,
+ const UStringVector &removePathParts, bool removePartsForAltStreams,
+ UInt64 packSize);
+
+
+ #ifdef SUPPORT_LINKS
+
+private:
+ CHardLinks _hardLinks;
+ UString linkPath;
+
+ // FString _CopyFile_Path;
+ // HRESULT MyCopyFile(ISequentialOutStream *outStream);
+
+public:
+ // call PrepareHardLinks() after Init()
+ 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)
+ {
+ _baseParentFolder = indexInArc;
+ _use_baseParentFolder_mode = true;
+ }
+ #endif
+
+ HRESULT CloseArc();
+
+private:
+ void ClearExtractedDirsInfo()
+ {
+ _extractedFolders.Clear();
+ }
+
+ HRESULT CloseFile();
+ HRESULT SetDirsTimes();
+};
+
+
+struct CArchiveExtractCallback_Closer
+{
+ CArchiveExtractCallback *_ref;
+
+ CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
+
+ HRESULT Close()
+ {
+ HRESULT res = S_OK;
+ if (_ref)
+ {
+ res = _ref->CloseArc();
+ _ref = NULL;
+ }
+ return res;
+ }
+
+ ~CArchiveExtractCallback_Closer()
+ {
+ Close();
+ }
+};
+
+
+bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.cpp
new file mode 100644
index 0000000000..aa47f7afdd
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.cpp
@@ -0,0 +1,78 @@
+// ArchiveName.cpp
+
+#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 NFind::CFileInfo &fi, bool keepName)
+{
+ FString resultName = fi.Name;
+ if (!fi.IsDir() && !keepName)
+ {
+ int dotPos = resultName.ReverseFind_Dot();
+ if (dotPos > 0)
+ {
+ FString archiveName2 = resultName.Left(dotPos);
+ if (archiveName2.ReverseFind_Dot() < 0)
+ resultName = archiveName2;
+ }
+ }
+ return Get_Correct_FsFile_Name(fs2us(resultName));
+}
+
+static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName)
+{
+ FString resultName ("Archive");
+ if (fromPrev)
+ {
+ FString dirPrefix;
+ if (NDir::GetOnlyDirPrefix(path, dirPrefix))
+ {
+ 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();
+ NFind::CFileInfo fi;
+ if (fi.Find(dirPrefix))
+ resultName = fi.Name;
+ }
+ }
+ }
+ }
+ else
+ {
+ NFind::CFileInfo fi;
+ if (fi.Find(path))
+ {
+ resultName = fi.Name;
+ if (!fi.IsDir() && !keepName)
+ {
+ 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 &path, bool fromPrev, bool keepName)
+{
+ return Get_Correct_FsFile_Name(fs2us(CreateArchiveName2(us2fs(path), fromPrev, keepName)));
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.h
new file mode 100644
index 0000000000..7b49c7bb97
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.h
@@ -0,0 +1,13 @@
+// ArchiveName.h
+
+#ifndef __ARCHIVE_NAME_H
+#define __ARCHIVE_NAME_H
+
+#include "../../../Common/MyString.h"
+
+#include "../../../Windows/FileFind.h"
+
+UString CreateArchiveName(const UString &path, bool fromPrev, bool keepName);
+UString CreateArchiveName(const NWindows::NFile::NFind::CFileInfo &fileInfo, bool keepName);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
new file mode 100644
index 0000000000..a9fda7b2cb
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -0,0 +1,154 @@
+// ArchiveOpenCallback.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/ComTry.h"
+
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
+
+#include "../../Common/FileStreams.h"
+
+#include "ArchiveOpenCallback.h"
+
+using namespace NWindows;
+
+STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
+{
+ COM_TRY_BEGIN
+ if (ReOpenCallback)
+ return ReOpenCallback->SetTotal(files, bytes);
+ if (!Callback)
+ return S_OK;
+ return Callback->Open_SetTotal(files, bytes);
+ COM_TRY_END
+}
+
+STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
+{
+ COM_TRY_BEGIN
+ if (ReOpenCallback)
+ return ReOpenCallback->SetCompleted(files, bytes);
+ if (!Callback)
+ return S_OK;
+ return Callback->Open_SetCompleted(files, bytes);
+ COM_TRY_END
+}
+
+STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+ if (_subArchiveMode)
+ switch (propID)
+ {
+ case kpidName: prop = _subArchiveName; break;
+ // case kpidSize: prop = _subArchiveSize; break; // we don't use it now
+ }
+ else
+ switch (propID)
+ {
+ case kpidName: prop = _fileInfo.Name; break;
+ case kpidIsDir: prop = _fileInfo.IsDir(); break;
+ case kpidSize: prop = _fileInfo.Size; break;
+ case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break;
+ case kpidCTime: prop = _fileInfo.CTime; break;
+ case kpidATime: prop = _fileInfo.ATime; break;
+ case kpidMTime: prop = _fileInfo.MTime; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+struct CInFileStreamVol: public CInFileStream
+{
+ int FileNameIndex;
+ COpenCallbackImp *OpenCallbackImp;
+ CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
+
+ ~CInFileStreamVol()
+ {
+ if (OpenCallbackRef)
+ OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false;
+ }
+};
+
+
+// from ArchiveExtractCallback.cpp
+bool IsSafePath(const UString &path);
+
+STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
+{
+ COM_TRY_BEGIN
+ *inStream = NULL;
+
+ if (_subArchiveMode)
+ return S_FALSE;
+ if (Callback)
+ {
+ RINOK(Callback->Open_CheckBreak());
+ }
+
+ UString name2 = name;
+
+
+ #ifndef _SFX
+
+ #ifdef _WIN32
+ name2.Replace(L'/', WCHAR_PATH_SEPARATOR);
+ #endif
+
+ // if (!allowAbsVolPaths)
+ if (!IsSafePath(name2))
+ return S_FALSE;
+
+ #endif
+
+
+ FString fullPath;
+ if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath))
+ return S_FALSE;
+ if (!_fileInfo.Find(fullPath))
+ return S_FALSE;
+ if (_fileInfo.IsDir())
+ return S_FALSE;
+ CInFileStreamVol *inFile = new CInFileStreamVol;
+ CMyComPtr<IInStream> inStreamTemp = inFile;
+ if (!inFile->Open(fullPath))
+ {
+ DWORD lastError = ::GetLastError();
+ if (lastError == 0)
+ return E_FAIL;
+ return HRESULT_FROM_WIN32(lastError);
+ }
+
+ FileSizes.Add(_fileInfo.Size);
+ FileNames.Add(name2);
+ inFile->FileNameIndex = FileNames_WasUsed.Add(true);
+ inFile->OpenCallbackImp = this;
+ inFile->OpenCallbackRef = this;
+ // TotalSize += _fileInfo.Size;
+ *inStream = inStreamTemp.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+#ifndef _NO_CRYPTO
+STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+ if (ReOpenCallback)
+ {
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+ ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+ if (getTextPassword)
+ return getTextPassword->CryptoGetTextPassword(password);
+ }
+ if (!Callback)
+ return E_NOTIMPL;
+ PasswordWasAsked = true;
+ return Callback->Open_CryptoGetTextPassword(password);
+ COM_TRY_END
+}
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.h
new file mode 100644
index 0000000000..7f7548f9c4
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -0,0 +1,112 @@
+// ArchiveOpenCallback.h
+
+#ifndef __ARCHIVE_OPEN_CALLBACK_H
+#define __ARCHIVE_OPEN_CALLBACK_H
+
+#include "../../../Common/MyCom.h"
+
+#include "../../../Windows/FileFind.h"
+
+#ifndef _NO_CRYPTO
+#include "../../IPassword.h"
+#endif
+#include "../../Archive/IArchive.h"
+
+#ifdef _NO_CRYPTO
+
+#define INTERFACE_IOpenCallbackUI_Crypto(x)
+
+#else
+
+#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_Clear_PasswordWasAsked_Flag() x; */ \
+
+#endif
+
+#define INTERFACE_IOpenCallbackUI(x) \
+ 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
+{
+ INTERFACE_IOpenCallbackUI(=0)
+};
+
+class COpenCallbackImp:
+ public IArchiveOpenCallback,
+ public IArchiveOpenVolumeCallback,
+ public IArchiveOpenSetSubArchiveName,
+ #ifndef _NO_CRYPTO
+ public ICryptoGetTextPassword,
+ #endif
+ public CMyUnknownImp
+{
+public:
+ MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback)
+ MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName)
+ #ifndef _NO_CRYPTO
+ MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ INTERFACE_IArchiveOpenCallback(;)
+ INTERFACE_IArchiveOpenVolumeCallback(;)
+
+ #ifndef _NO_CRYPTO
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+ #endif
+
+ STDMETHOD(SetSubArchiveName(const wchar_t *name))
+ {
+ _subArchiveMode = true;
+ _subArchiveName = name;
+ // TotalSize = 0;
+ return S_OK;
+ }
+
+private:
+ FString _folderPrefix;
+ NWindows::NFile::NFind::CFileInfo _fileInfo;
+ bool _subArchiveMode;
+ UString _subArchiveName;
+
+public:
+ UStringVector FileNames;
+ CBoolVector FileNames_WasUsed;
+ CRecordVector<UInt64> FileSizes;
+
+ bool PasswordWasAsked;
+
+ IOpenCallbackUI *Callback;
+ CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
+ // UInt64 TotalSize;
+
+ COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {}
+
+ void Init(const FString &folderPrefix, const FString &fileName)
+ {
+ _folderPrefix = folderPrefix;
+ if (!_fileInfo.Find(_folderPrefix + fileName))
+ throw 20121118;
+ FileNames.Clear();
+ FileNames_WasUsed.Clear();
+ FileSizes.Clear();
+ _subArchiveMode = false;
+ // TotalSize = 0;
+ PasswordWasAsked = false;
+ }
+
+ bool SetSecondFileInfo(CFSTR newName)
+ {
+ return _fileInfo.Find(newName) && !_fileInfo.IsDir();
+ }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.cpp
new file mode 100644
index 0000000000..c0d0e5497c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.cpp
@@ -0,0 +1,3492 @@
+// Bench.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#ifndef _WIN32
+#define USE_POSIX_TIME
+#define USE_POSIX_TIME2
+#endif
+
+#ifdef USE_POSIX_TIME
+#include <time.h>
+#ifdef USE_POSIX_TIME2
+#include <sys/time.h>
+#endif
+#endif
+
+#ifdef _WIN32
+#define USE_ALLOCA
+#endif
+
+#ifdef USE_ALLOCA
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+#include "../../../../C/7zCrc.h"
+#include "../../../../C/Alloc.h"
+#include "../../../../C/CpuArch.h"
+
+#ifndef _7ZIP_ST
+#include "../../../Windows/Synchronization.h"
+#include "../../../Windows/Thread.h"
+#endif
+
+#if defined(_WIN32) || defined(UNIX_USE_WIN_FILE)
+#define USE_WIN_FILE
+#endif
+
+#ifdef USE_WIN_FILE
+#include "../../../Windows/FileIO.h"
+#endif
+
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+
+#include "../../Common/MethodProps.h"
+#include "../../Common/StreamUtils.h"
+
+#include "Bench.h"
+
+using namespace NWindows;
+
+static const UInt32 k_LZMA = 0x030101;
+
+static const UInt64 kComplexInCommands = (UInt64)1 <<
+ #ifdef UNDER_CE
+ 31;
+ #else
+ 34;
+ #endif
+
+static const UInt32 kComplexInSeconds = 4;
+
+static void SetComplexCommands(UInt32 complexInSeconds,
+ bool isSpecifiedFreq, UInt64 cpuFreq, UInt64 &complexInCommands)
+{
+ complexInCommands = kComplexInCommands;
+ const UInt64 kMinFreq = (UInt64)1000000 * 4;
+ const UInt64 kMaxFreq = (UInt64)1000000 * 20000;
+ if (cpuFreq < kMinFreq && !isSpecifiedFreq)
+ cpuFreq = kMinFreq;
+ if (cpuFreq < kMaxFreq || isSpecifiedFreq)
+ {
+ if (complexInSeconds != 0)
+ complexInCommands = complexInSeconds * cpuFreq;
+ else
+ complexInCommands = cpuFreq >> 2;
+ }
+}
+
+static const unsigned kNumHashDictBits = 17;
+static const UInt32 kFilterUnpackSize = (48 << 10);
+
+static const unsigned kOldLzmaDictBits = 30;
+
+static const UInt32 kAdditionalSize = (1 << 16);
+static const UInt32 kCompressedAdditionalSize = (1 << 10);
+static const UInt32 kMaxLzmaPropSize = 5;
+
+class CBaseRandomGenerator
+{
+ UInt32 A1;
+ UInt32 A2;
+public:
+ CBaseRandomGenerator() { Init(); }
+ void Init() { A1 = 362436069; A2 = 521288629;}
+ UInt32 GetRnd()
+ {
+ return
+ ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) +
+ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );
+ }
+};
+
+
+static const unsigned kBufferAlignment = 1 << 4;
+
+struct CBenchBuffer
+{
+ size_t BufferSize;
+
+ #ifdef _WIN32
+
+ Byte *Buffer;
+
+ CBenchBuffer(): BufferSize(0), Buffer(NULL) {}
+ ~CBenchBuffer() { ::MidFree(Buffer); }
+
+ void AllocAlignedMask(size_t size, size_t)
+ {
+ ::MidFree(Buffer);
+ BufferSize = 0;
+ Buffer = (Byte *)::MidAlloc(size);
+ if (Buffer)
+ BufferSize = size;
+ }
+
+ #else
+
+ Byte *Buffer;
+ Byte *_bufBase;
+
+ CBenchBuffer(): BufferSize(0), Buffer(NULL), _bufBase(NULL){}
+ ~CBenchBuffer() { ::MidFree(_bufBase); }
+
+ void AllocAlignedMask(size_t size, size_t alignMask)
+ {
+ ::MidFree(_bufBase);
+ Buffer = NULL;
+ BufferSize = 0;
+ _bufBase = (Byte *)::MidAlloc(size + alignMask);
+
+ if (_bufBase)
+ {
+ // Buffer = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask);
+ Buffer = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask);
+ BufferSize = size;
+ }
+ }
+
+ #endif
+
+ bool Alloc(size_t size)
+ {
+ if (Buffer && BufferSize == size)
+ return true;
+ AllocAlignedMask(size, kBufferAlignment - 1);
+ return (Buffer != NULL || size == 0);
+ }
+};
+
+
+class CBenchRandomGenerator: public CBenchBuffer
+{
+ static UInt32 GetVal(UInt32 &res, unsigned numBits)
+ {
+ UInt32 val = res & (((UInt32)1 << numBits) - 1);
+ res >>= numBits;
+ return val;
+ }
+
+ static UInt32 GetLen(UInt32 &r)
+ {
+ UInt32 len = GetVal(r, 2);
+ return GetVal(r, 1 + len);
+ }
+
+public:
+
+ void GenerateSimpleRandom(CBaseRandomGenerator *_RG_)
+ {
+ CBaseRandomGenerator rg = *_RG_;
+ const size_t bufSize = BufferSize;
+ Byte *buf = Buffer;
+ for (size_t i = 0; i < bufSize; i++)
+ buf[i] = (Byte)rg.GetRnd();
+ *_RG_ = rg;
+ }
+
+ void GenerateLz(unsigned dictBits, CBaseRandomGenerator *_RG_)
+ {
+ CBaseRandomGenerator rg = *_RG_;
+ UInt32 pos = 0;
+ UInt32 rep0 = 1;
+ const size_t bufSize = BufferSize;
+ Byte *buf = Buffer;
+ unsigned posBits = 1;
+
+ while (pos < bufSize)
+ {
+ UInt32 r = rg.GetRnd();
+ if (GetVal(r, 1) == 0 || pos < 1024)
+ buf[pos++] = (Byte)(r & 0xFF);
+ else
+ {
+ UInt32 len;
+ len = 1 + GetLen(r);
+
+ if (GetVal(r, 3) != 0)
+ {
+ len += GetLen(r);
+
+ while (((UInt32)1 << posBits) < pos)
+ posBits++;
+
+ unsigned numBitsMax = dictBits;
+ if (numBitsMax > posBits)
+ numBitsMax = posBits;
+
+ const unsigned kAddBits = 6;
+ unsigned numLogBits = 5;
+ if (numBitsMax <= (1 << 4) - 1 + kAddBits)
+ numLogBits = 4;
+
+ for (;;)
+ {
+ UInt32 ppp = GetVal(r, numLogBits) + kAddBits;
+ r = rg.GetRnd();
+ if (ppp > numBitsMax)
+ continue;
+ rep0 = GetVal(r, ppp);
+ if (rep0 < pos)
+ break;
+ r = rg.GetRnd();
+ }
+ rep0++;
+ }
+
+ {
+ UInt32 rem = (UInt32)bufSize - pos;
+ if (len > rem)
+ len = rem;
+ }
+ Byte *dest = buf + pos;
+ const Byte *src = dest - rep0;
+ pos += len;
+ for (UInt32 i = 0; i < len; i++)
+ *dest++ = *src++;
+ }
+ }
+
+ *_RG_ = rg;
+ }
+};
+
+
+class CBenchmarkInStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ const Byte *Data;
+ size_t Pos;
+ size_t Size;
+public:
+ MY_UNKNOWN_IMP
+ void Init(const Byte *data, size_t size)
+ {
+ Data = data;
+ Size = size;
+ Pos = 0;
+ }
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ size_t remain = Size - Pos;
+ UInt32 kMaxBlockSize = (1 << 20);
+ if (size > kMaxBlockSize)
+ size = kMaxBlockSize;
+ if (size > remain)
+ size = (UInt32)remain;
+ for (UInt32 i = 0; i < size; i++)
+ ((Byte *)data)[i] = Data[Pos + i];
+ Pos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+}
+
+class CBenchmarkOutStream:
+ public ISequentialOutStream,
+ public CBenchBuffer,
+ public CMyUnknownImp
+{
+ // bool _overflow;
+public:
+ size_t Pos;
+ bool RealCopy;
+ bool CalcCrc;
+ UInt32 Crc;
+
+ // CBenchmarkOutStream(): _overflow(false) {}
+ void Init(bool realCopy, bool calcCrc)
+ {
+ Crc = CRC_INIT_VAL;
+ RealCopy = realCopy;
+ CalcCrc = calcCrc;
+ // _overflow = false;
+ Pos = 0;
+ }
+
+ // void Print() { printf("\n%8d %8d\n", (unsigned)BufferSize, (unsigned)Pos); }
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ size_t curSize = BufferSize - Pos;
+ if (curSize > size)
+ curSize = size;
+ 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)
+ {
+ // _overflow = true;
+ return E_FAIL;
+ }
+ return S_OK;
+}
+
+class CCrcOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ bool CalcCrc;
+ UInt32 Crc;
+ MY_UNKNOWN_IMP
+
+ CCrcOutStream(): CalcCrc(true) {};
+ void Init() { Crc = CRC_INIT_VAL; }
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (CalcCrc)
+ Crc = CrcUpdate(Crc, data, size);
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
+}
+
+static UInt64 GetTimeCount()
+{
+ #ifdef USE_POSIX_TIME
+ #ifdef USE_POSIX_TIME2
+ timeval v;
+ if (gettimeofday(&v, 0) == 0)
+ return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec;
+ return (UInt64)time(NULL) * 1000000;
+ #else
+ return time(NULL);
+ #endif
+ #else
+ /*
+ LARGE_INTEGER value;
+ if (::QueryPerformanceCounter(&value))
+ return value.QuadPart;
+ */
+ return GetTickCount();
+ #endif
+}
+
+static UInt64 GetFreq()
+{
+ #ifdef USE_POSIX_TIME
+ #ifdef USE_POSIX_TIME2
+ return 1000000;
+ #else
+ return 1;
+ #endif
+ #else
+ /*
+ LARGE_INTEGER value;
+ if (::QueryPerformanceFrequency(&value))
+ return value.QuadPart;
+ */
+ return 1000;
+ #endif
+}
+
+#ifdef USE_POSIX_TIME
+
+struct CUserTime
+{
+ UInt64 Sum;
+ clock_t Prev;
+
+ void Init()
+ {
+ Prev = clock();
+ Sum = 0;
+ }
+
+ UInt64 GetUserTime()
+ {
+ clock_t v = clock();
+ Sum += v - Prev;
+ Prev = v;
+ return Sum;
+ }
+};
+
+#else
+
+static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }
+UInt64 GetWinUserTime()
+{
+ FILETIME creationTime, exitTime, kernelTime, userTime;
+ if (
+ #ifdef UNDER_CE
+ ::GetThreadTimes(::GetCurrentThread()
+ #else
+ ::GetProcessTimes(::GetCurrentProcess()
+ #endif
+ , &creationTime, &exitTime, &kernelTime, &userTime) != 0)
+ return GetTime64(userTime) + GetTime64(kernelTime);
+ return (UInt64)GetTickCount() * 10000;
+}
+
+struct CUserTime
+{
+ UInt64 StartTime;
+
+ void Init() { StartTime = GetWinUserTime(); }
+ UInt64 GetUserTime() { return GetWinUserTime() - StartTime; }
+};
+
+#endif
+
+static UInt64 GetUserFreq()
+{
+ #ifdef USE_POSIX_TIME
+ return CLOCKS_PER_SEC;
+ #else
+ return 10000000;
+ #endif
+}
+
+class CBenchProgressStatus
+{
+ #ifndef _7ZIP_ST
+ NSynchronization::CCriticalSection CS;
+ #endif
+public:
+ HRESULT Res;
+ bool EncodeMode;
+ void SetResult(HRESULT res)
+ {
+ #ifndef _7ZIP_ST
+ NSynchronization::CCriticalSectionLock lock(CS);
+ #endif
+ Res = res;
+ }
+ HRESULT GetResult()
+ {
+ #ifndef _7ZIP_ST
+ NSynchronization::CCriticalSectionLock lock(CS);
+ #endif
+ return Res;
+ }
+};
+
+struct CBenchInfoCalc
+{
+ CBenchInfo BenchInfo;
+ CUserTime UserTime;
+
+ void SetStartTime();
+ void SetFinishTime(CBenchInfo &dest);
+};
+
+void CBenchInfoCalc::SetStartTime()
+{
+ BenchInfo.GlobalFreq = GetFreq();
+ BenchInfo.UserFreq = GetUserFreq();
+ BenchInfo.GlobalTime = ::GetTimeCount();
+ BenchInfo.UserTime = 0;
+ UserTime.Init();
+}
+
+void CBenchInfoCalc::SetFinishTime(CBenchInfo &dest)
+{
+ dest = BenchInfo;
+ dest.GlobalTime = ::GetTimeCount() - BenchInfo.GlobalTime;
+ dest.UserTime = UserTime.GetUserTime();
+}
+
+class CBenchProgressInfo:
+ public ICompressProgressInfo,
+ public CMyUnknownImp,
+ public CBenchInfoCalc
+{
+public:
+ CBenchProgressStatus *Status;
+ HRESULT Res;
+ IBenchCallback *Callback;
+
+ CBenchProgressInfo(): Callback(0) {}
+ MY_UNKNOWN_IMP
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ HRESULT res = Status->GetResult();
+ if (res != S_OK)
+ return res;
+ if (!Callback)
+ return res;
+ CBenchInfo info;
+ SetFinishTime(info);
+ if (Status->EncodeMode)
+ {
+ info.UnpackSize = BenchInfo.UnpackSize + *inSize;
+ info.PackSize = BenchInfo.PackSize + *outSize;
+ res = Callback->SetEncodeResult(info, false);
+ }
+ else
+ {
+ info.PackSize = BenchInfo.PackSize + *inSize;
+ info.UnpackSize = BenchInfo.UnpackSize + *outSize;
+ res = Callback->SetDecodeResult(info, false);
+ }
+ if (res != S_OK)
+ Status->SetResult(res);
+ return res;
+}
+
+static const unsigned kSubBits = 8;
+
+static UInt32 GetLogSize(UInt32 size)
+{
+ for (unsigned i = kSubBits; i < 32; i++)
+ for (UInt32 j = 0; j < (1 << kSubBits); j++)
+ if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
+ return (i << kSubBits) + j;
+ return (32 << kSubBits);
+}
+
+static void NormalizeVals(UInt64 &v1, UInt64 &v2)
+{
+ while (v1 > 1000000)
+ {
+ v1 >>= 1;
+ v2 >>= 1;
+ }
+}
+
+UInt64 CBenchInfo::GetUsage() const
+{
+ UInt64 userTime = UserTime;
+ UInt64 userFreq = UserFreq;
+ UInt64 globalTime = GlobalTime;
+ UInt64 globalFreq = GlobalFreq;
+ NormalizeVals(userTime, userFreq);
+ NormalizeVals(globalFreq, globalTime);
+ if (userFreq == 0)
+ userFreq = 1;
+ if (globalTime == 0)
+ globalTime = 1;
+ return userTime * globalFreq * 1000000 / userFreq / globalTime;
+}
+
+UInt64 CBenchInfo::GetRatingPerUsage(UInt64 rating) const
+{
+ UInt64 userTime = UserTime;
+ UInt64 userFreq = UserFreq;
+ UInt64 globalTime = GlobalTime;
+ UInt64 globalFreq = GlobalFreq;
+ NormalizeVals(userFreq, userTime);
+ NormalizeVals(globalTime, globalFreq);
+ if (globalFreq == 0)
+ globalFreq = 1;
+ if (userTime == 0)
+ userTime = 1;
+ return userFreq * globalTime / globalFreq * rating / userTime;
+}
+
+static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
+{
+ UInt64 elTime = elapsedTime;
+ NormalizeVals(freq, elTime);
+ if (elTime == 0)
+ elTime = 1;
+ return value * freq / elTime;
+}
+
+UInt64 CBenchInfo::GetSpeed(UInt64 numCommands) const
+{
+ return MyMultDiv64(numCommands, GlobalTime, GlobalFreq);
+}
+
+struct CBenchProps
+{
+ bool LzmaRatingMode;
+
+ UInt32 EncComplex;
+ UInt32 DecComplexCompr;
+ UInt32 DecComplexUnc;
+
+ CBenchProps(): LzmaRatingMode(false) {}
+ void SetLzmaCompexity();
+
+ UInt64 GeComprCommands(UInt64 unpackSize)
+ {
+ return unpackSize * EncComplex;
+ }
+
+ UInt64 GeDecomprCommands(UInt64 packSize, UInt64 unpackSize)
+ {
+ return (packSize * DecComplexCompr + unpackSize * DecComplexUnc);
+ }
+
+ UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size);
+ UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations);
+};
+
+void CBenchProps::SetLzmaCompexity()
+{
+ EncComplex = 1200;
+ DecComplexUnc = 4;
+ DecComplexCompr = 190;
+ LzmaRatingMode = true;
+}
+
+UInt64 CBenchProps::GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size)
+{
+ if (dictSize < (1 << kBenchMinDicLogSize))
+ dictSize = (1 << kBenchMinDicLogSize);
+ UInt64 encComplex = EncComplex;
+ if (LzmaRatingMode)
+ {
+ UInt64 t = GetLogSize(dictSize) - (kBenchMinDicLogSize << kSubBits);
+ encComplex = 870 + ((t * t * 5) >> (2 * kSubBits));
+ }
+ UInt64 numCommands = (UInt64)size * encComplex;
+ return MyMultDiv64(numCommands, elapsedTime, freq);
+}
+
+UInt64 CBenchProps::GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations)
+{
+ UInt64 numCommands = (inSize * DecComplexCompr + outSize * DecComplexUnc) * numIterations;
+ return MyMultDiv64(numCommands, elapsedTime, freq);
+}
+
+UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size)
+{
+ CBenchProps props;
+ props.SetLzmaCompexity();
+ return props.GetCompressRating(dictSize, elapsedTime, freq, size);
+}
+
+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations)
+{
+ CBenchProps props;
+ props.SetLzmaCompexity();
+ return props.GetDecompressRating(elapsedTime, freq, outSize, inSize, numIterations);
+}
+
+struct CEncoderInfo;
+
+struct CEncoderInfo
+{
+ #ifndef _7ZIP_ST
+ NWindows::CThread thread[2];
+ UInt32 NumDecoderSubThreads;
+ #endif
+ CMyComPtr<ICompressCoder> _encoder;
+ CMyComPtr<ICompressFilter> _encoderFilter;
+ CBenchProgressInfo *progressInfoSpec[2];
+ CMyComPtr<ICompressProgressInfo> progressInfo[2];
+ UInt64 NumIterations;
+
+ #ifdef USE_ALLOCA
+ size_t AllocaSize;
+ #endif
+
+ Byte _key[32];
+ Byte _iv[16];
+ Byte _psw[16];
+ bool CheckCrc_Enc;
+ bool CheckCrc_Dec;
+
+ struct CDecoderInfo
+ {
+ CEncoderInfo *Encoder;
+ UInt32 DecoderIndex;
+ bool CallbackMode;
+
+ #ifdef USE_ALLOCA
+ size_t AllocaSize;
+ #endif
+ };
+ CDecoderInfo decodersInfo[2];
+
+ CMyComPtr<ICompressCoder> _decoders[2];
+ CMyComPtr<ICompressFilter> _decoderFilter;
+
+ HRESULT Results[2];
+ CBenchmarkOutStream *outStreamSpec;
+ CMyComPtr<ISequentialOutStream> outStream;
+ IBenchCallback *callback;
+ IBenchPrintCallback *printCallback;
+ UInt32 crc;
+ size_t kBufferSize;
+ size_t compressedSize;
+ const Byte *uncompressedDataPtr;
+
+ const Byte *fileData;
+ CBenchRandomGenerator rg;
+
+ CBenchBuffer rgCopy; // it must be 16-byte aligned !!!
+ CBenchmarkOutStream *propStreamSpec;
+ CMyComPtr<ISequentialOutStream> propStream;
+
+ // for decode
+ COneMethodInfo _method;
+ size_t _uncompressedDataSize;
+
+ HRESULT Init(
+ const COneMethodInfo &method,
+ unsigned generateDictBits,
+ CBaseRandomGenerator *rg);
+ HRESULT Encode();
+ HRESULT Decode(UInt32 decoderIndex);
+
+ CEncoderInfo():
+ fileData(NULL),
+ CheckCrc_Enc(true),
+ CheckCrc_Dec(true),
+ outStreamSpec(0), callback(0), printCallback(0), propStreamSpec(0) {}
+
+ #ifndef _7ZIP_ST
+
+ static THREAD_FUNC_DECL EncodeThreadFunction(void *param)
+ {
+ HRESULT res;
+ CEncoderInfo *encoder = (CEncoderInfo *)param;
+ try
+ {
+ #ifdef USE_ALLOCA
+ alloca(encoder->AllocaSize);
+ #endif
+
+ res = encoder->Encode();
+ encoder->Results[0] = res;
+ }
+ catch(...)
+ {
+ res = E_FAIL;
+ }
+ if (res != S_OK)
+ 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;
+ }
+
+ HRESULT CreateEncoderThread()
+ {
+ return thread[0].Create(EncodeThreadFunction, this);
+ }
+
+ HRESULT CreateDecoderThread(unsigned index, bool callbackMode
+ #ifdef USE_ALLOCA
+ , size_t allocaSize
+ #endif
+ )
+ {
+ 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
+};
+
+
+HRESULT CEncoderInfo::Init(
+ const COneMethodInfo &method,
+ unsigned generateDictBits,
+ CBaseRandomGenerator *rgLoc)
+{
+ // we need extra space, if input data is already compressed
+ const size_t kCompressedBufferSize =
+ kCompressedAdditionalSize +
+ kBufferSize + kBufferSize / 16;
+ // kBufferSize / 2;
+
+ if (kCompressedBufferSize < kBufferSize)
+ return E_FAIL;
+
+ uncompressedDataPtr = fileData;
+
+ if (!fileData)
+ {
+ if (!rg.Alloc(kBufferSize))
+ return E_OUTOFMEMORY;
+
+ // DWORD ttt = GetTickCount();
+ if (generateDictBits == 0)
+ rg.GenerateSimpleRandom(rgLoc);
+ else
+ rg.GenerateLz(generateDictBits, rgLoc);
+ // printf("\n%d\n ", GetTickCount() - ttt);
+
+ crc = CrcCalc(rg.Buffer, rg.BufferSize);
+ uncompressedDataPtr = rg.Buffer;
+ }
+
+ if (_encoderFilter)
+ {
+ if (!rgCopy.Alloc(kBufferSize))
+ return E_OUTOFMEMORY;
+ }
+
+
+ outStreamSpec = new CBenchmarkOutStream;
+ outStream = outStreamSpec;
+ if (!outStreamSpec->Alloc(kCompressedBufferSize))
+ return E_OUTOFMEMORY;
+
+ propStreamSpec = 0;
+ if (!propStream)
+ {
+ propStreamSpec = new CBenchmarkOutStream;
+ propStream = propStreamSpec;
+ }
+ if (!propStreamSpec->Alloc(kMaxLzmaPropSize))
+ return E_OUTOFMEMORY;
+ propStreamSpec->Init(true, false);
+
+
+ CMyComPtr<IUnknown> coder;
+ if (_encoderFilter)
+ coder = _encoderFilter;
+ else
+ coder = _encoder;
+ {
+ CMyComPtr<ICompressSetCoderProperties> scp;
+ coder.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
+ {
+ UInt64 reduceSize = kBufferSize;
+ RINOK(method.SetCoderProps(scp, &reduceSize));
+ }
+ else
+ {
+ if (method.AreThereNonOptionalProps())
+ return E_INVALIDARG;
+ }
+
+ CMyComPtr<ICompressWriteCoderProperties> writeCoderProps;
+ coder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps);
+ if (writeCoderProps)
+ {
+ RINOK(writeCoderProps->WriteCoderProperties(propStream));
+ }
+
+ {
+ CMyComPtr<ICryptoSetPassword> sp;
+ coder.QueryInterface(IID_ICryptoSetPassword, &sp);
+ if (sp)
+ {
+ RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw)));
+
+ // we must call encoding one time to calculate password key for key cache.
+ // it must be after WriteCoderProperties!
+ Byte temp[16];
+ memset(temp, 0, sizeof(temp));
+
+ if (_encoderFilter)
+ {
+ _encoderFilter->Init();
+ _encoderFilter->Filter(temp, sizeof(temp));
+ }
+ else
+ {
+ CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+ inStreamSpec->Init(temp, sizeof(temp));
+
+ CCrcOutStream *crcStreamSpec = new CCrcOutStream;
+ CMyComPtr<ISequentialOutStream> crcStream = crcStreamSpec;
+ crcStreamSpec->Init();
+
+ RINOK(_encoder->Code(inStream, crcStream, 0, 0, NULL));
+ }
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+static void My_FilterBench(ICompressFilter *filter, Byte *data, size_t size)
+{
+ while (size != 0)
+ {
+ UInt32 cur = (UInt32)1 << 31;
+ if (cur > size)
+ cur = (UInt32)size;
+ UInt32 processed = filter->Filter(data, cur);
+ data += processed;
+ // if (processed > size) (in AES filter), we must fill last block with zeros.
+ // but it is not important for benchmark. So we just copy that data without filtering.
+ if (processed > size || processed == 0)
+ break;
+ size -= processed;
+ }
+}
+
+
+HRESULT CEncoderInfo::Encode()
+{
+ CBenchInfo &bi = progressInfoSpec[0]->BenchInfo;
+ bi.UnpackSize = 0;
+ bi.PackSize = 0;
+ CMyComPtr<ICryptoProperties> cp;
+ CMyComPtr<IUnknown> coder;
+ if (_encoderFilter)
+ coder = _encoderFilter;
+ else
+ coder = _encoder;
+ coder.QueryInterface(IID_ICryptoProperties, &cp);
+ CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+ UInt64 prev = 0;
+
+ UInt32 crcPrev = 0;
+
+ if (cp)
+ {
+ RINOK(cp->SetKey(_key, sizeof(_key)));
+ RINOK(cp->SetInitVector(_iv, sizeof(_iv)));
+ }
+
+ for (UInt64 i = 0; i < NumIterations; i++)
+ {
+ if (printCallback && bi.UnpackSize - prev > (1 << 20))
+ {
+ RINOK(printCallback->CheckBreak());
+ prev = bi.UnpackSize;
+ }
+
+ bool isLast = (i == NumIterations - 1);
+ bool calcCrc = ((isLast || (i & 0x7F) == 0 || CheckCrc_Enc) && NumIterations != 1);
+ outStreamSpec->Init(isLast, calcCrc);
+
+ if (_encoderFilter)
+ {
+ memcpy(rgCopy.Buffer, uncompressedDataPtr, kBufferSize);
+ _encoderFilter->Init();
+ My_FilterBench(_encoderFilter, rgCopy.Buffer, kBufferSize);
+ RINOK(WriteStream(outStream, rgCopy.Buffer, kBufferSize));
+ }
+ else
+ {
+ inStreamSpec->Init(uncompressedDataPtr, kBufferSize);
+ RINOK(_encoder->Code(inStream, outStream, NULL, NULL, progressInfo[0]));
+ }
+
+ // outStreamSpec->Print();
+
+ UInt32 crcNew = CRC_GET_DIGEST(outStreamSpec->Crc);
+ if (i == 0)
+ crcPrev = crcNew;
+ else if (calcCrc && crcPrev != crcNew)
+ return E_FAIL;
+
+ compressedSize = outStreamSpec->Pos;
+ bi.UnpackSize += kBufferSize;
+ bi.PackSize += compressedSize;
+ }
+
+ _encoder.Release();
+ _encoderFilter.Release();
+ return S_OK;
+}
+
+
+HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)
+{
+ CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
+ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+ CMyComPtr<ICompressCoder> &decoder = _decoders[decoderIndex];
+ CMyComPtr<IUnknown> coder;
+ if (_decoderFilter)
+ {
+ if (decoderIndex != 0)
+ return E_FAIL;
+ coder = _decoderFilter;
+ }
+ else
+ coder = decoder;
+
+ CMyComPtr<ICompressSetDecoderProperties2> setDecProps;
+ coder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps);
+ if (!setDecProps && propStreamSpec->Pos != 0)
+ return E_FAIL;
+
+ CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;
+ CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;
+
+ CBenchProgressInfo *pi = progressInfoSpec[decoderIndex];
+ pi->BenchInfo.UnpackSize = 0;
+ pi->BenchInfo.PackSize = 0;
+
+ #ifndef _7ZIP_ST
+ {
+ CMyComPtr<ICompressSetCoderMt> setCoderMt;
+ coder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ if (setCoderMt)
+ {
+ RINOK(setCoderMt->SetNumberOfThreads(NumDecoderSubThreads));
+ }
+ }
+ #endif
+
+ CMyComPtr<ICompressSetCoderProperties> scp;
+ coder.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
+ {
+ UInt64 reduceSize = _uncompressedDataSize;
+ RINOK(_method.SetCoderProps(scp, &reduceSize));
+ }
+
+ CMyComPtr<ICryptoProperties> cp;
+ coder.QueryInterface(IID_ICryptoProperties, &cp);
+
+ if (setDecProps)
+ {
+ RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, (UInt32)propStreamSpec->Pos));
+ }
+
+ {
+ CMyComPtr<ICryptoSetPassword> sp;
+ coder.QueryInterface(IID_ICryptoSetPassword, &sp);
+ if (sp)
+ {
+ RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw)));
+ }
+ }
+
+ UInt64 prev = 0;
+
+ if (cp)
+ {
+ RINOK(cp->SetKey(_key, sizeof(_key)));
+ RINOK(cp->SetInitVector(_iv, sizeof(_iv)));
+ }
+
+ for (UInt64 i = 0; i < NumIterations; i++)
+ {
+ if (printCallback && pi->BenchInfo.UnpackSize - prev > (1 << 20))
+ {
+ RINOK(printCallback->CheckBreak());
+ prev = pi->BenchInfo.UnpackSize;
+ }
+
+ inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
+ crcOutStreamSpec->Init();
+
+ UInt64 outSize = kBufferSize;
+ crcOutStreamSpec->CalcCrc = ((i & 0x7F) == 0 || CheckCrc_Dec);
+
+ if (_decoderFilter)
+ {
+ if (compressedSize > rgCopy.BufferSize)
+ return E_FAIL;
+ memcpy(rgCopy.Buffer, outStreamSpec->Buffer, compressedSize);
+ _decoderFilter->Init();
+ My_FilterBench(_decoderFilter, rgCopy.Buffer, compressedSize);
+ RINOK(WriteStream(crcOutStream, rgCopy.Buffer, compressedSize));
+ }
+ else
+ {
+ RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));
+ }
+
+ if (crcOutStreamSpec->CalcCrc && CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)
+ return S_FALSE;
+ pi->BenchInfo.UnpackSize += kBufferSize;
+ pi->BenchInfo.PackSize += compressedSize;
+ }
+
+ decoder.Release();
+ _decoderFilter.Release();
+ return S_OK;
+}
+
+
+static const UInt32 kNumThreadsMax = (1 << 12);
+
+struct CBenchEncoders
+{
+ CEncoderInfo *encoders;
+ CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; }
+ ~CBenchEncoders() { delete []encoders; }
+};
+
+
+static UInt64 GetNumIterations(UInt64 numCommands, UInt64 complexInCommands)
+{
+ if (numCommands < (1 << 4))
+ numCommands = (1 << 4);
+ UInt64 res = complexInCommands / numCommands;
+ return (res == 0 ? 1 : res);
+}
+
+
+static HRESULT MethodBench(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ UInt64 complexInCommands,
+ bool
+ #ifndef _7ZIP_ST
+ oldLzmaBenchMode
+ #endif
+ ,
+ UInt32
+ #ifndef _7ZIP_ST
+ numThreads
+ #endif
+ ,
+ const COneMethodInfo &method2,
+ size_t uncompressedDataSize,
+ const Byte *fileData,
+ unsigned generateDictBits,
+
+ IBenchPrintCallback *printCallback,
+ IBenchCallback *callback,
+ CBenchProps *benchProps)
+{
+ COneMethodInfo method = method2;
+ UInt64 methodId;
+ UInt32 numStreams;
+ int codecIndex = FindMethod_Index(
+ EXTERNAL_CODECS_LOC_VARS
+ method.MethodName, true,
+ methodId, numStreams);
+ if (codecIndex < 0)
+ return E_NOTIMPL;
+ if (numStreams != 1)
+ return E_INVALIDARG;
+
+ UInt32 numEncoderThreads = 1;
+ UInt32 numSubDecoderThreads = 1;
+
+ #ifndef _7ZIP_ST
+ numEncoderThreads = numThreads;
+
+ if (oldLzmaBenchMode && methodId == k_LZMA)
+ {
+ if (numThreads == 1 && method.Get_NumThreads() < 0)
+ method.AddProp_NumThreads(1);
+ const UInt32 numLzmaThreads = method.Get_Lzma_NumThreads();
+ if (numThreads > 1 && numLzmaThreads > 1)
+ {
+ numEncoderThreads = numThreads / 2;
+ numSubDecoderThreads = 2;
+ }
+ }
+ #endif
+
+ CBenchEncoders encodersSpec(numEncoderThreads);
+ CEncoderInfo *encoders = encodersSpec.encoders;
+
+ UInt32 i;
+
+ for (i = 0; i < numEncoderThreads; i++)
+ {
+ CEncoderInfo &encoder = encoders[i];
+ encoder.callback = (i == 0) ? callback : 0;
+ encoder.printCallback = printCallback;
+
+ {
+ CCreatedCoder cod;
+ RINOK(CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS codecIndex, 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 ;
+
+ memset(encoder._iv, 0, sizeof(encoder._iv));
+ memset(encoder._key, 0, sizeof(encoder._key));
+ memset(encoder._psw, 0, sizeof(encoder._psw));
+
+ for (UInt32 j = 0; j < numSubDecoderThreads; j++)
+ {
+ CCreatedCoder cod;
+ CMyComPtr<ICompressCoder> &decoder = encoder._decoders[j];
+ RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS methodId, false, encoder._decoderFilter, cod));
+ decoder = cod.Coder;
+ if (!encoder._decoderFilter && !decoder)
+ return E_NOTIMPL;
+ }
+ }
+
+ CBaseRandomGenerator rg;
+ rg.Init();
+
+ UInt32 crc = 0;
+ if (fileData)
+ crc = CrcCalc(fileData, uncompressedDataSize);
+
+ for (i = 0; i < numEncoderThreads; i++)
+ {
+ CEncoderInfo &encoder = encoders[i];
+ encoder._method = method;
+ encoder._uncompressedDataSize = uncompressedDataSize;
+ encoder.kBufferSize = uncompressedDataSize;
+ encoder.fileData = fileData;
+ encoder.crc = crc;
+
+ RINOK(encoders[i].Init(method, generateDictBits, &rg));
+ }
+
+ CBenchProgressStatus status;
+ status.Res = S_OK;
+ status.EncodeMode = true;
+
+ for (i = 0; i < numEncoderThreads; i++)
+ {
+ CEncoderInfo &encoder = encoders[i];
+ encoder.NumIterations = GetNumIterations(benchProps->GeComprCommands(uncompressedDataSize), complexInCommands);
+
+ for (int j = 0; j < 2; j++)
+ {
+ CBenchProgressInfo *spec = new CBenchProgressInfo;
+ encoder.progressInfoSpec[j] = spec;
+ encoder.progressInfo[j] = spec;
+ spec->Status = &status;
+ }
+
+ if (i == 0)
+ {
+ CBenchProgressInfo *bpi = encoder.progressInfoSpec[0];
+ bpi->Callback = callback;
+ bpi->BenchInfo.NumIterations = numEncoderThreads;
+ bpi->SetStartTime();
+ }
+
+ #ifndef _7ZIP_ST
+ if (numEncoderThreads > 1)
+ {
+ #ifdef USE_ALLOCA
+ encoder.AllocaSize = (i * 16 * 21) & 0x7FF;
+ #endif
+
+ RINOK(encoder.CreateEncoderThread())
+ }
+ else
+ #endif
+ {
+ RINOK(encoder.Encode());
+ }
+ }
+
+ #ifndef _7ZIP_ST
+ if (numEncoderThreads > 1)
+ for (i = 0; i < numEncoderThreads; i++)
+ encoders[i].thread[0].Wait();
+ #endif
+
+ RINOK(status.Res);
+
+ CBenchInfo info;
+
+ encoders[0].progressInfoSpec[0]->SetFinishTime(info);
+ info.UnpackSize = 0;
+ info.PackSize = 0;
+ info.NumIterations = encoders[0].NumIterations;
+
+ for (i = 0; i < numEncoderThreads; i++)
+ {
+ CEncoderInfo &encoder = encoders[i];
+ info.UnpackSize += encoder.kBufferSize;
+ info.PackSize += encoder.compressedSize;
+ }
+
+ RINOK(callback->SetEncodeResult(info, true));
+
+
+ status.Res = S_OK;
+ status.EncodeMode = false;
+
+ UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads;
+
+ for (i = 0; i < numEncoderThreads; i++)
+ {
+ CEncoderInfo &encoder = encoders[i];
+
+ if (i == 0)
+ {
+ encoder.NumIterations = GetNumIterations(benchProps->GeDecomprCommands(encoder.compressedSize, encoder.kBufferSize), complexInCommands);
+ CBenchProgressInfo *bpi = encoder.progressInfoSpec[0];
+ bpi->Callback = callback;
+ bpi->BenchInfo.NumIterations = numDecoderThreads;
+ bpi->SetStartTime();
+ }
+ else
+ encoder.NumIterations = encoders[0].NumIterations;
+
+ #ifndef _7ZIP_ST
+ {
+ int numSubThreads = method.Get_NumThreads();
+ encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : numSubThreads;
+ }
+ if (numDecoderThreads > 1)
+ {
+ for (UInt32 j = 0; j < numSubDecoderThreads; j++)
+ {
+ HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0)
+ #ifdef USE_ALLOCA
+ , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF
+ #endif
+ );
+ RINOK(res);
+ }
+ }
+ else
+ #endif
+ {
+ RINOK(encoder.Decode(0));
+ }
+ }
+
+ #ifndef _7ZIP_ST
+ HRESULT res = S_OK;
+ if (numDecoderThreads > 1)
+ for (i = 0; i < numEncoderThreads; i++)
+ for (UInt32 j = 0; j < numSubDecoderThreads; j++)
+ {
+ CEncoderInfo &encoder = encoders[i];
+ encoder.thread[j].Wait();
+ if (encoder.Results[j] != S_OK)
+ res = encoder.Results[j];
+ }
+ RINOK(res);
+ #endif
+
+ RINOK(status.Res);
+ encoders[0].progressInfoSpec[0]->SetFinishTime(info);
+
+ #ifndef _7ZIP_ST
+ #ifdef UNDER_CE
+ if (numDecoderThreads > 1)
+ for (i = 0; i < numEncoderThreads; i++)
+ for (UInt32 j = 0; j < numSubDecoderThreads; j++)
+ {
+ FILETIME creationTime, exitTime, kernelTime, userTime;
+ if (::GetThreadTimes(encoders[i].thread[j], &creationTime, &exitTime, &kernelTime, &userTime) != 0)
+ info.UserTime += GetTime64(userTime) + GetTime64(kernelTime);
+ }
+ #endif
+ #endif
+
+ info.UnpackSize = 0;
+ info.PackSize = 0;
+ info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;
+
+ for (i = 0; i < numEncoderThreads; i++)
+ {
+ CEncoderInfo &encoder = encoders[i];
+ info.UnpackSize += encoder.kBufferSize;
+ info.PackSize += encoder.compressedSize;
+ }
+
+ RINOK(callback->SetDecodeResult(info, false));
+ RINOK(callback->SetDecodeResult(info, true));
+
+ return S_OK;
+}
+
+
+static inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)
+{
+ UInt32 hs = dictionary - 1;
+ hs |= (hs >> 1);
+ hs |= (hs >> 2);
+ hs |= (hs >> 4);
+ hs |= (hs >> 8);
+ hs >>= 1;
+ hs |= 0xFFFF;
+ if (hs > (1 << 24))
+ hs >>= 1;
+ hs++;
+ return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 +
+ (1 << 20) + (multiThread ? (6 << 20) : 0);
+}
+
+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary, bool totalBench)
+{
+ const UInt32 kBufferSize = dictionary;
+ const UInt32 kCompressedBufferSize = kBufferSize; // / 2;
+ bool lzmaMt = (totalBench || numThreads > 1);
+ UInt32 numBigThreads = numThreads;
+ if (!totalBench && lzmaMt)
+ numBigThreads /= 2;
+ return ((UInt64)kBufferSize + kCompressedBufferSize +
+ GetLZMAUsage(lzmaMt, dictionary) + (2 << 20)) * numBigThreads;
+}
+
+static HRESULT CrcBig(const void *data, UInt32 size, UInt64 numIterations,
+ const UInt32 *checkSum, IHasher *hf,
+ IBenchPrintCallback *callback)
+{
+ Byte hash[64];
+ UInt64 i;
+ for (i = 0; i < sizeof(hash); i++)
+ hash[i] = 0;
+ for (i = 0; i < numIterations; i++)
+ {
+ if (callback && (i & 0xFF) == 0)
+ {
+ RINOK(callback->CheckBreak());
+ }
+ hf->Init();
+ hf->Update(data, size);
+ hf->Final(hash);
+ UInt32 hashSize = hf->GetDigestSize();
+ if (hashSize > sizeof(hash))
+ return S_FALSE;
+ UInt32 sum = 0;
+ for (UInt32 j = 0; j < hashSize; j += 4)
+ sum ^= GetUi32(hash + j);
+ if (checkSum && sum != *checkSum)
+ {
+ return S_FALSE;
+ }
+ }
+ return S_OK;
+}
+
+UInt32 g_BenchCpuFreqTemp = 1;
+
+#define YY1 sum += val; sum ^= val;
+#define YY3 YY1 YY1 YY1 YY1
+#define YY5 YY3 YY3 YY3 YY3
+#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++)
+ {
+ YY7
+ }
+ return sum;
+}
+
+EXTERN_C_END
+
+
+#ifndef _7ZIP_ST
+
+struct CFreqInfo
+{
+ NWindows::CThread Thread;
+ IBenchPrintCallback *Callback;
+ HRESULT CallbackRes;
+ UInt32 ValRes;
+ UInt32 Size;
+ UInt64 NumIterations;
+
+ void Wait()
+ {
+ Thread.Wait();
+ Thread.Close();
+ }
+};
+
+static THREAD_FUNC_DECL FreqThreadFunction(void *param)
+{
+ CFreqInfo *p = (CFreqInfo *)param;
+
+ UInt32 sum = g_BenchCpuFreqTemp;
+ for (UInt64 k = p->NumIterations; k > 0; k--)
+ {
+ p->CallbackRes = p->Callback->CheckBreak();
+ if (p->CallbackRes != S_OK)
+ return 0;
+ sum = CountCpuFreq(sum, p->Size, g_BenchCpuFreqTemp);
+ }
+ p->ValRes = sum;
+ return 0;
+}
+
+struct CFreqThreads
+{
+ CFreqInfo *Items;
+ UInt32 NumThreads;
+
+ CFreqThreads(): Items(0), NumThreads(0) {}
+ void WaitAll()
+ {
+ for (UInt32 i = 0; i < NumThreads; i++)
+ Items[i].Wait();
+ NumThreads = 0;
+ }
+ ~CFreqThreads()
+ {
+ WaitAll();
+ delete []Items;
+ }
+};
+
+struct CCrcInfo
+{
+ NWindows::CThread Thread;
+ IBenchPrintCallback *Callback;
+ HRESULT CallbackRes;
+
+ const Byte *Data;
+ UInt32 Size;
+ UInt64 NumIterations;
+ bool CheckSumDefined;
+ UInt32 CheckSum;
+ CMyComPtr<IHasher> Hasher;
+ HRESULT Res;
+
+ #ifdef USE_ALLOCA
+ size_t AllocaSize;
+ #endif
+
+ void Wait()
+ {
+ Thread.Wait();
+ Thread.Close();
+ }
+};
+
+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);
+ return 0;
+}
+
+struct CCrcThreads
+{
+ CCrcInfo *Items;
+ UInt32 NumThreads;
+
+ CCrcThreads(): Items(0), NumThreads(0) {}
+ void WaitAll()
+ {
+ for (UInt32 i = 0; i < NumThreads; i++)
+ Items[i].Wait();
+ NumThreads = 0;
+ }
+ ~CCrcThreads()
+ {
+ WaitAll();
+ delete []Items;
+ }
+};
+
+#endif
+
+static UInt32 CrcCalc1(const Byte *buf, UInt32 size)
+{
+ UInt32 crc = CRC_INIT_VAL;;
+ for (UInt32 i = 0; i < size; i++)
+ crc = CRC_UPDATE_BYTE(crc, buf[i]);
+ return CRC_GET_DIGEST(crc);
+}
+
+static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
+{
+ for (UInt32 i = 0; i < size; i++)
+ buf[i] = (Byte)RG.GetRnd();
+}
+
+static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
+{
+ RandGen(buf, size, RG);
+ return CrcCalc1(buf, size);
+}
+
+bool CrcInternalTest()
+{
+ CBenchBuffer buffer;
+ const UInt32 kBufferSize0 = (1 << 8);
+ const UInt32 kBufferSize1 = (1 << 10);
+ const UInt32 kCheckSize = (1 << 5);
+ if (!buffer.Alloc(kBufferSize0 + kBufferSize1))
+ return false;
+ Byte *buf = buffer.Buffer;
+ UInt32 i;
+ for (i = 0; i < kBufferSize0; i++)
+ buf[i] = (Byte)i;
+ UInt32 crc1 = CrcCalc1(buf, kBufferSize0);
+ if (crc1 != 0x29058C73)
+ return false;
+ CBaseRandomGenerator RG;
+ RandGen(buf + kBufferSize0, kBufferSize1, RG);
+ for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++)
+ for (UInt32 j = 0; j < kCheckSize; j++)
+ if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j))
+ return false;
+ return true;
+}
+
+struct CBenchMethod
+{
+ unsigned Weight;
+ unsigned DictBits;
+ UInt32 EncComplex;
+ UInt32 DecComplexCompr;
+ UInt32 DecComplexUnc;
+ const char *Name;
+};
+
+static const CBenchMethod g_Bench[] =
+{
+ { 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;
+};
+
+static const CBenchHash g_Hash[] =
+{
+ { 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" },
+ { 2, 5500, 0xE084E913, "BLAKE2sp" }
+};
+
+struct CTotalBenchRes
+{
+ // UInt64 NumIterations1; // for Usage
+ UInt64 NumIterations2; // for Rating / RPU
+
+ UInt64 Rating;
+ UInt64 Usage;
+ UInt64 RPU;
+
+ 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);
+ // NumIterations1 = (r1.NumIterations1 + r2.NumIterations1);
+ NumIterations2 = (r1.NumIterations2 + r2.NumIterations2);
+ }
+};
+
+static void PrintNumber(IBenchPrintCallback &f, UInt64 value, unsigned size)
+{
+ char s[128];
+ unsigned startPos = (unsigned)sizeof(s) - 32;
+ memset(s, ' ', startPos);
+ ConvertUInt64ToString(value, s + startPos);
+ // if (withSpace)
+ {
+ startPos--;
+ size++;
+ }
+ unsigned len = (unsigned)strlen(s + startPos);
+ if (size > len)
+ {
+ startPos -= (size - len);
+ if (startPos < 0)
+ startPos = 0;
+ }
+ f.Print(s + startPos);
+}
+
+static const unsigned kFieldSize_Name = 12;
+static const unsigned kFieldSize_SmallName = 4;
+static const unsigned kFieldSize_Speed = 9;
+static const unsigned kFieldSize_Usage = 5;
+static const unsigned kFieldSize_RU = 6;
+static const unsigned kFieldSize_Rating = 6;
+static const unsigned kFieldSize_EU = 5;
+static const unsigned kFieldSize_Effec = 5;
+
+static const unsigned kFieldSize_TotalSize = 4 + kFieldSize_Speed + kFieldSize_Usage + kFieldSize_RU + kFieldSize_Rating;
+static const unsigned kFieldSize_EUAndEffec = 2 + kFieldSize_EU + kFieldSize_Effec;
+
+
+static void PrintRating(IBenchPrintCallback &f, UInt64 rating, unsigned size)
+{
+ PrintNumber(f, (rating + 500000) / 1000000, size);
+}
+
+
+static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, unsigned size)
+{
+ PrintNumber(f, (val * 100 + divider / 2) / divider, size);
+}
+
+static void PrintChars(IBenchPrintCallback &f, char c, unsigned size)
+{
+ char s[256];
+ memset(s, (Byte)c, size);
+ s[size] = 0;
+ f.Print(s);
+}
+
+static void PrintSpaces(IBenchPrintCallback &f, unsigned size)
+{
+ PrintChars(f, ' ', size);
+}
+
+static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating, bool showFreq, UInt64 cpuFreq)
+{
+ PrintNumber(f, (usage + 5000) / 10000, kFieldSize_Usage);
+ PrintRating(f, rpu, kFieldSize_RU);
+ PrintRating(f, rating, kFieldSize_Rating);
+ if (showFreq)
+ {
+ if (cpuFreq == 0)
+ PrintSpaces(f, kFieldSize_EUAndEffec);
+ else
+ {
+ UInt64 ddd = cpuFreq * usage / 100;
+ if (ddd == 0)
+ ddd = 1;
+ PrintPercents(f, (rating * 10000), ddd, kFieldSize_EU);
+ PrintPercents(f, rating, cpuFreq, kFieldSize_Effec);
+ }
+ }
+}
+
+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)
+ {
+ if (speed != 0)
+ PrintNumber(*f, speed / 1024, kFieldSize_Speed);
+ else
+ PrintSpaces(*f, 1 + kFieldSize_Speed);
+ }
+ UInt64 usage = info.GetUsage();
+ UInt64 rpu = info.GetRatingPerUsage(rating);
+ if (f)
+ {
+ PrintResults(*f, usage, rpu, rating, showFreq, cpuFreq);
+ }
+
+ if (res)
+ {
+ // 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 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 PrintHex(AString &s, UInt64 v)
+{
+ char temp[32];
+ ConvertUInt64ToHex(v, temp);
+ s += temp;
+}
+
+AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti)
+{
+ AString s;
+ // s.Add_UInt32(ti.numProcessThreads);
+ if (ti.processAffinityMask != ti.systemAffinityMask)
+ {
+ // if (ti.numProcessThreads != ti.numSysThreads)
+ {
+ s += " / ";
+ s.Add_UInt32(ti.GetNumSystemThreads());
+ }
+ s += " : ";
+ PrintHex(s, ti.processAffinityMask);
+ s += " / ";
+ PrintHex(s, ti.systemAffinityMask);
+ }
+ return s;
+}
+
+
+extern bool g_LargePagesMode;
+
+
+static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString,
+ bool size_Defined, UInt64 size, const char *threadsString, UInt32 numThreads)
+{
+ f.Print("RAM ");
+ f.Print(sizeString);
+ if (size_Defined)
+ PrintNumber(f, (size >> 20), 6);
+ else
+ f.Print(" ?");
+ f.Print(" MB");
+ if (g_LargePagesMode)
+ f.Print(" LP");
+ f.Print(", # ");
+ f.Print(threadsString);
+ PrintNumber(f, numThreads, 3);
+}
+
+
+
+struct CBenchCallbackToPrint: public IBenchCallback
+{
+ CBenchProps BenchProps;
+ CTotalBenchRes EncodeRes;
+ CTotalBenchRes DecodeRes;
+ IBenchPrintCallback *_file;
+ UInt32 DictSize;
+
+ bool Use2Columns;
+ unsigned NameFieldSize;
+
+ bool ShowFreq;
+ UInt64 CpuFreq;
+
+ 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);
+ void NewLine();
+
+ HRESULT SetFreq(bool showFreq, UInt64 cpuFreq);
+ HRESULT SetEncodeResult(const CBenchInfo &info, bool final);
+ HRESULT SetDecodeResult(const CBenchInfo &info, bool final);
+};
+
+HRESULT CBenchCallbackToPrint::SetFreq(bool showFreq, UInt64 cpuFreq)
+{
+ ShowFreq = showFreq;
+ CpuFreq = cpuFreq;
+ return S_OK;
+}
+
+HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool final)
+{
+ RINOK(_file->CheckBreak());
+ if (final)
+ {
+ UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations);
+ PrintResults(_file, info,
+ EncodeWeight, rating,
+ ShowFreq, CpuFreq, &EncodeRes);
+ if (!Use2Columns)
+ _file->NewLine();
+ }
+ return S_OK;
+}
+
+static const char * const kSep = " | ";
+
+HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool final)
+{
+ RINOK(_file->CheckBreak());
+ if (final)
+ {
+ UInt64 rating = BenchProps.GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);
+ if (Use2Columns)
+ _file->Print(kSep);
+ else
+ PrintSpaces(*_file, NameFieldSize);
+ CBenchInfo info2 = info;
+ info2.UnpackSize *= info2.NumIterations;
+ info2.PackSize *= info2.NumIterations;
+ info2.NumIterations = 1;
+ PrintResults(_file, info2,
+ DecodeWeight, rating,
+ ShowFreq, CpuFreq, &DecodeRes);
+ }
+ return S_OK;
+}
+
+void CBenchCallbackToPrint::Print(const char *s)
+{
+ _file->Print(s);
+}
+
+void CBenchCallbackToPrint::NewLine()
+{
+ _file->NewLine();
+}
+
+void PrintLeft(IBenchPrintCallback &f, const char *s, unsigned size)
+{
+ f.Print(s);
+ int numSpaces = size - MyStringLen(s);
+ if (numSpaces > 0)
+ PrintSpaces(f, numSpaces);
+}
+
+void PrintRight(IBenchPrintCallback &f, const char *s, unsigned size)
+{
+ int numSpaces = size - MyStringLen(s);
+ if (numSpaces > 0)
+ PrintSpaces(f, numSpaces);
+ f.Print(s);
+}
+
+static HRESULT TotalBench(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ UInt64 complexInCommands,
+ UInt32 numThreads,
+ bool forceUnpackSize,
+ size_t unpackSize,
+ const Byte *fileData,
+ IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback)
+{
+ for (unsigned i = 0; i < ARRAY_SIZE(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;
+ callback->BenchProps.EncComplex = bench.EncComplex;
+
+ COneMethodInfo method;
+ NCOM::CPropVariant propVariant;
+ propVariant = bench.Name;
+ RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant));
+
+ size_t 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,
+ false, numThreads, method,
+ unpackSize2, fileData,
+ bench.DictBits,
+ printCallback, callback, &callback->BenchProps);
+
+ if (res == E_NOTIMPL)
+ {
+ // callback->Print(" ---");
+ // we need additional empty line as line for decompression results
+ if (!callback->Use2Columns)
+ callback->NewLine();
+ }
+ else
+ {
+ RINOK(res);
+ }
+
+ callback->NewLine();
+ }
+ return S_OK;
+}
+
+
+static HRESULT FreqBench(
+ UInt64 complexInCommands,
+ UInt32 numThreads,
+ IBenchPrintCallback *_file,
+ bool showFreq,
+ UInt64 specifiedFreq,
+ UInt64 &cpuFreq,
+ UInt32 &res)
+{
+ res = 0;
+ cpuFreq = 0;
+
+ UInt32 bufferSize = 1 << 20;
+ UInt32 complexity = kNumFreqCommands;
+ if (numThreads == 0)
+ numThreads = 1;
+
+ #ifdef _7ZIP_ST
+ numThreads = 1;
+ #endif
+
+ UInt32 bsize = (bufferSize == 0 ? 1 : bufferSize);
+ UInt64 numIterations = complexInCommands / complexity / bsize;
+ if (numIterations == 0)
+ numIterations = 1;
+
+ CBenchInfoCalc progressInfoSpec;
+
+ #ifndef _7ZIP_ST
+ CFreqThreads threads;
+ if (numThreads > 1)
+ {
+ threads.Items = new CFreqInfo[numThreads];
+ UInt32 i;
+ for (i = 0; i < numThreads; i++)
+ {
+ CFreqInfo &info = threads.Items[i];
+ info.Callback = _file;
+ info.CallbackRes = S_OK;
+ info.NumIterations = numIterations;
+ info.Size = bufferSize;
+ }
+ progressInfoSpec.SetStartTime();
+ for (i = 0; i < numThreads; i++)
+ {
+ CFreqInfo &info = threads.Items[i];
+ RINOK(info.Thread.Create(FreqThreadFunction, &info));
+ threads.NumThreads++;
+ }
+ threads.WaitAll();
+ for (i = 0; i < numThreads; i++)
+ {
+ RINOK(threads.Items[i].CallbackRes);
+ }
+ }
+ else
+ #endif
+ {
+ progressInfoSpec.SetStartTime();
+ UInt32 sum = g_BenchCpuFreqTemp;
+ for (UInt64 k = numIterations; k > 0; k--)
+ {
+ RINOK(_file->CheckBreak());
+ sum = CountCpuFreq(sum, bufferSize, g_BenchCpuFreqTemp);
+ }
+ res += sum;
+ }
+
+ CBenchInfo info;
+ progressInfoSpec.SetFinishTime(info);
+
+ info.UnpackSize = 0;
+ info.PackSize = 0;
+ info.NumIterations = 1;
+
+ if (_file)
+ {
+ {
+ UInt64 numCommands = (UInt64)numIterations * bufferSize * numThreads * complexity;
+ UInt64 rating = info.GetSpeed(numCommands);
+ cpuFreq = rating / numThreads;
+ PrintResults(_file, info,
+ 0, // weight
+ rating,
+ showFreq, showFreq ? (specifiedFreq != 0 ? specifiedFreq : cpuFreq) : 0, NULL);
+ }
+ RINOK(_file->CheckBreak());
+ }
+
+ return S_OK;
+}
+
+
+
+static HRESULT CrcBench(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ UInt64 complexInCommands,
+ UInt32 numThreads, UInt32 bufferSize,
+ UInt64 &speed,
+ UInt32 complexity, unsigned benchWeight,
+ const UInt32 *checkSum,
+ const COneMethodInfo &method,
+ IBenchPrintCallback *_file,
+ CTotalBenchRes *encodeRes,
+ bool showFreq, UInt64 cpuFreq)
+{
+ if (numThreads == 0)
+ numThreads = 1;
+
+ #ifdef _7ZIP_ST
+ numThreads = 1;
+ #endif
+
+ const AString &methodName = method.MethodName;
+ // methodName.RemoveChar(L'-');
+ CMethodId hashID;
+ if (!FindHashMethod(
+ EXTERNAL_CODECS_LOC_VARS
+ methodName, hashID))
+ return E_NOTIMPL;
+
+ CBenchBuffer buffer;
+ size_t totalSize = (size_t)bufferSize * numThreads;
+ if (totalSize / numThreads != bufferSize)
+ return E_OUTOFMEMORY;
+ if (!buffer.Alloc(totalSize))
+ return E_OUTOFMEMORY;
+
+ Byte *buf = buffer.Buffer;
+ CBaseRandomGenerator RG;
+ UInt32 bsize = (bufferSize == 0 ? 1 : bufferSize);
+ UInt64 numIterations = complexInCommands * 256 / complexity / bsize;
+ if (numIterations == 0)
+ numIterations = 1;
+
+ CBenchInfoCalc progressInfoSpec;
+
+ #ifndef _7ZIP_ST
+ CCrcThreads threads;
+ if (numThreads > 1)
+ {
+ threads.Items = new CCrcInfo[numThreads];
+
+ UInt32 i;
+ for (i = 0; i < numThreads; i++)
+ {
+ CCrcInfo &info = threads.Items[i];
+ AString name;
+ RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, info.Hasher));
+ if (!info.Hasher)
+ return E_NOTIMPL;
+ CMyComPtr<ICompressSetCoderProperties> scp;
+ info.Hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
+ {
+ UInt64 reduceSize = 1;
+ RINOK(method.SetCoderProps(scp, &reduceSize));
+ }
+
+ Byte *data = buf + (size_t)bufferSize * i;
+ info.Callback = _file;
+ info.Data = data;
+ info.NumIterations = numIterations;
+ info.Size = bufferSize;
+ /* info.Crc = */ RandGenCrc(data, bufferSize, RG);
+ info.CheckSumDefined = false;
+ if (checkSum)
+ {
+ 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];
+ RINOK(info.Thread.Create(CrcThreadFunction, &info));
+ threads.NumThreads++;
+ }
+ threads.WaitAll();
+ for (i = 0; i < numThreads; i++)
+ {
+ RINOK(threads.Items[i].Res);
+ }
+ }
+ else
+ #endif
+ {
+ /* UInt32 crc = */ RandGenCrc(buf, bufferSize, RG);
+ progressInfoSpec.SetStartTime();
+ CMyComPtr<IHasher> hasher;
+ AString name;
+ RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher));
+ if (!hasher)
+ return E_NOTIMPL;
+ CMyComPtr<ICompressSetCoderProperties> scp;
+ hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
+ {
+ UInt64 reduceSize = 1;
+ RINOK(method.SetCoderProps(scp, &reduceSize));
+ }
+ RINOK(CrcBig(buf, bufferSize, numIterations, checkSum, hasher, _file));
+ }
+
+ CBenchInfo info;
+ progressInfoSpec.SetFinishTime(info);
+
+ UInt64 unpSize = numIterations * bufferSize;
+ UInt64 unpSizeThreads = unpSize * numThreads;
+ info.UnpackSize = unpSizeThreads;
+ info.PackSize = unpSizeThreads;
+ info.NumIterations = 1;
+
+ if (_file)
+ {
+ {
+ UInt64 numCommands = unpSizeThreads * complexity / 256;
+ UInt64 rating = info.GetSpeed(numCommands);
+ PrintResults(_file, info,
+ benchWeight, rating,
+ showFreq, cpuFreq, encodeRes);
+ }
+ RINOK(_file->CheckBreak());
+ }
+
+ speed = info.GetSpeed(unpSizeThreads);
+
+ return S_OK;
+}
+
+static HRESULT TotalBench_Hash(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ UInt64 complexInCommands,
+ UInt32 numThreads, UInt32 bufSize,
+ IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback,
+ CTotalBenchRes *encodeRes,
+ bool showFreq, UInt64 cpuFreq)
+{
+ for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++)
+ {
+ const CBenchHash &bench = g_Hash[i];
+ PrintLeft(*callback->_file, bench.Name, kFieldSize_Name);
+ // callback->BenchProps.DecComplexUnc = bench.DecComplexUnc;
+ // callback->BenchProps.DecComplexCompr = bench.DecComplexCompr;
+ // callback->BenchProps.EncComplex = bench.EncComplex;
+
+ COneMethodInfo method;
+ NCOM::CPropVariant propVariant;
+ propVariant = bench.Name;
+ RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant));
+
+ UInt64 speed;
+ HRESULT res = CrcBench(
+ EXTERNAL_CODECS_LOC_VARS
+ complexInCommands,
+ numThreads, bufSize,
+ speed,
+ bench.Complex, bench.Weight,
+ &bench.CheckSum, method,
+ printCallback, encodeRes, showFreq, cpuFreq);
+ if (res == E_NOTIMPL)
+ {
+ // callback->Print(" ---");
+ }
+ else
+ {
+ RINOK(res);
+ }
+ callback->NewLine();
+ }
+ return S_OK;
+}
+
+struct CTempValues
+{
+ UInt64 *Values;
+ CTempValues(UInt32 num) { Values = new UInt64[num]; }
+ ~CTempValues() { delete []Values; }
+};
+
+static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
+{
+ const wchar_t *end;
+ UInt64 result = ConvertStringToUInt64(s, &end);
+ if (*end != 0 || s.IsEmpty())
+ prop = s;
+ else if (result <= (UInt32)0xFFFFFFFF)
+ prop = (UInt32)result;
+ else
+ prop = result;
+}
+
+static UInt32 GetNumThreadsNext(unsigned i, UInt32 numThreads)
+{
+ if (i < 2)
+ return i + 1;
+ i -= 1;
+ UInt32 num = (UInt32)(2 + (i & 1)) << (i >> 1);
+ return (num <= numThreads) ? num : numThreads;
+}
+
+static bool AreSameMethodNames(const char *fullName, const char *shortName)
+{
+ return StringsAreEqualNoCase_Ascii(fullName, shortName);
+}
+
+
+#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 d[4] = { 0 };
+ MyCPUID(0x80000002 + i, &d[0], &d[1], &d[2], &d[3]);
+ for (int j = 0; j < 4; j++)
+ PrintCpuChars(s, d[j]);
+ }
+ }
+
+ s.Add_Space_if_NotEmpty();
+ {
+ char temp[32];
+ ConvertUInt32ToHex(c.ver, temp);
+ s += '(';
+ s += temp;
+ s += ')';
+ }
+}
+
+#endif
+
+
+
+static const char * const k_PROCESSOR_ARCHITECTURE[] =
+{
+ "x86" // "INTEL"
+ , "MIPS"
+ , "ALPHA"
+ , "PPC"
+ , "SHX"
+ , "ARM"
+ , "IA64"
+ , "ALPHA64"
+ , "MSIL"
+ , "x64" // "AMD64"
+ , "IA32_ON_WIN64"
+ , "NEUTRAL"
+ , "ARM64"
+ , "ARM32_ON_WIN64"
+};
+
+#define MY__PROCESSOR_ARCHITECTURE_INTEL 0
+#define MY__PROCESSOR_ARCHITECTURE_AMD64 9
+
+
+#define MY__PROCESSOR_INTEL_PENTIUM 586
+#define MY__PROCESSOR_AMD_X8664 8664
+
+/*
+static const CUInt32PCharPair k_PROCESSOR[] =
+{
+ { 2200, "IA64" },
+ { 8664, "x64" }
+};
+
+#define PROCESSOR_INTEL_386 386
+#define PROCESSOR_INTEL_486 486
+#define PROCESSOR_INTEL_PENTIUM 586
+#define PROCESSOR_INTEL_860 860
+#define PROCESSOR_INTEL_IA64 2200
+#define PROCESSOR_AMD_X8664 8664
+#define PROCESSOR_MIPS_R2000 2000
+#define PROCESSOR_MIPS_R3000 3000
+#define PROCESSOR_MIPS_R4000 4000
+#define PROCESSOR_ALPHA_21064 21064
+#define PROCESSOR_PPC_601 601
+#define PROCESSOR_PPC_603 603
+#define PROCESSOR_PPC_604 604
+#define PROCESSOR_PPC_620 620
+#define PROCESSOR_HITACHI_SH3 10003
+#define PROCESSOR_HITACHI_SH3E 10004
+#define PROCESSOR_HITACHI_SH4 10005
+#define PROCESSOR_MOTOROLA_821 821
+#define PROCESSOR_SHx_SH3 103
+#define PROCESSOR_SHx_SH4 104
+#define PROCESSOR_STRONGARM 2577 // 0xA11
+#define PROCESSOR_ARM720 1824 // 0x720
+#define PROCESSOR_ARM820 2080 // 0x820
+#define PROCESSOR_ARM920 2336 // 0x920
+#define PROCESSOR_ARM_7TDMI 70001
+#define PROCESSOR_OPTIL 18767 // 0x494f
+*/
+
+#ifdef _WIN32
+
+static const char * const k_PF[] =
+{
+ "FP_ERRATA"
+ , "FP_EMU"
+ , "CMPXCHG"
+ , "MMX"
+ , "PPC_MOVEMEM_64BIT"
+ , "ALPHA_BYTE"
+ , "SSE"
+ , "3DNOW"
+ , "RDTSC"
+ , "PAE"
+ , "SSE2"
+ , "SSE_DAZ"
+ , "NX"
+ , "SSE3"
+ , "CMPXCHG16B"
+ , "CMP8XCHG16"
+ , "CHANNELS"
+ , "XSAVE"
+ , "ARM_VFP_32"
+ , "ARM_NEON"
+ , "L2AT"
+ , "VIRT_FIRMWARE"
+ , "RDWRFSGSBASE"
+ , "FASTFAIL"
+ , "ARM_DIVIDE"
+ , "ARM_64BIT_LOADSTORE_ATOMIC"
+ , "ARM_EXTERNAL_CACHE"
+ , "ARM_FMAC"
+ , "RDRAND"
+ , "ARM_V8"
+ , "ARM_V8_CRYPTO"
+ , "ARM_V8_CRC32"
+ , "RDTSCP"
+};
+
+#endif
+
+
+static void PrintSize(AString &s, UInt64 v)
+{
+ char c = 0;
+ if ((v & 0x3FF) == 0) { v >>= 10; c = 'K';
+ if ((v & 0x3FF) == 0) { v >>= 10; c = 'M';
+ if ((v & 0x3FF) == 0) { v >>= 10; c = 'G';
+ if ((v & 0x3FF) == 0) { v >>= 10; c = 'T';
+ }}}}
+ else
+ {
+ PrintHex(s, v);
+ return;
+ }
+ char temp[32];
+ ConvertUInt64ToString(v, temp);
+ s += temp;
+ if (c)
+ s += c;
+}
+
+
+static void PrintPage(AString &s, UInt32 v)
+{
+ if ((v & 0x3FF) == 0)
+ {
+ s.Add_UInt32(v >> 10);
+ s += "K";
+ }
+ else
+ s.Add_UInt32(v >> 10);
+}
+
+static AString TypeToString2(const char * const table[], unsigned num, UInt32 value)
+{
+ char sz[16];
+ const char *p = NULL;
+ if (value < num)
+ p = table[value];
+ if (!p)
+ {
+ ConvertUInt32ToString(value, sz);
+ p = sz;
+ }
+ return (AString)p;
+}
+
+#ifdef _WIN32
+
+static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si)
+{
+ s += TypeToString2(k_PROCESSOR_ARCHITECTURE, ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture);
+
+ if (!( si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == MY__PROCESSOR_INTEL_PENTIUM
+ || si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == MY__PROCESSOR_AMD_X8664))
+ {
+ s += " ";
+ // s += TypePairToString(k_PROCESSOR, ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType);
+ s.Add_UInt32(si.dwProcessorType);
+ }
+ s += " ";
+ PrintHex(s, si.wProcessorLevel);
+ s += ".";
+ PrintHex(s, si.wProcessorRevision);
+ if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors))
+ if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8)
+ {
+ s += " act:";
+ PrintHex(s, si.dwActiveProcessorMask);
+ }
+ s += " cpus:";
+ s.Add_UInt32(si.dwNumberOfProcessors);
+ if (si.dwPageSize != 1 << 12)
+ {
+ s += " page:";
+ PrintPage(s, si.dwPageSize);
+ }
+ if (si.dwAllocationGranularity != 1 << 16)
+ {
+ s += " gran:";
+ PrintPage(s, si.dwAllocationGranularity);
+ }
+ s += " ";
+
+ DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress;
+ UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1;
+ const UInt32 kReserveSize = ((UInt32)1 << 16);
+ if (minAdd != kReserveSize)
+ {
+ PrintSize(s, minAdd);
+ s += "-";
+ }
+ else
+ {
+ if ((maxSize & (kReserveSize - 1)) == 0)
+ maxSize += kReserveSize;
+ }
+ PrintSize(s, maxSize);
+}
+
+#ifndef _WIN64
+typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
+#endif
+
+#endif
+
+void GetSysInfo(AString &s1, AString &s2)
+{
+ s1.Empty();
+ s2.Empty();
+
+ #ifdef _WIN32
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ {
+ SysInfo_To_String(s1, si);
+ // s += " : ";
+ }
+
+ #if !defined(_WIN64) && !defined(UNDER_CE)
+ Func_GetNativeSystemInfo fn_GetNativeSystemInfo = (Func_GetNativeSystemInfo)GetProcAddress(
+ GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo");
+ if (fn_GetNativeSystemInfo)
+ {
+ SYSTEM_INFO si2;
+ fn_GetNativeSystemInfo(&si2);
+ // if (memcmp(&si, &si2, sizeof(si)) != 0)
+ {
+ // s += " - ";
+ SysInfo_To_String(s2, si2);
+ }
+ }
+ #endif
+ #endif
+}
+
+
+void GetCpuName(AString &s)
+{
+ s.Empty();
+
+ #ifdef MY_CPU_X86_OR_AMD64
+ {
+ Cx86cpuid cpuid;
+ if (x86cpuid_CheckAndRead(&cpuid))
+ {
+ AString s2;
+ x86cpuid_to_String(cpuid, s2);
+ s += s2;
+ }
+ else
+ {
+ #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
+
+ if (g_LargePagesMode)
+ s += " (LP)";
+}
+
+
+void GetCpuFeatures(AString &s)
+{
+ s.Empty();
+
+ #ifdef _WIN32
+ const unsigned kNumFeatures_Extra = 32; // we check also for unknown features
+ const unsigned kNumFeatures = ARRAY_SIZE(k_PF) + kNumFeatures_Extra;
+ for (unsigned i = 0; i < kNumFeatures; i++)
+ {
+ if (IsProcessorFeaturePresent(i))
+ {
+ s.Add_Space_if_NotEmpty();
+ s += TypeToString2(k_PF, ARRAY_SIZE(k_PF), i);
+ }
+ }
+ #endif
+}
+
+
+#ifdef _WIN32
+#ifndef UNDER_CE
+
+typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
+
+static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi)
+{
+ HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
+ if (!ntdll)
+ return FALSE;
+ Func_RtlGetVersion func = (Func_RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion");
+ if (!func)
+ return FALSE;
+ func(vi);
+ return TRUE;
+}
+
+#endif
+#endif
+
+
+HRESULT Bench(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ IBenchPrintCallback *printCallback,
+ IBenchCallback *benchCallback,
+ // IBenchFreqCallback *freqCallback,
+ const CObjectVector<CProperty> &props,
+ UInt32 numIterations,
+ bool multiDict)
+{
+ if (!CrcInternalTest())
+ return S_FALSE;
+
+ UInt32 numCPUs = 1;
+ UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29;
+
+ NSystem::CProcessAffinity threadsInfo;
+ threadsInfo.InitST();
+
+ #ifndef _7ZIP_ST
+
+ if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0)
+ numCPUs = threadsInfo.GetNumProcessThreads();
+ else
+ numCPUs = NSystem::GetNumberOfProcessors();
+
+ #endif
+
+ bool ramSize_Defined = NSystem::GetRamSize(ramSize);
+
+ UInt32 numThreadsSpecified = numCPUs;
+
+ UInt32 testTime = kComplexInSeconds;
+
+ UInt64 specifiedFreq = 0;
+
+ bool multiThreadTests = false;
+
+ COneMethodInfo method;
+
+ CBenchBuffer fileDataBuffer;
+
+ {
+ unsigned i;
+ for (i = 0; i < props.Size(); i++)
+ {
+ const CProperty &property = props[i];
+ UString name (property.Name);
+ name.MakeLower_Ascii();
+
+ if (name.IsEqualTo("file"))
+ {
+ if (property.Value.IsEmpty())
+ return E_INVALIDARG;
+
+ #ifdef USE_WIN_FILE
+
+ NFile::NIO::CInFile file;
+ if (!file.Open(us2fs(property.Value)))
+ return E_INVALIDARG;
+ UInt64 len;
+ if (!file.GetLength(len))
+ return E_FAIL;
+ if (len >= ((UInt32)1 << 31) || len == 0)
+ return E_INVALIDARG;
+ if (!fileDataBuffer.Alloc((size_t)len))
+ return E_OUTOFMEMORY;
+ UInt32 processedSize;
+ file.Read(fileDataBuffer.Buffer, (UInt32)len, processedSize);
+ if (processedSize != len)
+ return E_FAIL;
+ if (printCallback)
+ {
+ printCallback->Print("file size =");
+ PrintNumber(*printCallback, len, 0);
+ printCallback->NewLine();
+ }
+ continue;
+
+ #else
+
+ return E_NOTIMPL;
+
+ #endif
+ }
+
+ NCOM::CPropVariant propVariant;
+ if (!property.Value.IsEmpty())
+ ParseNumberString(property.Value, propVariant);
+
+ if (name.IsEqualTo("time"))
+ {
+ RINOK(ParsePropToUInt32(UString(), propVariant, testTime));
+ continue;
+ }
+
+ if (name.IsEqualTo("freq"))
+ {
+ UInt32 freq32 = 0;
+ RINOK(ParsePropToUInt32(UString(), propVariant, freq32));
+ if (freq32 == 0)
+ return E_INVALIDARG;
+ specifiedFreq = (UInt64)freq32 * 1000000;
+
+ if (printCallback)
+ {
+ printCallback->Print("freq=");
+ PrintNumber(*printCallback, freq32, 0);
+ printCallback->NewLine();
+ }
+
+ continue;
+ }
+
+ if (name.IsPrefixedBy_Ascii_NoCase("mt"))
+ {
+ UString s = name.Ptr(2);
+ if (s.IsEqualTo("*")
+ || s.IsEmpty() && propVariant.vt == VT_BSTR && StringsAreEqual_Ascii(propVariant.bstrVal, "*"))
+ {
+ multiThreadTests = true;
+ continue;
+ }
+ #ifndef _7ZIP_ST
+ RINOK(ParseMtProp(s, propVariant, numCPUs, numThreadsSpecified));
+ #endif
+ continue;
+ }
+
+ RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant));
+ }
+ }
+
+ if (printCallback)
+ {
+ #ifdef _WIN32
+ #ifndef UNDER_CE
+ {
+ AString s;
+ // OSVERSIONINFO vi;
+ OSVERSIONINFOEXW vi;
+ vi.dwOSVersionInfoSize = sizeof(vi);
+ // if (::GetVersionEx(&vi))
+ if (My_RtlGetVersion(&vi))
+ {
+ s += "Windows";
+ if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
+ s.Add_UInt32(vi.dwPlatformId);
+ s += " "; s.Add_UInt32(vi.dwMajorVersion);
+ s += "."; s.Add_UInt32(vi.dwMinorVersion);
+ s += " "; s.Add_UInt32(vi.dwBuildNumber);
+ // s += " "; s += GetAnsiString(vi.szCSDVersion);
+ }
+ printCallback->Print(s);
+ printCallback->NewLine();
+ }
+ #endif
+ #endif
+
+ {
+ AString s1, s2;
+ GetSysInfo(s1, s2);
+ if (!s1.IsEmpty() || !s2.IsEmpty())
+ {
+ printCallback->Print(s1);
+ if (s1 != s2 && !s2.IsEmpty())
+ {
+ printCallback->Print(" - ");
+ printCallback->Print(s2);
+ }
+ printCallback->NewLine();
+ }
+ }
+ {
+ AString s;
+ GetCpuFeatures(s);
+ if (!s.IsEmpty())
+ {
+ printCallback->Print(s);
+ printCallback->NewLine();
+ }
+ }
+ {
+ AString s;
+ GetCpuName(s);
+ if (!s.IsEmpty())
+ {
+ printCallback->Print(s);
+ printCallback->NewLine();
+ }
+ }
+ }
+
+ if (printCallback)
+ {
+ printCallback->Print("CPU Freq:");
+ }
+
+ UInt64 complexInCommands = kComplexInCommands;
+
+ if (printCallback /* || freqCallback */)
+ {
+ UInt64 numMilCommands = 1 << 6;
+ if (specifiedFreq != 0)
+ {
+ while (numMilCommands > 1 && specifiedFreq < (numMilCommands * 1000000))
+ numMilCommands >>= 1;
+ }
+
+ 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);
+ const UInt64 realDelta = ::GetTimeCount() - start;
+ start = realDelta;
+ if (start == 0)
+ start = 1;
+ UInt64 freq = GetFreq();
+ // mips is constant in some compilers
+ const UInt64 mipsVal = numMilCommands * freq / start;
+ if (printCallback)
+ {
+ if (realDelta == 0)
+ {
+ printCallback->Print(" -");
+ }
+ else
+ {
+ // PrintNumber(*printCallback, start, 0);
+ PrintNumber(*printCallback, mipsVal, 5 + ((sum == 0xF1541213) ? 1 : 0));
+ }
+ }
+ /*
+ if (freqCallback)
+ freqCallback->AddCpuFreq(mipsVal);
+ */
+
+ if (jj >= 3)
+ {
+ SetComplexCommands(testTime, false, mipsVal * 1000000, complexInCommands);
+ if (jj >= 8 || start >= freq)
+ break;
+ // break; // change it
+ numMilCommands <<= 1;
+ }
+ }
+ }
+
+ if (printCallback)
+ {
+ printCallback->NewLine();
+ printCallback->NewLine();
+ PrintRequirements(*printCallback, "size: ", ramSize_Defined, ramSize, "CPU hardware threads:", numCPUs);
+ printCallback->Print(GetProcessThreadsInfo(threadsInfo));
+ printCallback->NewLine();
+ }
+
+ if (numThreadsSpecified < 1 || numThreadsSpecified > kNumThreadsMax)
+ return E_INVALIDARG;
+
+ UInt32 dict;
+ bool dictIsDefined = method.Get_DicSize(dict);
+
+ if (method.MethodName.IsEmpty())
+ method.MethodName = "LZMA";
+
+ if (benchCallback)
+ {
+ CBenchProps benchProps;
+ benchProps.SetLzmaCompexity();
+ UInt32 dictSize = method.Get_Lzma_DicSize();
+ UInt32 uncompressedDataSize = kAdditionalSize + dictSize;
+ return MethodBench(
+ EXTERNAL_CODECS_LOC_VARS
+ complexInCommands,
+ true, numThreadsSpecified,
+ method,
+ uncompressedDataSize, fileDataBuffer.Buffer,
+ kOldLzmaDictBits, printCallback, benchCallback, &benchProps);
+ }
+
+ 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)
+ return S_FALSE;
+ IBenchPrintCallback &f = *printCallback;
+ if (!dictIsDefined)
+ dict = (1 << 24);
+
+
+ // methhodName.RemoveChar(L'-');
+ UInt32 complexity = 10000;
+ const UInt32 *checkSum = NULL;
+ {
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(g_Hash); i++)
+ {
+ const CBenchHash &h = g_Hash[i];
+ AString benchMethod (h.Name);
+ AString benchProps;
+ int propPos = benchMethod.Find(':');
+ if (propPos >= 0)
+ {
+ benchProps = benchMethod.Ptr(propPos + 1);
+ benchMethod.DeleteFrom(propPos);
+ }
+
+ if (AreSameMethodNames(benchMethod, methodName))
+ {
+ if (benchProps.IsEmpty()
+ || benchMethod.IsEqualTo_Ascii_NoCase("crc32") && benchProps == "8" && method.PropsString.IsEmpty()
+ || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps))
+ {
+ complexity = h.Complex;
+ checkSum = &h.CheckSum;
+ if (method.PropsString.IsEqualTo_Ascii_NoCase(benchProps))
+ break;
+ }
+ }
+ }
+ if (i == ARRAY_SIZE(g_Hash))
+ return E_NOTIMPL;
+ }
+
+ f.NewLine();
+ f.Print("Size");
+ const unsigned kFieldSize_CrcSpeed = 6;
+ unsigned numThreadsTests = 0;
+ for (;;)
+ {
+ UInt32 t = GetNumThreadsNext(numThreadsTests, numThreadsSpecified);
+ PrintNumber(f, t, kFieldSize_CrcSpeed);
+ numThreadsTests++;
+ if (t >= numThreadsSpecified)
+ break;
+ }
+ f.NewLine();
+ f.NewLine();
+ CTempValues speedTotals(numThreadsTests);
+ {
+ for (unsigned ti = 0; ti < numThreadsTests; ti++)
+ speedTotals.Values[ti] = 0;
+ }
+
+ UInt64 numSteps = 0;
+ for (UInt32 i = 0; i < numIterations; i++)
+ {
+ for (unsigned pow = 10; pow < 32; pow++)
+ {
+ UInt32 bufSize = (UInt32)1 << pow;
+ if (bufSize > dict)
+ break;
+ char s[16];
+ ConvertUInt32ToString(pow, s);
+ unsigned pos = MyStringLen(s);
+ s[pos++] = ':';
+ s[pos++] = ' ';
+ s[pos] = 0;
+ f.Print(s);
+
+ for (unsigned ti = 0; ti < numThreadsTests; ti++)
+ {
+ RINOK(f.CheckBreak());
+ UInt32 t = GetNumThreadsNext(ti, numThreadsSpecified);
+ UInt64 speed = 0;
+ RINOK(CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands,
+ 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;
+ }
+ f.NewLine();
+ numSteps++;
+ }
+ }
+ if (numSteps != 0)
+ {
+ f.NewLine();
+ f.Print("Avg:");
+ for (unsigned ti = 0; ti < numThreadsTests; ti++)
+ {
+ PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), kFieldSize_CrcSpeed);
+ }
+ f.NewLine();
+ }
+ return S_OK;
+ }
+
+ bool use2Columns = false;
+
+ bool totalBenchMode = (method.MethodName.IsEqualTo_Ascii_NoCase("*"));
+ bool onlyHashBench = false;
+ if (method.MethodName.IsEqualTo_Ascii_NoCase("hash"))
+ {
+ onlyHashBench = true;
+ totalBenchMode = true;
+ }
+
+ // ---------- 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)
+ {
+ const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25);
+ unsigned dicSizeLog = dicSizeLog_Main;
+
+ #ifdef UNDER_CE
+ dicSizeLog = (UInt64)1 << 20;
+ #endif
+
+ if (ramSize_Defined)
+ for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
+ if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog), totalBenchMode) + (8 << 20) <= ramSize)
+ break;
+
+ dict = (UInt32)1 << dicSizeLog;
+
+ if (totalBenchMode && dicSizeLog != dicSizeLog_Main)
+ {
+ f.Print("Dictionary reduced to: ");
+ PrintNumber(f, dicSizeLog, 1);
+ f.NewLine();
+ }
+ }
+
+ PrintRequirements(f, "usage:", true, GetBenchMemoryUsage(numThreads, dict, totalBenchMode), "Benchmark threads: ", numThreads);
+ f.NewLine();
+
+ f.NewLine();
+
+ if (totalBenchMode)
+ {
+ callback.NameFieldSize = kFieldSize_Name;
+ use2Columns = false;
+ }
+ else
+ {
+ callback.NameFieldSize = kFieldSize_SmallName;
+ use2Columns = true;
+ }
+ callback.Use2Columns = use2Columns;
+
+ bool showFreq = false;
+ UInt64 cpuFreq = 0;
+
+ if (totalBenchMode)
+ {
+ showFreq = true;
+ }
+
+ unsigned fileldSize = kFieldSize_TotalSize;
+ if (showFreq)
+ fileldSize += kFieldSize_EUAndEffec;
+
+ if (use2Columns)
+ {
+ PrintSpaces(f, callback.NameFieldSize);
+ PrintRight(f, "Compressing", fileldSize);
+ f.Print(kSep);
+ PrintRight(f, "Decompressing", fileldSize);
+ }
+ f.NewLine();
+ PrintLeft(f, totalBenchMode ? "Method" : "Dict", callback.NameFieldSize);
+
+ int j;
+
+ for (j = 0; j < 2; j++)
+ {
+ PrintRight(f, "Speed", kFieldSize_Speed + 1);
+ PrintRight(f, "Usage", kFieldSize_Usage + 1);
+ PrintRight(f, "R/U", kFieldSize_RU + 1);
+ PrintRight(f, "Rating", kFieldSize_Rating + 1);
+ if (showFreq)
+ {
+ PrintRight(f, "E/U", kFieldSize_EU + 1);
+ PrintRight(f, "Effec", kFieldSize_Effec + 1);
+ }
+ if (!use2Columns)
+ break;
+ if (j == 0)
+ f.Print(kSep);
+ }
+
+ f.NewLine();
+ PrintSpaces(f, callback.NameFieldSize);
+
+ for (j = 0; j < 2; j++)
+ {
+ PrintRight(f, "KiB/s", kFieldSize_Speed + 1);
+ PrintRight(f, "%", kFieldSize_Usage + 1);
+ PrintRight(f, "MIPS", kFieldSize_RU + 1);
+ PrintRight(f, "MIPS", kFieldSize_Rating + 1);
+ if (showFreq)
+ {
+ PrintRight(f, "%", kFieldSize_EU + 1);
+ PrintRight(f, "%", kFieldSize_Effec + 1);
+ }
+ if (!use2Columns)
+ break;
+ if (j == 0)
+ f.Print(kSep);
+ }
+
+ f.NewLine();
+ f.NewLine();
+
+ if (specifiedFreq != 0)
+ cpuFreq = specifiedFreq;
+
+
+ if (totalBenchMode)
+ {
+ for (UInt32 i = 0; i < numIterations; i++)
+ {
+ if (i != 0)
+ printCallback->NewLine();
+ HRESULT res;
+
+ const unsigned kNumCpuTests = 3;
+ for (unsigned freqTest = 0; freqTest < kNumCpuTests; freqTest++)
+ {
+ PrintLeft(f, "CPU", kFieldSize_Name);
+ UInt32 resVal;
+ RINOK(FreqBench(complexInCommands, numThreads, printCallback,
+ (freqTest == kNumCpuTests - 1 || specifiedFreq != 0), // showFreq
+ specifiedFreq,
+ cpuFreq, resVal));
+ callback.NewLine();
+
+ if (specifiedFreq != 0)
+ cpuFreq = specifiedFreq;
+
+ if (freqTest == kNumCpuTests - 1)
+ SetComplexCommands(testTime, specifiedFreq != 0, cpuFreq, complexInCommands);
+ }
+ callback.NewLine();
+
+ callback.SetFreq(true, cpuFreq);
+
+ if (!onlyHashBench)
+ {
+ res = TotalBench(EXTERNAL_CODECS_LOC_VARS
+ complexInCommands, numThreads,
+ dictIsDefined || fileDataBuffer.Buffer, // forceUnpackSize
+ fileDataBuffer.Buffer ? fileDataBuffer.BufferSize : dict,
+ fileDataBuffer.Buffer,
+ printCallback, &callback);
+ RINOK(res);
+ }
+
+ res = TotalBench_Hash(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads,
+ 1 << kNumHashDictBits, printCallback, &callback, &callback.EncodeRes, true, cpuFreq);
+ RINOK(res);
+
+ callback.NewLine();
+ {
+ PrintLeft(f, "CPU", kFieldSize_Name);
+ UInt32 resVal;
+ UInt64 cpuFreqLastTemp = cpuFreq;
+ RINOK(FreqBench(complexInCommands, numThreads, printCallback,
+ specifiedFreq != 0, // showFreq
+ specifiedFreq,
+ cpuFreqLastTemp, resVal));
+ callback.NewLine();
+ }
+ }
+ }
+ else
+ {
+ bool needSetComplexity = true;
+ if (!methodName.IsEqualTo_Ascii_NoCase("LZMA"))
+ {
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(g_Bench); i++)
+ {
+ const CBenchMethod &h = g_Bench[i];
+ AString benchMethod (h.Name);
+ AString benchProps;
+ int propPos = benchMethod.Find(':');
+ if (propPos >= 0)
+ {
+ benchProps = benchMethod.Ptr(propPos + 1);
+ benchMethod.DeleteFrom(propPos);
+ }
+
+ if (AreSameMethodNames(benchMethod, methodName))
+ {
+ if (benchProps.IsEmpty()
+ || benchProps == "x5" && method.PropsString.IsEmpty()
+ || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps))
+ {
+ callback.BenchProps.EncComplex = h.EncComplex;
+ callback.BenchProps.DecComplexCompr = h.DecComplexCompr;
+ callback.BenchProps.DecComplexUnc = h.DecComplexUnc;;
+ needSetComplexity = false;
+ break;
+ }
+ }
+ }
+ if (i == ARRAY_SIZE(g_Bench))
+ return E_NOTIMPL;
+ }
+ if (needSetComplexity)
+ callback.BenchProps.SetLzmaCompexity();
+
+ for (unsigned i = 0; i < numIterations; i++)
+ {
+ const unsigned kStartDicLog = 22;
+ unsigned pow = (dict < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;
+ if (!multiDict)
+ pow = 31;
+ while (((UInt32)1 << pow) > dict && pow > 0)
+ pow--;
+ for (; ((UInt32)1 << pow) <= dict; pow++)
+ {
+ char s[16];
+ ConvertUInt32ToString(pow, s);
+ unsigned pos = MyStringLen(s);
+ s[pos++] = ':';
+ s[pos] = 0;
+ PrintLeft(f, s, kFieldSize_SmallName);
+ callback.DictSize = (UInt32)1 << pow;
+
+ COneMethodInfo method2 = method;
+
+ if (StringsAreEqualNoCase_Ascii(method2.MethodName, "LZMA"))
+ {
+ // We add dictionary size property.
+ // method2 can have two different dictionary size properties.
+ // And last property is main.
+ NCOM::CPropVariant propVariant = (UInt32)pow;
+ RINOK(method2.ParseMethodFromPROPVARIANT((UString)"d", propVariant));
+ }
+
+ size_t uncompressedDataSize;
+ if (fileDataBuffer.Buffer)
+ {
+ uncompressedDataSize = fileDataBuffer.BufferSize;
+ }
+ else
+ {
+ uncompressedDataSize = callback.DictSize;
+ if (uncompressedDataSize >= (1 << 18))
+ uncompressedDataSize += kAdditionalSize;
+ }
+
+ HRESULT res = MethodBench(
+ EXTERNAL_CODECS_LOC_VARS
+ complexInCommands,
+ true, numThreads,
+ method2,
+ uncompressedDataSize, fileDataBuffer.Buffer,
+ kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps);
+ f.NewLine();
+ RINOK(res);
+ if (!multiDict)
+ break;
+ }
+ }
+ }
+
+ PrintChars(f, '-', callback.NameFieldSize + fileldSize);
+
+ if (use2Columns)
+ {
+ f.Print(kSep);
+ PrintChars(f, '-', fileldSize);
+ }
+
+ f.NewLine();
+
+ if (use2Columns)
+ {
+ PrintLeft(f, "Avr:", callback.NameFieldSize);
+ PrintTotals(f, showFreq, cpuFreq, callback.EncodeRes);
+ f.Print(kSep);
+ 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/other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.h
new file mode 100644
index 0000000000..1990aab0d3
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.h
@@ -0,0 +1,72 @@
+// Bench.h
+
+#ifndef __7ZIP_BENCH_H
+#define __7ZIP_BENCH_H
+
+#include "../../../Windows/System.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../UI/Common/Property.h"
+
+struct CBenchInfo
+{
+ UInt64 GlobalTime;
+ UInt64 GlobalFreq;
+ UInt64 UserTime;
+ UInt64 UserFreq;
+ UInt64 UnpackSize;
+ UInt64 PackSize;
+ UInt64 NumIterations;
+
+ CBenchInfo(): NumIterations(0) {}
+ UInt64 GetUsage() const;
+ UInt64 GetRatingPerUsage(UInt64 rating) const;
+ UInt64 GetSpeed(UInt64 numCommands) const;
+};
+
+struct IBenchCallback
+{
+ virtual HRESULT SetFreq(bool showFreq, UInt64 cpuFreq) = 0;
+ virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0;
+ virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0;
+};
+
+UInt64 GetCompressRating(UInt32 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size);
+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations);
+
+const unsigned kBenchMinDicLogSize = 18;
+
+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary, bool totalBench = false);
+
+struct IBenchPrintCallback
+{
+ virtual void Print(const char *s) = 0;
+ virtual void NewLine() = 0;
+ virtual HRESULT CheckBreak() = 0;
+};
+
+/*
+struct IBenchFreqCallback
+{
+ virtual void AddCpuFreq(UInt64 freq) = 0;
+};
+*/
+
+HRESULT Bench(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ IBenchPrintCallback *printCallback,
+ IBenchCallback *benchCallback,
+ // IBenchFreqCallback *freqCallback,
+ const CObjectVector<CProperty> &props,
+ UInt32 numIterations,
+ bool multiDict
+ );
+
+AString GetProcessThreadsInfo(const NWindows::NSystem::CProcessAffinity &ti);
+
+void GetSysInfo(AString &s1, AString &s2);
+void GetCpuName(AString &s);
+void GetCpuFeatures(AString &s);
+
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.cpp
new file mode 100644
index 0000000000..0c13e9ebcf
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.cpp
@@ -0,0 +1,37 @@
+// DefaultName.cpp
+
+#include "StdAfx.h"
+
+#include "DefaultName.h"
+
+static UString GetDefaultName3(const UString &fileName,
+ const UString &extension, const UString &addSubExtension)
+{
+ const unsigned extLen = extension.Len();
+ const unsigned fileNameLen = fileName.Len();
+
+ if (fileNameLen > extLen + 1)
+ {
+ const unsigned dotPos = fileNameLen - (extLen + 1);
+ if (fileName[dotPos] == '.')
+ if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1)))
+ return fileName.Left(dotPos) + addSubExtension;
+ }
+
+ int dotPos = fileName.ReverseFind_Dot();
+ if (dotPos > 0)
+ return fileName.Left(dotPos) + addSubExtension;
+
+ if (addSubExtension.IsEmpty())
+ return fileName + L'~';
+ else
+ return fileName + addSubExtension;
+}
+
+UString GetDefaultName2(const UString &fileName,
+ const UString &extension, const UString &addSubExtension)
+{
+ UString name = GetDefaultName3(fileName, extension, addSubExtension);
+ name.TrimRight();
+ return name;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.h
new file mode 100644
index 0000000000..4484c3b5b4
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.h
@@ -0,0 +1,11 @@
+// DefaultName.h
+
+#ifndef __DEFAULT_NAME_H
+#define __DEFAULT_NAME_H
+
+#include "../../../Common/MyString.h"
+
+UString GetDefaultName2(const UString &fileName,
+ const UString &extension, const UString &addSubExtension);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/DirItem.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/DirItem.h
new file mode 100644
index 0000000000..47485bec3d
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/DirItem.h
@@ -0,0 +1,190 @@
+// DirItem.h
+
+#ifndef __DIR_ITEM_H
+#define __DIR_ITEM_H
+
+#include "../../../Common/MyString.h"
+
+#include "../../../Windows/FileFind.h"
+
+#include "../../Common/UniqBlocks.h"
+
+#include "../../Archive/IArchive.h"
+
+struct CDirItemsStat
+{
+ UInt64 NumDirs;
+ UInt64 NumFiles;
+ UInt64 NumAltStreams;
+ UInt64 FilesSize;
+ UInt64 AltStreamsSize;
+
+ UInt64 NumErrors;
+
+ // UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; }
+ UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; }
+ UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; }
+
+ bool IsEmpty() const { return
+ 0 == NumDirs
+ && 0 == NumFiles
+ && 0 == NumAltStreams
+ && 0 == FilesSize
+ && 0 == AltStreamsSize
+ && 0 == NumErrors; }
+
+ CDirItemsStat():
+ NumDirs(0),
+ NumFiles(0),
+ NumAltStreams(0),
+ FilesSize(0),
+ AltStreamsSize(0),
+ NumErrors(0)
+ {}
+};
+
+
+struct CDirItemsStat2: public CDirItemsStat
+{
+ UInt64 Anti_NumDirs;
+ UInt64 Anti_NumFiles;
+ UInt64 Anti_NumAltStreams;
+
+ // UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); }
+ UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); }
+
+ bool IsEmpty() const { return CDirItemsStat::IsEmpty()
+ && 0 == Anti_NumDirs
+ && 0 == Anti_NumFiles
+ && 0 == Anti_NumAltStreams; }
+
+ CDirItemsStat2():
+ Anti_NumDirs(0),
+ Anti_NumFiles(0),
+ Anti_NumAltStreams(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;
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+ UString Name;
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ // UString ShortName;
+ CByteBuffer ReparseData;
+ CByteBuffer ReparseData2; // fixed (reduced) absolute links
+
+ bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; }
+ #endif
+
+ UInt32 Attrib;
+ int PhyParent;
+ int LogParent;
+ int SecureIndex;
+
+ bool IsAltStream;
+
+ CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {}
+ bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
+};
+
+class CDirItems
+{
+ UStringVector Prefixes;
+ CIntVector PhyParents;
+ CIntVector LogParents;
+
+ UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;
+
+ HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);
+
+public:
+ CObjectVector<CDirItem> Items;
+
+ bool SymLinks;
+
+ bool ScanAltStreams;
+
+ CDirItemsStat Stat;
+
+ #ifndef UNDER_CE
+ HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,
+ const FString &phyPrefix);
+ #endif
+
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+
+ CUniqBlocks SecureBlocks;
+ CByteBuffer TempSecureBuf;
+ bool _saclEnabled;
+ bool ReadSecure;
+
+ HRESULT AddSecurityItem(const FString &path, int &secureIndex);
+
+ #endif
+
+ IDirItemsCallback *Callback;
+
+ CDirItems();
+
+ 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();
+
+ HRESULT EnumerateItems2(
+ const FString &phyPrefix,
+ const UString &logPrefix,
+ const FStringVector &filePaths,
+ FStringVector *requestedPaths);
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ void FillFixedReparse();
+ #endif
+
+ void ReserveDown();
+};
+
+struct CArcItem
+{
+ UInt64 Size;
+ FILETIME MTime;
+ UString Name;
+ bool IsDir;
+ bool IsAltStream;
+ bool SizeDefined;
+ bool MTimeDefined;
+ bool Censored;
+ UInt32 IndexInServer;
+ int TimeType;
+
+ CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.cpp
new file mode 100644
index 0000000000..032e2fffe1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -0,0 +1,1086 @@
+// EnumDirItems.cpp
+
+#include "StdAfx.h"
+
+#include <wchar.h>
+
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileIO.h"
+#include "../../../Windows/FileName.h"
+
+#if defined(_WIN32) && !defined(UNDER_CE)
+#define _USE_SECURITY_CODE
+#include "../../../Windows/SecurityUtils.h"
+#endif
+
+#include "EnumDirItems.h"
+#include "SortUtils.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+
+void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex,
+ const NFind::CFileInfo &fi)
+{
+ CDirItem di;
+ di.Size = fi.Size;
+ di.CTime = fi.CTime;
+ di.ATime = fi.ATime;
+ di.MTime = fi.MTime;
+ di.Attrib = fi.Attrib;
+ di.IsAltStream = fi.IsAltStream;
+ di.PhyParent = phyParent;
+ di.LogParent = logParent;
+ di.SecureIndex = secureIndex;
+ di.Name = fs2us(fi.Name);
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ // di.ShortName = fs2us(fi.ShortName);
+ #endif
+ 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();
+
+ 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];
+ p -= s.Len();
+ wmemcpy(p, (const wchar_t *)s, s.Len());
+ }
+
+ return path;
+}
+
+FString CDirItems::GetPhyPath(unsigned index) const
+{
+ const CDirItem &di = Items[index];
+ return us2fs(GetPrefixesPath(PhyParents, di.PhyParent, di.Name));
+}
+
+UString CDirItems::GetLogPath(unsigned index) const
+{
+ const CDirItem &di = Items[index];
+ return GetPrefixesPath(LogParents, di.LogParent, di.Name);
+}
+
+void CDirItems::ReserveDown()
+{
+ Prefixes.ReserveDown();
+ PhyParents.ReserveDown();
+ LogParents.ReserveDown();
+ Items.ReserveDown();
+}
+
+unsigned CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)
+{
+ PhyParents.Add(phyParent);
+ LogParents.Add(logParent);
+ return Prefixes.Add(prefix);
+}
+
+void CDirItems::DeleteLastPrefix()
+{
+ PhyParents.DeleteBack();
+ LogParents.DeleteBack();
+ Prefixes.DeleteBack();
+}
+
+bool InitLocalPrivileges();
+
+CDirItems::CDirItems():
+ SymLinks(false),
+ ScanAltStreams(false)
+ #ifdef _USE_SECURITY_CODE
+ , ReadSecure(false)
+ #endif
+ , Callback(NULL)
+{
+ #ifdef _USE_SECURITY_CODE
+ _saclEnabled = InitLocalPrivileges();
+ #endif
+}
+
+#ifdef _USE_SECURITY_CODE
+
+HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex)
+{
+ secureIndex = -1;
+
+ SECURITY_INFORMATION securInfo =
+ DACL_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ OWNER_SECURITY_INFORMATION;
+ if (_saclEnabled)
+ securInfo |= SACL_SECURITY_INFORMATION;
+
+ 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 S_OK;
+ if (secureSize > TempSecureBuf.Size())
+ errorCode = ERROR_INVALID_FUNCTION;
+ }
+ else
+ {
+ errorCode = GetLastError();
+ if (errorCode == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if (secureSize <= TempSecureBuf.Size())
+ errorCode = ERROR_INVALID_FUNCTION;
+ else
+ {
+ TempSecureBuf.Alloc(secureSize);
+ res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize);
+ if (res)
+ {
+ if (secureSize != TempSecureBuf.Size())
+ errorCode = ERROR_INVALID_FUNCTION;;
+ }
+ else
+ errorCode = GetLastError();
+ }
+ }
+ }
+
+ if (res)
+ {
+ secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize);
+ return S_OK;
+ }
+
+ if (errorCode == 0)
+ errorCode = ERROR_INVALID_FUNCTION;
+ return AddError(path, errorCode);
+}
+
+#endif
+
+HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix)
+{
+ RINOK(ScanProgress(phyPrefix));
+
+ NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(phyPrefix);
+ for (unsigned ttt = 0; ; ttt++)
+ {
+ NFind::CFileInfo fi;
+ bool found;
+ if (!enumerator.Next(fi, found))
+ {
+ return AddError(phyPrefix);
+ }
+ if (!found)
+ return S_OK;
+
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (ReadSecure)
+ {
+ RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex));
+ }
+ #endif
+
+ 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));
+ RINOK(EnumerateDir(parent, parent, phyPrefix + name2));
+ }
+ }
+}
+
+HRESULT CDirItems::EnumerateItems2(
+ const FString &phyPrefix,
+ const UString &logPrefix,
+ const FStringVector &filePaths,
+ FStringVector *requestedPaths)
+{
+ int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix));
+ int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix);
+
+ FOR_VECTOR (i, filePaths)
+ {
+ const FString &filePath = filePaths[i];
+ NFind::CFileInfo fi;
+ const FString phyPath = phyPrefix + filePath;
+ if (!fi.Find(phyPath))
+ {
+ RINOK(AddError(phyPath));
+ continue;
+ }
+ if (requestedPaths)
+ requestedPaths->Add(phyPath);
+
+ int delimiter = filePath.ReverseFind_PathSepar();
+ FString phyPrefixCur;
+ int phyParentCur = phyParent;
+ if (delimiter >= 0)
+ {
+ phyPrefixCur.SetFrom(filePath, delimiter + 1);
+ phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur));
+ }
+
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (ReadSecure)
+ {
+ RINOK(AddSecurityItem(phyPath, secureIndex));
+ }
+ #endif
+
+ AddDirFileInfo(phyParentCur, logParent, secureIndex, fi);
+
+ if (fi.IsDir())
+ {
+ const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;
+ unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2));
+ RINOK(EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2));
+ }
+ }
+
+ ReserveDown();
+ return S_OK;
+}
+
+
+
+
+
+
+static HRESULT EnumerateDirItems(
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &phyPrefix,
+ const UStringVector &addArchivePrefix,
+ CDirItems &dirItems,
+ bool enterToSubFolders);
+
+static HRESULT EnumerateDirItems_Spec(
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &curFolderName,
+ const FString &phyPrefix,
+ const UStringVector &addArchivePrefix,
+ CDirItems &dirItems,
+ 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);
+ if (numItems == dirItems.Items.Size())
+ dirItems.DeleteLastPrefix();
+ return res;
+}
+
+#ifndef UNDER_CE
+
+#ifdef _WIN32
+
+static HRESULT EnumerateAltStreams(
+ const NFind::CFileInfo &fi,
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &fullPath,
+ const UStringVector &addArchivePrefix, // prefix from curNode
+ bool addAllItems,
+ CDirItems &dirItems)
+{
+ NFind::CStreamEnumerator enumerator(fullPath);
+ for (;;)
+ {
+ NFind::CStreamInfo si;
+ bool found;
+ if (!enumerator.Next(si, found))
+ {
+ return dirItems.AddError(fullPath + FTEXT(":*")); // , (DWORD)E_FAIL
+ }
+ if (!found)
+ return S_OK;
+ if (si.IsMainStream())
+ continue;
+ UStringVector addArchivePrefixNew = addArchivePrefix;
+ UString reducedName = si.GetReducedName();
+ addArchivePrefixNew.Back() += reducedName;
+ if (curNode.CheckPathToRoot(false, addArchivePrefixNew, true))
+ continue;
+ if (!addAllItems)
+ if (!curNode.CheckPathToRoot(true, addArchivePrefixNew, true))
+ continue;
+
+ NFind::CFileInfo fi2 = fi;
+ fi2.Name += us2fs(reducedName);
+ fi2.Size = si.Size;
+ fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;
+ fi2.IsAltStream = true;
+ dirItems.AddDirFileInfo(phyParent, logParent, -1, fi2);
+ }
+}
+
+#endif
+
+HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,
+ const FString &phyPrefix)
+{
+ if (!SymLinks || !fi.HasReparsePoint())
+ return S_OK;
+ const FString path = phyPrefix + fi.Name;
+ CByteBuffer &buf = dirItem.ReparseData;
+ DWORD res = 0;
+ if (NIO::GetReparseData(path, buf))
+ {
+ CReparseAttr attr;
+ if (attr.Parse(buf, buf.Size(), res))
+ return S_OK;
+ // we ignore unknown reparse points
+ if (res != ERROR_INVALID_REPARSE_DATA)
+ res = 0;
+ }
+ else
+ {
+ res = ::GetLastError();
+ if (res == 0)
+ res = ERROR_INVALID_FUNCTION;
+ }
+
+ buf.Free();
+ if (res == 0)
+ return S_OK;
+ return AddError(path, res);
+}
+
+#endif
+
+static HRESULT EnumerateForItem(
+ NFind::CFileInfo &fi,
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &phyPrefix,
+ const UStringVector &addArchivePrefix, // prefix from curNode
+ CDirItems &dirItems,
+ bool enterToSubFolders)
+{
+ const UString name = fs2us(fi.Name);
+ bool enterToSubFolders2 = enterToSubFolders;
+ UStringVector addArchivePrefixNew = addArchivePrefix;
+ addArchivePrefixNew.Add(name);
+ {
+ UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
+ if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir()))
+ return S_OK;
+ }
+ int dirItemIndex = -1;
+
+ bool addAllSubStreams = false;
+
+ if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))
+ {
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (dirItems.ReadSecure)
+ {
+ RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex));
+ }
+ #endif
+
+ dirItemIndex = dirItems.Items.Size();
+ dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
+ if (fi.IsDir())
+ enterToSubFolders2 = true;
+
+ addAllSubStreams = true;
+ }
+
+ #ifndef UNDER_CE
+ if (dirItems.ScanAltStreams)
+ {
+ RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
+ phyPrefix + fi.Name,
+ addArchivePrefixNew,
+ addAllSubStreams,
+ dirItems));
+ }
+
+ if (dirItemIndex >= 0)
+ {
+ CDirItem &dirItem = dirItems.Items[dirItemIndex];
+ RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix));
+ if (dirItem.ReparseData.Size() != 0)
+ return S_OK;
+ }
+ #endif
+
+ if (!fi.IsDir())
+ return S_OK;
+
+ const NWildcard::CCensorNode *nextNode = 0;
+ if (addArchivePrefix.IsEmpty())
+ {
+ int index = curNode.FindSubNode(name);
+ if (index >= 0)
+ nextNode = &curNode.SubNodes[index];
+ }
+ if (!enterToSubFolders2 && nextNode == 0)
+ return S_OK;
+
+ addArchivePrefixNew = addArchivePrefix;
+ if (nextNode == 0)
+ {
+ nextNode = &curNode;
+ addArchivePrefixNew.Add(name);
+ }
+
+ return EnumerateDirItems_Spec(
+ *nextNode, phyParent, logParent, fi.Name, phyPrefix,
+ addArchivePrefixNew,
+ dirItems,
+ enterToSubFolders2);
+}
+
+
+static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode)
+{
+ FOR_VECTOR (i, curNode.IncludeItems)
+ {
+ const NWildcard::CItem &item = curNode.IncludeItems[i];
+ 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,
+ and wildcard mode is disabled, we can ignore wildcard in name */
+ /*
+ if (!item.WildcardParsing)
+ continue;
+ */
+ if (DoesNameContainWildcard(name))
+ return false;
+ }
+ return true;
+}
+
+
+#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)
+{
+ if (!enterToSubFolders)
+ if (curNode.NeedCheckSubDirs())
+ enterToSubFolders = true;
+
+ RINOK(dirItems.ScanProgress(phyPrefix));
+
+ // try direct_names case at first
+ if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
+ {
+ if (CanUseFsDirect(curNode))
+ {
+ // all names are direct (no wildcards)
+ // so we don't need file_system's dir enumerator
+ CRecordVector<bool> needEnterVector;
+ unsigned i;
+
+ for (i = 0; i < curNode.IncludeItems.Size(); i++)
+ {
+ const NWildcard::CItem &item = curNode.IncludeItems[i];
+ const UString &name = item.PathParts.Front();
+ 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 = CHAR_PATH_SEPARATOR;
+ }
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ else if (item.IsDriveItem())
+ {
+ needAltStreams = false;
+ fullPath.Add_PathSepar();
+ }
+ #endif
+ }
+ }
+
+ NFind::CFileInfo fi;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (IsVirtualFsFolder(phyPrefix, name))
+ {
+ fi.SetAsDir();
+ fi.Name = us2fs(name);
+ }
+ else
+ #endif
+ if (!fi.Find(fullPath))
+ {
+ RINOK(dirItems.AddError(fullPath));
+ continue;
+ }
+
+ bool isDir = fi.IsDir();
+ if (isDir && !item.ForDir || !isDir && !item.ForFile)
+ {
+ RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL));
+ continue;
+ }
+ {
+ UStringVector pathParts;
+ pathParts.Add(fs2us(fi.Name));
+ if (curNode.CheckPathToRoot(false, pathParts, !isDir))
+ continue;
+ }
+
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (needSecurity && dirItems.ReadSecure)
+ {
+ RINOK(dirItems.AddSecurityItem(fullPath, secureIndex));
+ }
+ #endif
+
+ dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
+
+ #ifndef UNDER_CE
+ {
+ CDirItem &dirItem = dirItems.Items.Back();
+ 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
+
+
+ #ifndef UNDER_CE
+ if (needAltStreams && dirItems.ScanAltStreams)
+ {
+ UStringVector pathParts;
+ pathParts.Add(fs2us(fi.Name));
+ RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
+ fullPath, pathParts,
+ true, /* addAllSubStreams */
+ dirItems));
+ }
+ #endif
+
+ if (!isDir)
+ continue;
+
+ UStringVector addArchivePrefixNew;
+ const NWildcard::CCensorNode *nextNode = 0;
+ int index = curNode.FindSubNode(name);
+ if (index >= 0)
+ {
+ for (int t = needEnterVector.Size(); t <= index; t++)
+ needEnterVector.Add(true);
+ needEnterVector[index] = false;
+ nextNode = &curNode.SubNodes[index];
+ }
+ else
+ {
+ nextNode = &curNode;
+ addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support
+ }
+
+ RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,
+ addArchivePrefixNew, dirItems, true));
+ }
+
+ for (i = 0; i < curNode.SubNodes.Size(); i++)
+ {
+ if (i < needEnterVector.Size())
+ if (!needEnterVector[i])
+ continue;
+ const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
+ FString fullPath = phyPrefix + us2fs(nextNode.Name);
+ NFind::CFileInfo fi;
+
+ if (phyPrefix.IsEmpty())
+ {
+ {
+ if (nextNode.Name.IsEmpty())
+ fullPath = CHAR_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 = us2fs(nextNode.Name);
+ }
+ else
+ {
+ if (!fi.Find(fullPath))
+ {
+ if (!nextNode.AreThereIncludeItems())
+ continue;
+ RINOK(dirItems.AddError(fullPath));
+ continue;
+ }
+
+ if (!fi.IsDir())
+ {
+ RINOK(dirItems.AddError(fullPath, (DWORD)E_FAIL));
+ continue;
+ }
+ }
+
+ RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,
+ UStringVector(), dirItems, false));
+ }
+
+ return S_OK;
+ }
+ }
+
+ #ifdef _WIN32
+ #ifndef UNDER_CE
+
+ // scan drives, if wildcard is "*:\"
+
+ if (phyPrefix.IsEmpty() && curNode.IncludeItems.Size() > 0)
+ {
+ unsigned i;
+ for (i = 0; i < curNode.IncludeItems.Size(); i++)
+ {
+ const NWildcard::CItem &item = curNode.IncludeItems[i];
+ if (item.PathParts.Size() < 1)
+ break;
+ const UString &name = item.PathParts.Front();
+ if (name.Len() != 2 || name[1] != ':')
+ break;
+ if (item.PathParts.Size() == 1)
+ if (item.ForFile || !item.ForDir)
+ break;
+ if (NWildcard::IsDriveColonName(name))
+ continue;
+ if (name[0] != '*' && name[0] != '?')
+ break;
+ }
+ if (i == curNode.IncludeItems.Size())
+ {
+ FStringVector driveStrings;
+ NFind::MyGetLogicalDriveStrings(driveStrings);
+ for (i = 0; i < driveStrings.Size(); i++)
+ {
+ FString driveName = driveStrings[i];
+ if (driveName.Len() < 3 || driveName.Back() != '\\')
+ return E_FAIL;
+ driveName.DeleteBack();
+ NFind::CFileInfo fi;
+ fi.SetAsDir();
+ fi.Name = driveName;
+
+ RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,
+ addArchivePrefix, dirItems, enterToSubFolders));
+ }
+ return S_OK;
+ }
+ }
+
+ #endif
+ #endif
+
+ NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(phyPrefix);
+
+ for (unsigned ttt = 0; ; ttt++)
+ {
+ NFind::CFileInfo fi;
+ bool found;
+ if (!enumerator.Next(fi, found))
+ {
+ RINOK(dirItems.AddError(phyPrefix));
+ break;
+ }
+ if (!found)
+ break;
+
+ if (dirItems.Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask)
+ {
+ RINOK(dirItems.ScanProgress(phyPrefix));
+ }
+
+ RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,
+ addArchivePrefix, dirItems, enterToSubFolders));
+ }
+
+ return S_OK;
+}
+
+HRESULT EnumerateItems(
+ const NWildcard::CCensor &censor,
+ const NWildcard::ECensorPathMode pathMode,
+ const UString &addPathPrefix,
+ CDirItems &dirItems)
+{
+ FOR_VECTOR (i, censor.Pairs)
+ {
+ const NWildcard::CPair &pair = censor.Pairs[i];
+ int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix);
+ int logParent = -1;
+
+ if (pathMode == NWildcard::k_AbsPath)
+ logParent = phyParent;
+ else
+ {
+ if (!addPathPrefix.IsEmpty())
+ logParent = dirItems.AddPrefix(-1, -1, addPathPrefix);
+ }
+
+ RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(),
+ dirItems,
+ false // enterToSubFolders
+ ));
+ }
+ dirItems.ReserveDown();
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ dirItems.FillFixedReparse();
+ #endif
+
+ return S_OK;
+}
+
+#if defined(_WIN32) && !defined(UNDER_CE)
+
+void CDirItems::FillFixedReparse()
+{
+ /* imagex/WIM reduces absolute pathes in links (raparse data),
+ if we archive non root folder. We do same thing here */
+
+ if (!SymLinks)
+ return;
+
+ FOR_VECTOR(i, Items)
+ {
+ CDirItem &item = Items[i];
+ if (item.ReparseData.Size() == 0)
+ continue;
+
+ CReparseAttr attr;
+ DWORD errorCode = 0;
+ if (!attr.Parse(item.ReparseData, item.ReparseData.Size(), errorCode))
+ continue;
+ if (attr.IsRelative())
+ continue;
+
+ const UString &link = attr.GetPath();
+ if (!IsDrivePath(link))
+ continue;
+ // maybe we need to support networks paths also ?
+
+ FString fullPathF;
+ if (!NDir::MyGetFullPathName(GetPhyPath(i), fullPathF))
+ continue;
+ UString fullPath = fs2us(fullPathF);
+ const UString logPath = GetLogPath(i);
+ if (logPath.Len() >= fullPath.Len())
+ continue;
+ if (CompareFileNames(logPath, fullPath.RightPtr(logPath.Len())) != 0)
+ continue;
+
+ const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len());
+ if (!IsPathSepar(prefix.Back()))
+ continue;
+
+ unsigned rootPrefixSize = GetRootPrefixSize(prefix);
+ if (rootPrefixSize == 0)
+ continue;
+ if (rootPrefixSize == prefix.Len())
+ continue; // simple case: paths are from root
+
+ if (link.Len() <= prefix.Len())
+ continue;
+
+ if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0)
+ continue;
+
+ UString newLink = prefix.Left(rootPrefixSize);
+ newLink += link.Ptr(prefix.Len());
+
+ CByteBuffer data;
+ if (!FillLinkData(data, newLink, attr.IsSymLink()))
+ continue;
+ item.ReparseData2 = data;
+ }
+}
+
+#endif
+
+
+
+static const char * const kCannotFindArchive = "Cannot find archive";
+
+HRESULT EnumerateDirItemsAndSort(
+ NWildcard::CCensor &censor,
+ NWildcard::ECensorPathMode censorPathMode,
+ const UString &addPathPrefix,
+ UStringVector &sortedPaths,
+ UStringVector &sortedFullPaths,
+ CDirItemsStat &st,
+ IDirItemsCallback *callback)
+{
+ FStringVector paths;
+
+ {
+ CDirItems dirItems;
+ dirItems.Callback = callback;
+ {
+ HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems);
+ st = dirItems.Stat;
+ RINOK(res);
+ }
+
+ FOR_VECTOR (i, dirItems.Items)
+ {
+ const CDirItem &dirItem = dirItems.Items[i];
+ if (!dirItem.IsDir())
+ paths.Add(dirItems.GetPhyPath(i));
+ }
+ }
+
+ if (paths.Size() == 0)
+ {
+ // return S_OK;
+ throw CMessagePathException(kCannotFindArchive);
+ }
+
+ UStringVector fullPaths;
+
+ unsigned i;
+
+ for (i = 0; i < paths.Size(); i++)
+ {
+ FString 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(fs2us(paths[index]));
+ sortedFullPaths.AddInReserved(fullPaths[index]);
+ if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0)
+ throw CMessagePathException("Duplicate archive path:", sortedFullPaths[i]);
+ }
+
+ return S_OK;
+}
+
+
+
+
+#ifdef _WIN32
+
+// This code converts all short file names to long file names.
+
+static void ConvertToLongName(const UString &prefix, UString &name)
+{
+ if (name.IsEmpty() || DoesNameContainWildcard(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);
+}
+
+static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)
+{
+ FOR_VECTOR (i, items)
+ {
+ NWildcard::CItem &item = items[i];
+ if (item.Recursive || item.PathParts.Size() != 1)
+ continue;
+ if (prefix.IsEmpty() && item.IsDriveItem())
+ continue;
+ ConvertToLongName(prefix, item.PathParts.Front());
+ }
+}
+
+static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node)
+{
+ ConvertToLongNames(prefix, node.IncludeItems);
+ ConvertToLongNames(prefix, node.ExcludeItems);
+ unsigned i;
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ {
+ UString &name = node.SubNodes[i].Name;
+ if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name))
+ continue;
+ ConvertToLongName(prefix, name);
+ }
+ // mix folders with same name
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ {
+ NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];
+ for (unsigned j = i + 1; j < node.SubNodes.Size();)
+ {
+ const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
+ if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name))
+ {
+ nextNode1.IncludeItems += nextNode2.IncludeItems;
+ nextNode1.ExcludeItems += nextNode2.ExcludeItems;
+ node.SubNodes.Delete(j);
+ }
+ else
+ j++;
+ }
+ }
+ for (i = 0; i < node.SubNodes.Size(); i++)
+ {
+ NWildcard::CCensorNode &nextNode = node.SubNodes[i];
+ ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode);
+ }
+}
+
+void ConvertToLongNames(NWildcard::CCensor &censor)
+{
+ FOR_VECTOR (i, censor.Pairs)
+ {
+ NWildcard::CPair &pair = censor.Pairs[i];
+ ConvertToLongNames(pair.Prefix, pair.Head);
+ }
+}
+
+#endif
+
+
+CMessagePathException::CMessagePathException(const char *a, const wchar_t *u)
+{
+ (*this) += a;
+ if (u)
+ {
+ Add_LF();
+ (*this) += u;
+ }
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.h
new file mode 100644
index 0000000000..6220500538
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.h
@@ -0,0 +1,41 @@
+// EnumDirItems.h
+
+#ifndef __ENUM_DIR_ITEMS_H
+#define __ENUM_DIR_ITEMS_H
+
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileFind.h"
+
+#include "DirItem.h"
+
+void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
+ const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems);
+
+HRESULT EnumerateItems(
+ const NWildcard::CCensor &censor,
+ NWildcard::ECensorPathMode pathMode,
+ const UString &addPathPrefix,
+ CDirItems &dirItems);
+
+
+struct CMessagePathException: public UString
+{
+ CMessagePathException(const char *a, const wchar_t *u = NULL);
+};
+
+
+HRESULT EnumerateDirItemsAndSort(
+ NWildcard::CCensor &censor,
+ NWildcard::ECensorPathMode pathMode,
+ const UString &addPathPrefix,
+ UStringVector &sortedPaths,
+ UStringVector &sortedFullPaths,
+ CDirItemsStat &st,
+ IDirItemsCallback *callback);
+
+#ifdef _WIN32
+void ConvertToLongNames(NWildcard::CCensor &censor);
+#endif
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExitCode.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExitCode.h
new file mode 100644
index 0000000000..d03ec6d797
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExitCode.h
@@ -0,0 +1,27 @@
+// ExitCode.h
+
+#ifndef __EXIT_CODE_H
+#define __EXIT_CODE_H
+
+namespace NExitCode {
+
+enum EEnum {
+
+ kSuccess = 0, // Successful operation
+ kWarning = 1, // Non fatal error(s) occurred
+ kFatalError = 2, // A fatal error occurred
+ // kCRCError = 3, // A CRC error occurred when unpacking
+ // kLockedArchive = 4, // Attempt to modify an archive previously locked
+ // kWriteError = 5, // Write to disk error
+ // kOpenError = 6, // Open file error
+ kUserError = 7, // Command line option error
+ kMemoryError = 8, // Not enough memory for operation
+ // kCreateFileError = 9, // Create file error
+
+ kUserBreak = 255 // User stopped the process
+
+};
+
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.cpp
new file mode 100644
index 0000000000..2cb2c9b924
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.cpp
@@ -0,0 +1,482 @@
+// Extract.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/Sort.h"
+
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
+
+#include "../Common/ExtractingFilePath.h"
+
+#include "Extract.h"
+#include "SetProperties.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+static HRESULT DecompressArchive(
+ CCodecs *codecs,
+ const CArchiveLink &arcLink,
+ UInt64 packSize,
+ const NWildcard::CCensorNode &wildcardCensor,
+ const CExtractOptions &options,
+ bool calcCrc,
+ IExtractCallbackUI *callback,
+ CArchiveExtractCallback *ecs,
+ UString &errorMessage,
+ UInt64 &stdInProcessed)
+{
+ const CArc &arc = arcLink.Arcs.Back();
+ stdInProcessed = 0;
+ IInArchive *archive = arc.Archive;
+ CRecordVector<UInt32> realIndices;
+
+ UStringVector removePathParts;
+
+ FString outDir = options.OutputDir;
+ UString replaceName = arc.DefaultName;
+
+ if (arcLink.Arcs.Size() > 1)
+ {
+ // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1".
+ // So it extracts different archives to one folder.
+ // We will use top level archive name
+ const CArc &arc0 = arcLink.Arcs[0];
+ if (StringsAreEqualNoCase_Ascii(codecs->Formats[arc0.FormatIndex].Name, "pe"))
+ replaceName = arc0.DefaultName;
+ }
+
+ outDir.Replace(FString("*"), us2fs(Get_Correct_FsFile_Name(replaceName)));
+
+ bool elimIsPossible = false;
+ UString elimPrefix; // only pure name without dir delimiter
+ FString outDirReduced = outDir;
+
+ if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths)
+ {
+ UString dirPrefix;
+ SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);
+ if (!elimPrefix.IsEmpty())
+ {
+ if (IsPathSepar(elimPrefix.Back()))
+ elimPrefix.DeleteBack();
+ if (!elimPrefix.IsEmpty())
+ {
+ outDirReduced = us2fs(dirPrefix);
+ elimIsPossible = true;
+ }
+ }
+ }
+
+ bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
+
+ if (!options.StdInMode)
+ {
+ UInt32 numItems;
+ RINOK(archive->GetNumberOfItems(&numItems));
+
+ CReadArcItem item;
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ 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
+ }
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if (!options.NtOptions.AltStreams.Val && item.IsAltStream)
+ continue;
+ #endif
+
+ if (elimIsPossible)
+ {
+ const UString &s =
+ #ifdef SUPPORT_ALT_STREAMS
+ item.MainPath;
+ #else
+ item.Path;
+ #endif
+ if (!IsPath1PrefixedByPath2(s, elimPrefix))
+ elimIsPossible = false;
+ else
+ {
+ wchar_t c = s[elimPrefix.Len()];
+ if (c == 0)
+ {
+ if (!item.MainIsDir)
+ elimIsPossible = false;
+ }
+ else if (!IsPathSepar(c))
+ elimIsPossible = false;
+ }
+ }
+
+ if (!allFilesAreAllowed)
+ {
+ if (!CensorNode_CheckPath(wildcardCensor, item))
+ continue;
+ }
+
+ realIndices.Add(i);
+ }
+
+ if (realIndices.Size() == 0)
+ {
+ callback->ThereAreNoFiles();
+ return callback->ExtractResult(S_OK);
+ }
+ }
+
+ if (elimIsPossible)
+ {
+ removePathParts.Add(elimPrefix);
+ // outDir = outDirReduced;
+ }
+
+ #ifdef _WIN32
+ // GetCorrectFullFsPath doesn't like "..".
+ // outDir.TrimRight();
+ // outDir = GetCorrectFullFsPath(outDir);
+ #endif
+
+ if (outDir.IsEmpty())
+ outDir = "." STRING_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 = "Can not create output directory: ";
+ errorMessage += fs2us(outDir);
+ return res;
+ }
+
+ ecs->Init(
+ options.NtOptions,
+ options.StdInMode ? &wildcardCensor : NULL,
+ &arc,
+ callback,
+ options.StdOutMode, options.TestMode,
+ outDir,
+ removePathParts, false,
+ packSize);
+
+
+ #ifdef SUPPORT_LINKS
+
+ if (!options.StdInMode &&
+ !options.TestMode &&
+ options.NtOptions.HardLinks.Val)
+ {
+ RINOK(ecs->PrepareHardLinks(&realIndices));
+ }
+
+ #endif
+
+
+ HRESULT result;
+ Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;
+
+ CArchiveExtractCallback_Closer ecsCloser(ecs);
+
+ if (options.StdInMode)
+ {
+ result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
+ NCOM::CPropVariant prop;
+ if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
+ ConvertPropVariantToUInt64(prop, stdInProcessed);
+ }
+ else
+ result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);
+
+ HRESULT res2 = ecsCloser.Close();
+ if (result == S_OK)
+ result = res2;
+
+ return callback->ExtractResult(result);
+}
+
+/* v9.31: BUG was fixed:
+ Sorted list for file paths was sorted with case insensitive compare function.
+ But FindInSorted function did binary search via case sensitive compare function */
+
+int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name)
+{
+ unsigned left = 0, right = fileName.Size();
+ while (left != right)
+ {
+ unsigned mid = (left + right) / 2;
+ const UString &midValue = fileName[mid];
+ int compare = CompareFileNames(name, midValue);
+ if (compare == 0)
+ return mid;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ return -1;
+}
+
+HRESULT Extract(
+ CCodecs *codecs,
+ const CObjectVector<COpenType> &types,
+ const CIntVector &excludedFormats,
+ UStringVector &arcPaths, UStringVector &arcPathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ const CExtractOptions &options,
+ IOpenCallbackUI *openCallback,
+ IExtractCallbackUI *extractCallback,
+ #ifndef _SFX
+ IHashCalc *hash,
+ #endif
+ UString &errorMessage,
+ CDecompressStat &st)
+{
+ 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;
+ fi.Size = 0;
+ if (!options.StdInMode)
+ {
+ const FString &arcPath = us2fs(arcPaths[i]);
+ if (!fi.Find(arcPath))
+ throw "there is no such archive";
+ if (fi.IsDir())
+ throw "can't decompress folder";
+ }
+ arcSizes.Add(fi.Size);
+ totalPackSize += fi.Size;
+ }
+
+ CBoolArr skipArcs(numArcs);
+ for (i = 0; i < numArcs; i++)
+ skipArcs[i] = false;
+
+ CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> ec(ecs);
+ bool multi = (numArcs > 1);
+ ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode,
+ false // keepEmptyDirParts
+ );
+ #ifndef _SFX
+ ecs->SetHashMethods(hash);
+ #endif
+
+ if (multi)
+ {
+ RINOK(extractCallback->SetTotal(totalPackSize));
+ }
+
+ UInt64 totalPackProcessed = 0;
+ bool thereAreNotOpenArcs = false;
+
+ for (i = 0; i < numArcs; i++)
+ {
+ if (skipArcs[i])
+ continue;
+
+ const UString &arcPath = arcPaths[i];
+ NFind::CFileInfo fi;
+ if (options.StdInMode)
+ {
+ fi.Size = 0;
+ fi.Attrib = 0;
+ }
+ else
+ {
+ if (!fi.Find(us2fs(arcPath)) || fi.IsDir())
+ throw "there is no such archive";
+ }
+
+ /*
+ #ifndef _NO_CRYPTO
+ openCallback->Open_Clear_PasswordWasAsked_Flag();
+ #endif
+ */
+
+ RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode));
+ CArchiveLink arcLink;
+
+ CObjectVector<COpenType> types2 = types;
+ /*
+ #ifndef _SFX
+ if (types.IsEmpty())
+ {
+ int pos = arcPath.ReverseFind(L'.');
+ if (pos >= 0)
+ {
+ UString s = arcPath.Ptr(pos + 1);
+ int index = codecs->FindFormatForExtension(s);
+ if (index >= 0 && s == L"001")
+ {
+ s = arcPath.Left(pos);
+ pos = s.ReverseFind(L'.');
+ if (pos >= 0)
+ {
+ int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1));
+ if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0
+ {
+ types2.Add(index2);
+ types2.Add(index);
+ }
+ }
+ }
+ }
+ }
+ #endif
+ */
+
+ COpenOptions op;
+ #ifndef _SFX
+ op.props = &options.Properties;
+ #endif
+ op.codecs = codecs;
+ op.types = &types2;
+ op.excludedFormats = &excludedFormats;
+ op.stdInMode = options.StdInMode;
+ op.stream = NULL;
+ op.filePath = arcPath;
+
+ HRESULT result = arcLink.Open_Strict(op, openCallback);
+
+ if (result == E_ABORT)
+ return result;
+
+ // arcLink.Set_ErrorsText();
+ RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result));
+
+ if (result != S_OK)
+ {
+ thereAreNotOpenArcs = true;
+ if (!options.StdInMode)
+ {
+ NFind::CFileInfo fi2;
+ if (fi2.Find(us2fs(arcPath)))
+ if (!fi2.IsDir())
+ totalPackProcessed += fi2.Size;
+ }
+ continue;
+ }
+
+ if (!options.StdInMode)
+ {
+ // numVolumes += arcLink.VolumePaths.Size();
+ // arcLink.VolumesSize;
+
+ // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes);
+ // numArcs = arcPaths.Size();
+ if (arcLink.VolumePaths.Size() != 0)
+ {
+ Int64 correctionSize = arcLink.VolumesSize;
+ FOR_VECTOR (v, arcLink.VolumePaths)
+ {
+ int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);
+ if (index >= 0)
+ {
+ if ((unsigned)index > i)
+ {
+ skipArcs[(unsigned)index] = true;
+ correctionSize -= arcSizes[(unsigned)index];
+ }
+ }
+ }
+ if (correctionSize != 0)
+ {
+ Int64 newPackSize = (Int64)totalPackSize + correctionSize;
+ if (newPackSize < 0)
+ newPackSize = 0;
+ totalPackSize = newPackSize;
+ RINOK(extractCallback->SetTotal(totalPackSize));
+ }
+ }
+ }
+
+ /*
+ // Now openCallback and extractCallback use same object. So we don't need to send password.
+
+ #ifndef _NO_CRYPTO
+ bool passwordIsDefined;
+ UString password;
+ RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password));
+ if (passwordIsDefined)
+ {
+ RINOK(extractCallback->SetPassword(password));
+ }
+ #endif
+ */
+
+ CArc &arc = arcLink.Arcs.Back();
+ arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
+ arc.MTime = fi.MTime;
+
+ UInt64 packProcessed;
+ bool calcCrc =
+ #ifndef _SFX
+ (hash != NULL);
+ #else
+ false;
+ #endif
+
+ RINOK(DecompressArchive(
+ codecs,
+ arcLink,
+ fi.Size + arcLink.VolumesSize,
+ wildcardCensor,
+ options,
+ calcCrc,
+ extractCallback, ecs, errorMessage, packProcessed));
+
+ if (!options.StdInMode)
+ packProcessed = fi.Size + arcLink.VolumesSize;
+ totalPackProcessed += packProcessed;
+ ecs->LocalProgressSpec->InSize += packProcessed;
+ ecs->LocalProgressSpec->OutSize = ecs->UnpackSize;
+ if (!errorMessage.IsEmpty())
+ return E_FAIL;
+ }
+
+ if (multi || thereAreNotOpenArcs)
+ {
+ RINOK(extractCallback->SetTotal(totalPackSize));
+ RINOK(extractCallback->SetCompleted(&totalPackProcessed));
+ }
+
+ 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/other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.h
new file mode 100644
index 0000000000..9c806bee7e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.h
@@ -0,0 +1,94 @@
+// Extract.h
+
+#ifndef __EXTRACT_H
+#define __EXTRACT_H
+
+#include "../../../Windows/FileFind.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "ArchiveExtractCallback.h"
+#include "ArchiveOpenCallback.h"
+#include "ExtractMode.h"
+#include "Property.h"
+
+#include "../Common/LoadCodecs.h"
+
+struct CExtractOptionsBase
+{
+ CBoolPair ElimDup;
+
+ bool PathMode_Force;
+ bool OverwriteMode_Force;
+ NExtract::NPathMode::EEnum PathMode;
+ NExtract::NOverwriteMode::EEnum OverwriteMode;
+
+ FString OutputDir;
+ CExtractNtOptions NtOptions;
+
+ CExtractOptionsBase():
+ PathMode_Force(false),
+ OverwriteMode_Force(false),
+ PathMode(NExtract::NPathMode::kFullPaths),
+ OverwriteMode(NExtract::NOverwriteMode::kAsk)
+ {}
+};
+
+struct CExtractOptions: public CExtractOptionsBase
+{
+ bool StdInMode;
+ bool StdOutMode;
+ bool YesToAll;
+ bool TestMode;
+
+ // bool ShowDialog;
+ // bool PasswordEnabled;
+ // UString Password;
+ #ifndef _SFX
+ CObjectVector<CProperty> Properties;
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ CCodecs *Codecs;
+ #endif
+
+ CExtractOptions():
+ TestMode(false),
+ StdInMode(false),
+ StdOutMode(false),
+ YesToAll(false)
+ {}
+};
+
+struct CDecompressStat
+{
+ UInt64 NumArchives;
+ UInt64 UnpackSize;
+ UInt64 AltStreams_UnpackSize;
+ UInt64 PackSize;
+ UInt64 NumFolders;
+ UInt64 NumFiles;
+ UInt64 NumAltStreams;
+
+ void Clear()
+ {
+ NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0;
+ }
+};
+
+HRESULT Extract(
+ CCodecs *codecs,
+ const CObjectVector<COpenType> &types,
+ const CIntVector &excludedFormats,
+ UStringVector &archivePaths, UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ const CExtractOptions &options,
+ IOpenCallbackUI *openCallback,
+ IExtractCallbackUI *extractCallback,
+ #ifndef _SFX
+ IHashCalc *hash,
+ #endif
+ UString &errorMessage,
+ CDecompressStat &st);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractMode.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractMode.h
new file mode 100644
index 0000000000..c28b7ccfa7
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractMode.h
@@ -0,0 +1,34 @@
+// ExtractMode.h
+
+#ifndef __EXTRACT_MODE_H
+#define __EXTRACT_MODE_H
+
+namespace NExtract {
+
+namespace NPathMode
+{
+ enum EEnum
+ {
+ kFullPaths,
+ kCurPaths,
+ kNoPaths,
+ kAbsPaths,
+ kNoPathsAlt // alt streams must be extracted without name of base file
+ };
+}
+
+namespace NOverwriteMode
+{
+ enum EEnum
+ {
+ kAsk,
+ kOverwrite,
+ kSkip,
+ kRename,
+ kRenameExisting
+ };
+}
+
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.cpp
new file mode 100644
index 0000000000..13665de579
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -0,0 +1,280 @@
+// ExtractingFilePath.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileName.h"
+
+#include "ExtractingFilePath.h"
+
+bool g_PathTrailReplaceMode =
+ #ifdef _WIN32
+ true
+ #else
+ false
+ #endif
+ ;
+
+
+static void ReplaceIncorrectChars(UString &s)
+{
+ {
+ for (unsigned i = 0; i < s.Len(); i++)
+ {
+ wchar_t c = s[i];
+ if (
+ #ifdef _WIN32
+ c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"'
+ || c == '/'
+ // || c == 0x202E // RLO
+ ||
+ #endif
+ c == WCHAR_PATH_SEPARATOR)
+ s.ReplaceOneCharAtPos(i, '_');
+ }
+ }
+
+ if (g_PathTrailReplaceMode)
+ {
+ /*
+ // if (g_PathTrailReplaceMode == 1)
+ {
+ if (!s.IsEmpty())
+ {
+ wchar_t c = s.Back();
+ if (c == '.' || c == ' ')
+ {
+ // s += (wchar_t)(0x9c); // STRING TERMINATOR
+ s += (wchar_t)'_';
+ }
+ }
+ }
+ else
+ */
+ {
+ unsigned i;
+ for (i = s.Len(); i != 0;)
+ {
+ wchar_t c = s[i - 1];
+ if (c != '.' && c != ' ')
+ break;
+ i--;
+ s.ReplaceOneCharAtPos(i, '_');
+ // s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7));
+ }
+ /*
+ if (g_PathTrailReplaceMode > 1 && i != s.Len())
+ {
+ s.DeleteFrom(i);
+ }
+ */
+ }
+ }
+}
+
+#ifdef _WIN32
+
+/* 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:" */
+
+void Correct_AltStream_Name(UString &s)
+{
+ 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 == '/'
+ || c == 0x202E // RLO
+ )
+ s.ReplaceOneCharAtPos(i, '_');
+ }
+ if (s.IsEmpty())
+ s = '_';
+}
+
+static const unsigned g_ReservedWithNum_Index = 4;
+
+static const char * const g_ReservedNames[] =
+{
+ "CON", "PRN", "AUX", "NUL",
+ "COM", "LPT"
+};
+
+static bool IsSupportedName(const UString &name)
+{
+ for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)
+ {
+ const char *reservedName = g_ReservedNames[i];
+ unsigned len = MyStringLen(reservedName);
+ if (name.Len() < len)
+ continue;
+ if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))
+ continue;
+ 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;
+ }
+ }
+ return true;
+}
+
+static void CorrectUnsupportedName(UString &name)
+{
+ if (!IsSupportedName(name))
+ name.InsertAtFront(L'_');
+}
+
+#endif
+
+static void Correct_PathPart(UString &s)
+{
+ // "." and ".."
+ if (s.IsEmpty())
+ return;
+
+ if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0))
+ s.Empty();
+ #ifdef _WIN32
+ else
+ ReplaceIncorrectChars(s);
+ #endif
+}
+
+// static const char * const k_EmptyReplaceName = "[]";
+static const char k_EmptyReplaceName = '_';
+
+UString Get_Correct_FsFile_Name(const UString &name)
+{
+ UString res = name;
+ Correct_PathPart(res);
+
+ #ifdef _WIN32
+ CorrectUnsupportedName(res);
+ #endif
+
+ if (res.IsEmpty())
+ res = k_EmptyReplaceName;
+ return res;
+}
+
+
+void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)
+{
+ unsigned i = 0;
+
+ if (absIsAllowed)
+ {
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ bool isDrive = false;
+ #endif
+
+ if (parts[0].IsEmpty())
+ {
+ 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
+ }
+ #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.
+ UString &ds = parts[i - 1];
+ if (ds.Len() > 2)
+ {
+ parts.Insert(i, ds.Ptr(2));
+ ds.DeleteFrom(2);
+ }
+ }
+ #endif
+ }
+
+ if (i != 0)
+ keepAndReplaceEmptyPrefixes = false;
+
+ for (; i < parts.Size();)
+ {
+ UString &s = parts[i];
+
+ Correct_PathPart(s);
+
+ if (s.IsEmpty())
+ {
+ if (!keepAndReplaceEmptyPrefixes)
+ if (isDir || i != parts.Size() - 1)
+ {
+ parts.Delete(i);
+ continue;
+ }
+ s = k_EmptyReplaceName;
+ }
+ else
+ {
+ keepAndReplaceEmptyPrefixes = false;
+ #ifdef _WIN32
+ CorrectUnsupportedName(s);
+ #endif
+ }
+
+ i++;
+ }
+
+ if (!isDir)
+ {
+ if (parts.IsEmpty())
+ parts.Add((UString)k_EmptyReplaceName);
+ else
+ {
+ UString &s = parts.Back();
+ if (s.IsEmpty())
+ s = k_EmptyReplaceName;
+ }
+ }
+}
+
+UString MakePathFromParts(const UStringVector &parts)
+{
+ UString s;
+ FOR_VECTOR (i, parts)
+ {
+ if (i != 0)
+ s.Add_PathSepar();
+ s += parts[i];
+ }
+ return s;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.h
new file mode 100644
index 0000000000..12eb0bad7f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.h
@@ -0,0 +1,31 @@
+// ExtractingFilePath.h
+
+#ifndef __EXTRACTING_FILE_PATH_H
+#define __EXTRACTING_FILE_PATH_H
+
+#include "../../../Common/MyString.h"
+
+#ifdef _WIN32
+void Correct_AltStream_Name(UString &s);
+#endif
+
+// replaces unsuported characters, and replaces "." , ".." and "" to "[]"
+UString Get_Correct_FsFile_Name(const UString &name);
+
+/*
+ Correct_FsPath() corrects path parts to prepare it for File System operations.
+ It also corrects empty path parts like "\\\\":
+ - frontal empty path parts : it removes them or changes them to "_"
+ - another empty path parts : it removes them
+ if (absIsAllowed && path is absolute) : it removes empty path parts after start absolute path prefix marker
+ else
+ {
+ if (!keepAndReplaceEmptyPrefixes) : it removes empty path parts
+ if ( keepAndReplaceEmptyPrefixes) : it changes each empty frontal path part to "_"
+ }
+*/
+void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir);
+
+UString MakePathFromParts(const UStringVector &parts);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.cpp
new file mode 100644
index 0000000000..9c0a1d0ae0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.cpp
@@ -0,0 +1,347 @@
+// HashCalc.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/Alloc.h"
+
+#include "../../../Common/StringToInt.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "EnumDirItems.h"
+#include "HashCalc.h"
+
+using namespace NWindows;
+
+class CHashMidBuf
+{
+ void *_data;
+public:
+ CHashMidBuf(): _data(0) {}
+ operator void *() { return _data; }
+ bool Alloc(size_t size)
+ {
+ if (_data != 0)
+ return false;
+ _data = ::MidAlloc(size);
+ return _data != 0;
+ }
+ ~CHashMidBuf() { ::MidFree(_data); }
+};
+
+static const char * const k_DefaultHashMethod = "CRC32";
+
+HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)
+{
+ UStringVector names = hashMethods;
+ if (names.IsEmpty())
+ names.Add(UString(k_DefaultHashMethod));
+
+ CRecordVector<CMethodId> ids;
+ CObjectVector<COneMethodInfo> methods;
+
+ unsigned i;
+ for (i = 0; i < names.Size(); i++)
+ {
+ COneMethodInfo m;
+ RINOK(m.ParseMethodFromString(names[i]));
+
+ if (m.MethodName.IsEmpty())
+ m.MethodName = k_DefaultHashMethod;
+
+ if (m.MethodName == "*")
+ {
+ CRecordVector<CMethodId> tempMethods;
+ GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);
+ methods.Clear();
+ ids.Clear();
+ FOR_VECTOR (t, tempMethods)
+ {
+ unsigned index = ids.AddToUniqueSorted(tempMethods[t]);
+ if (ids.Size() != methods.Size())
+ methods.Insert(index, m);
+ }
+ break;
+ }
+ else
+ {
+ // m.MethodName.RemoveChar(L'-');
+ CMethodId id;
+ if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id))
+ return E_NOTIMPL;
+ unsigned index = ids.AddToUniqueSorted(id);
+ if (ids.Size() != methods.Size())
+ methods.Insert(index, m);
+ }
+ }
+
+ for (i = 0; i < ids.Size(); i++)
+ {
+ CMyComPtr<IHasher> hasher;
+ AString name;
+ RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher));
+ if (!hasher)
+ throw "Can't create hasher";
+ const COneMethodInfo &m = methods[i];
+ {
+ 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)
+ return E_NOTIMPL;
+ CHasherState &h = Hashers.AddNew();
+ h.Hasher = hasher;
+ h.Name = name;
+ h.DigestSize = digestSize;
+ for (unsigned k = 0; k < k_HashCalc_NumGroups; k++)
+ memset(h.Digests[k], 0, digestSize);
+ }
+
+ return S_OK;
+}
+
+void CHashBundle::InitForNewFile()
+{
+ CurSize = 0;
+ FOR_VECTOR (i, Hashers)
+ {
+ CHasherState &h = Hashers[i];
+ h.Hasher->Init();
+ memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize);
+ }
+}
+
+void CHashBundle::Update(const void *data, UInt32 size)
+{
+ CurSize += size;
+ FOR_VECTOR (i, Hashers)
+ Hashers[i].Hasher->Update(data, size);
+}
+
+void CHashBundle::SetSize(UInt64 size)
+{
+ CurSize = size;
+}
+
+static void AddDigests(Byte *dest, const Byte *src, UInt32 size)
+{
+ unsigned next = 0;
+ for (UInt32 i = 0; i < size; i++)
+ {
+ next += (unsigned)dest[i] + (unsigned)src[i];
+ dest[i] = (Byte)next;
+ next >>= 8;
+ }
+}
+
+void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)
+{
+ if (isDir)
+ NumDirs++;
+ else if (isAltStream)
+ {
+ NumAltStreams++;
+ AltStreamsSize += CurSize;
+ }
+ else
+ {
+ NumFiles++;
+ FilesSize += CurSize;
+ }
+
+ Byte pre[16];
+ memset(pre, 0, sizeof(pre));
+ if (isDir)
+ pre[0] = 1;
+
+ FOR_VECTOR (i, Hashers)
+ {
+ CHasherState &h = Hashers[i];
+ if (!isDir)
+ {
+ h.Hasher->Final(h.Digests[0]);
+ if (!isAltStream)
+ AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize);
+ }
+
+ h.Hasher->Init();
+ h.Hasher->Update(pre, sizeof(pre));
+ h.Hasher->Update(h.Digests[0], h.DigestSize);
+
+ for (unsigned k = 0; k < path.Len(); k++)
+ {
+ wchar_t c = path[k];
+ Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) };
+ h.Hasher->Update(temp, 2);
+ }
+
+ Byte tempDigest[k_HashCalc_DigestSize_Max];
+ h.Hasher->Final(tempDigest);
+ if (!isAltStream)
+ AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize);
+ AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize);
+ }
+}
+
+
+HRESULT HashCalc(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const NWildcard::CCensor &censor,
+ const CHashOptions &options,
+ AString &errorInfo,
+ IHashCallbackUI *callback)
+{
+ CDirItems dirItems;
+ dirItems.Callback = callback;
+
+ if (options.StdInMode)
+ {
+ CDirItem di;
+ di.Size = (UInt64)(Int64)-1;
+ di.Attrib = 0;
+ di.MTime.dwLowDateTime = 0;
+ di.MTime.dwHighDateTime = 0;
+ di.CTime = di.ATime = di.MTime;
+ dirItems.Items.Add(di);
+ }
+ else
+ {
+ RINOK(callback->StartScanning());
+ dirItems.ScanAltStreams = options.AltStreamsMode;
+
+ HRESULT res = EnumerateItems(censor,
+ options.PathMode,
+ UString(),
+ dirItems);
+
+ if (res != S_OK)
+ {
+ if (res != E_ABORT)
+ errorInfo = "Scanning error";
+ return res;
+ }
+ RINOK(callback->FinishScanning(dirItems.Stat));
+ }
+
+ unsigned i;
+ CHashBundle hb;
+ RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods));
+ hb.Init();
+
+ hb.NumErrors = dirItems.Stat.NumErrors;
+
+ if (options.StdInMode)
+ {
+ RINOK(callback->SetNumFiles(1));
+ }
+ else
+ {
+ RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes()));
+ }
+
+ const UInt32 kBufSize = 1 << 15;
+ CHashMidBuf buf;
+ if (!buf.Alloc(kBufSize))
+ return E_OUTOFMEMORY;
+
+ UInt64 completeValue = 0;
+
+ RINOK(callback->BeforeFirstFile(hb));
+
+ for (i = 0; i < dirItems.Items.Size(); i++)
+ {
+ CMyComPtr<ISequentialInStream> inStream;
+ UString path;
+ bool isDir = false;
+ bool isAltStream = false;
+ if (options.StdInMode)
+ {
+ inStream = new CStdInFileStream;
+ }
+ else
+ {
+ CInFileStream *inStreamSpec = new CInFileStream;
+ inStream = inStreamSpec;
+ const CDirItem &dirItem = dirItems.Items[i];
+ isDir = dirItem.IsDir();
+ isAltStream = dirItem.IsAltStream;
+ path = dirItems.GetLogPath(i);
+ if (!isDir)
+ {
+ FString phyPath = dirItems.GetPhyPath(i);
+ if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite))
+ {
+ HRESULT res = callback->OpenFileError(phyPath, ::GetLastError());
+ hb.NumErrors++;
+ if (res != S_FALSE)
+ return res;
+ continue;
+ }
+ }
+ }
+ RINOK(callback->GetStream(path, isDir));
+ UInt64 fileSize = 0;
+
+ hb.InitForNewFile();
+ if (!isDir)
+ {
+ for (UInt32 step = 0;; step++)
+ {
+ if ((step & 0xFF) == 0)
+ RINOK(callback->SetCompleted(&completeValue));
+ UInt32 size;
+ RINOK(inStream->Read(buf, kBufSize, &size));
+ if (size == 0)
+ break;
+ hb.Update(buf, size);
+ fileSize += size;
+ completeValue += size;
+ }
+ }
+ hb.Final(isDir, isAltStream, path);
+ RINOK(callback->SetOperationResult(fileSize, hb, !isDir));
+ RINOK(callback->SetCompleted(&completeValue));
+ }
+ return callback->AfterLastFile(hb);
+}
+
+
+static inline char GetHex(unsigned v)
+{
+ 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++)
+ {
+ dest[0] = ' ';
+ dest[1] = ' ';
+ dest += 2;
+ }
+ return;
+ }
+
+ int step = 2;
+ if (size <= 8)
+ {
+ step = -2;
+ dest += size * 2 - 2;
+ }
+
+ for (UInt32 i = 0; i < size; i++)
+ {
+ unsigned b = data[i];
+ dest[0] = GetHex((b >> 4) & 0xF);
+ dest[1] = GetHex(b & 0xF);
+ dest += step;
+ }
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.h
new file mode 100644
index 0000000000..77373b8534
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.h
@@ -0,0 +1,106 @@
+// HashCalc.h
+
+#ifndef __HASH_CALC_H
+#define __HASH_CALC_H
+
+#include "../../../Common/Wildcard.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/MethodProps.h"
+
+#include "DirItem.h"
+
+const unsigned k_HashCalc_DigestSize_Max = 64;
+
+const unsigned k_HashCalc_NumGroups = 4;
+
+enum
+{
+ k_HashCalc_Index_Current,
+ k_HashCalc_Index_DataSum,
+ k_HashCalc_Index_NamesSum,
+ k_HashCalc_Index_StreamsSum
+};
+
+struct CHasherState
+{
+ CMyComPtr<IHasher> Hasher;
+ AString Name;
+ UInt32 DigestSize;
+ Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max];
+};
+
+struct IHashCalc
+{
+ virtual void InitForNewFile() = 0;
+ virtual void Update(const void *data, UInt32 size) = 0;
+ virtual void SetSize(UInt64 size) = 0;
+ virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0;
+};
+
+struct CHashBundle: public IHashCalc
+{
+ CObjectVector<CHasherState> Hashers;
+
+ UInt64 NumDirs;
+ UInt64 NumFiles;
+ UInt64 NumAltStreams;
+ UInt64 FilesSize;
+ UInt64 AltStreamsSize;
+ UInt64 NumErrors;
+
+ UInt64 CurSize;
+
+ HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);
+
+ void Init()
+ {
+ NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
+ }
+
+ void InitForNewFile();
+ void Update(const void *data, UInt32 size);
+ void SetSize(UInt64 size);
+ void Final(bool isDir, bool isAltStream, const UString &path);
+};
+
+#define INTERFACE_IHashCallbackUI(x) \
+ INTERFACE_IDirItemsCallback(x) \
+ virtual HRESULT StartScanning() 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 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: public IDirItemsCallback
+{
+ INTERFACE_IHashCallbackUI(=0)
+};
+
+struct CHashOptions
+{
+ UStringVector Methods;
+ bool OpenShareForWrite;
+ bool StdInMode;
+ bool AltStreamsMode;
+ NWildcard::ECensorPathMode PathMode;
+
+ CHashOptions(): StdInMode(false), OpenShareForWrite(false), AltStreamsMode(false), PathMode(NWildcard::k_RelatPath) {};
+};
+
+HRESULT HashCalc(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const NWildcard::CCensor &censor,
+ const CHashOptions &options,
+ AString &errorInfo,
+ IHashCallbackUI *callback);
+
+void AddHashHexToString(char *dest, const Byte *data, UInt32 size);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/IFileExtractCallback.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/IFileExtractCallback.h
new file mode 100644
index 0000000000..3f554ef31d
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/IFileExtractCallback.h
@@ -0,0 +1,114 @@
+// IFileExtractCallback.h
+
+#ifndef __I_FILE_EXTRACT_CALLBACK_H
+#define __I_FILE_EXTRACT_CALLBACK_H
+
+#include "../../../Common/MyString.h"
+
+#include "../../IDecl.h"
+
+#include "LoadCodecs.h"
+#include "OpenArchive.h"
+
+namespace NOverwriteAnswer
+{
+ enum EEnum
+ {
+ kYes,
+ kYesToAll,
+ kNo,
+ kNoToAll,
+ kAutoRename,
+ kCancel
+ };
+}
+
+
+/* ---------- 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)
+{
+ 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
+{
+ INTERFACE_IExtractCallbackUI(PURE)
+};
+
+
+
+#define INTERFACE_IGetProp(x) \
+ STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \
+
+DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20)
+{
+ INTERFACE_IGetProp(PURE)
+};
+
+#define INTERFACE_IFolderExtractToStreamCallback(x) \
+ 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, Int32 encrypted) x; \
+
+DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)
+{
+ INTERFACE_IFolderExtractToStreamCallback(PURE)
+};
+
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.cpp
new file mode 100644
index 0000000000..d31e05f196
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -0,0 +1,1074 @@
+// 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"
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/StringToInt.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "LoadCodecs.h"
+
+using namespace NWindows;
+
+#ifdef NEW_FOLDER_INTERFACE
+#include "../../../Common/StringToInt.h"
+#endif
+
+#include "../../ICoder.h"
+#include "../../Common/RegisterArc.h"
+
+#ifdef EXTERNAL_CODECS
+
+// #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"
+#endif
+
+using namespace NFile;
+
+
+#define kCodecsFolderName FTEXT("Codecs")
+#define kFormatsFolderName FTEXT("Formats")
+
+
+static CFSTR const kMainDll =
+ // #ifdef _WIN32
+ FTEXT("7z.dll");
+ // #else
+ // FTEXT("7z.so");
+ // #endif
+
+
+#ifdef _WIN32
+
+static LPCTSTR const kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
+static LPCWSTR const kProgramPathValue = L"Path";
+static LPCWSTR const kProgramPath2Value = L"Path"
+ #ifdef _WIN64
+ L"64";
+ #else
+ L"32";
+ #endif
+
+static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)
+{
+ NRegistry::CKey key;
+ if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
+ {
+ UString pathU;
+ if (key.QueryValue(value, pathU) == ERROR_SUCCESS)
+ {
+ path = us2fs(pathU);
+ NName::NormalizeDirPathPrefix(path);
+ return NFind::DoesFileExist(path + kMainDll);
+ }
+ }
+ return false;
+}
+
+#endif // _WIN32
+
+#endif // EXTERNAL_CODECS
+
+
+static const unsigned kNumArcsMax = 64;
+static unsigned g_NumArcs = 0;
+static const CArcInfo *g_Arcs[kNumArcsMax];
+
+void RegisterArc(const CArcInfo *arcInfo) throw()
+{
+ if (g_NumArcs < kNumArcsMax)
+ {
+ g_Arcs[g_NumArcs] = arcInfo;
+ g_NumArcs++;
+ }
+}
+
+static void SplitString(const UString &srcString, UStringVector &destStrings)
+{
+ destStrings.Clear();
+ UString s;
+ unsigned len = srcString.Len();
+ if (len == 0)
+ return;
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = srcString[i];
+ if (c == L' ')
+ {
+ if (!s.IsEmpty())
+ {
+ destStrings.Add(s);
+ s.Empty();
+ }
+ }
+ else
+ s += c;
+ }
+ if (!s.IsEmpty())
+ destStrings.Add(s);
+}
+
+int CArcInfoEx::FindExtension(const UString &ext) const
+{
+ FOR_VECTOR (i, Exts)
+ if (ext.IsEqualTo_NoCase(Exts[i].Ext))
+ return i;
+ return -1;
+}
+
+void CArcInfoEx::AddExts(const UString &ext, const UString &addExt)
+{
+ UStringVector exts, addExts;
+ SplitString(ext, exts);
+ SplitString(addExt, addExts);
+ FOR_VECTOR (i, exts)
+ {
+ CArcExtInfo extInfo;
+ extInfo.Ext = exts[i];
+ if (i < addExts.Size())
+ {
+ extInfo.AddExt = addExts[i];
+ if (extInfo.AddExt == L"*")
+ extInfo.AddExt.Empty();
+ }
+ Exts.Add(extInfo);
+ }
+}
+
+#ifndef _SFX
+
+static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)
+{
+ signatures.Clear();
+ while (size > 0)
+ {
+ unsigned len = *data++;
+ size--;
+ if (len > size)
+ return false;
+ signatures.AddNew().CopyFrom(data, len);
+ data += len;
+ size -= len;
+ }
+ return true;
+}
+
+#endif // _SFX
+
+#ifdef EXTERNAL_CODECS
+
+static FString GetBaseFolderPrefixFromRegistry()
+{
+ FString moduleFolderPrefix = NDLL::GetModuleDirPrefix();
+ #ifdef _WIN32
+ if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&
+ !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&
+ !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))
+ {
+ FString path;
+ if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path;
+ if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path;
+ if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path;
+ if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path;
+ }
+ #endif
+ return moduleFolderPrefix;
+}
+
+
+static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,
+ PROPID propId, CLSID &clsId, bool &isAssigned)
+{
+ NCOM::CPropVariant prop;
+ isAssigned = false;
+ RINOK(getMethodProperty(index, propId, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
+ return E_FAIL;
+ isAssigned = true;
+ clsId = *(const GUID *)prop.bstrVal;
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+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 getNumberOfMethods = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods");
+ if (getNumberOfMethods)
+ {
+ RINOK(getNumberOfMethods(&numMethods));
+ }
+ for (UInt32 i = 0; i < numMethods; i++)
+ {
+ CDllCodecInfo info;
+ info.LibIndex = Libs.Size() - 1;
+ info.CodecIndex = i;
+ RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));
+ RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));
+ Codecs.Add(info);
+ }
+ }
+
+ Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers");
+ if (getHashers)
+ {
+ RINOK(getHashers(&lib.ComHashers));
+ if (lib.ComHashers)
+ {
+ UInt32 numMethods = lib.ComHashers->GetNumHashers();
+ for (UInt32 i = 0; i < numMethods; i++)
+ {
+ CDllHasherInfo info;
+ info.LibIndex = Libs.Size() - 1;
+ info.HasherIndex = i;
+ Hashers.Add(info);
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+static HRESULT GetProp(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
+ UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
+{
+ if (getProp2)
+ return getProp2(index, propID, &prop);;
+ return getProp(propID, &prop);
+}
+
+static HRESULT GetProp_Bool(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
+ UInt32 index, PROPID propID, bool &res)
+{
+ res = false;
+ NCOM::CPropVariant prop;
+ RINOK(GetProp(getProp, getProp2, index, propID, prop));
+ if (prop.vt == VT_BOOL)
+ res = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+static HRESULT GetProp_UInt32(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
+ UInt32 index, PROPID propID, UInt32 &res, bool &defined)
+{
+ res = 0;
+ defined = false;
+ NCOM::CPropVariant prop;
+ RINOK(GetProp(getProp, getProp2, index, propID, prop));
+ if (prop.vt == VT_UI4)
+ {
+ res = prop.ulVal;
+ defined = true;
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+static HRESULT GetProp_String(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
+ UInt32 index, PROPID propID, UString &res)
+{
+ res.Empty();
+ NCOM::CPropVariant prop;
+ RINOK(GetProp(getProp, getProp2, index, propID, prop));
+ if (prop.vt == VT_BSTR)
+ res.SetFromBstr(prop.bstrVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+static HRESULT GetProp_RawData(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
+ UInt32 index, PROPID propID, CByteBuffer &bb)
+{
+ bb.Free();
+ NCOM::CPropVariant prop;
+ RINOK(GetProp(getProp, getProp2, index, propID, prop));
+ if (prop.vt == VT_BSTR)
+ {
+ UINT len = ::SysStringByteLen(prop.bstrVal);
+ bb.CopyFrom((const Byte *)prop.bstrVal, len);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+static const UInt32 kArcFlagsPars[] =
+{
+ NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName,
+ NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams,
+ NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure
+};
+
+HRESULT CCodecs::LoadFormats()
+{
+ const NDLL::CLibrary &lib = Libs.Back().Lib;
+
+ Func_GetHandlerProperty getProp = NULL;
+ Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2");
+ Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc");
+
+ UInt32 numFormats = 1;
+
+ if (getProp2)
+ {
+ Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats");
+ if (getNumberOfFormats)
+ {
+ RINOK(getNumberOfFormats(&numFormats));
+ }
+ }
+ else
+ {
+ getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty");
+ if (!getProp)
+ return S_OK;
+ }
+
+ for (UInt32 i = 0; i < numFormats; i++)
+ {
+ CArcInfoEx item;
+ item.LibIndex = Libs.Size() - 1;
+ item.FormatIndex = i;
+
+ RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name));
+
+ {
+ NCOM::CPropVariant prop;
+ if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK)
+ continue;
+ if (prop.vt != VT_BSTR)
+ continue;
+ if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
+ return E_FAIL;
+ item.ClassID = *(const GUID *)prop.bstrVal;
+ prop.Clear();
+ }
+
+ UString ext, addExt;
+ RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext));
+ RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt));
+ item.AddExts(ext, addExt);
+
+ GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled);
+ bool flags_Defined = false;
+ RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined));
+ item.NewInterface = flags_Defined;
+ if (!flags_Defined) // && item.UpdateEnabled
+ {
+ // support for DLL version before 9.31:
+ for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2)
+ {
+ bool val = false;
+ GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val);
+ if (val)
+ item.Flags |= kArcFlagsPars[j + 1];
+ }
+ }
+
+ CByteBuffer sig;
+ RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig));
+ if (sig.Size() != 0)
+ item.Signatures.Add(sig);
+ else
+ {
+ RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig));
+ ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures);
+ }
+
+ bool signatureOffset_Defined;
+ RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined));
+
+ // bool version_Defined;
+ // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined));
+
+ if (getIsArc)
+ getIsArc(i, &item.IsArcFunc);
+
+ Formats.Add(item);
+ }
+ return S_OK;
+}
+
+#ifdef _7ZIP_LARGE_PAGES
+extern "C"
+{
+ extern SIZE_T g_LargePageSize;
+}
+#endif
+
+HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK)
+{
+ if (loadedOK)
+ *loadedOK = false;
+
+ if (needCheckDll)
+ {
+ NDLL::CLibrary lib;
+ if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
+ return S_OK;
+ }
+
+ 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
+
+ #ifdef _7ZIP_LARGE_PAGES
+ if (g_LargePageSize != 0)
+ {
+ Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode");
+ if (setLargePageMode)
+ setLargePageMode();
+ }
+ #endif
+
+ if (CaseSensitiveChange)
+ {
+ Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive");
+ if (setCaseSensitive)
+ setCaseSensitive(CaseSensitive ? 1 : 0);
+ }
+
+ lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject");
+ {
+ unsigned startSize = Codecs.Size() + Hashers.Size();
+ res = LoadCodecs();
+ used = (startSize != Codecs.Size() + Hashers.Size());
+ if (res == S_OK && lib.CreateObject)
+ {
+ startSize = Formats.Size();
+ res = LoadFormats();
+ if (startSize != Formats.Size())
+ used = true;
+ }
+ }
+ }
+
+ if (!used)
+ Libs.DeleteBack();
+
+ return res;
+}
+
+HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix)
+{
+ NFile::NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(folderPrefix);
+ NFile::NFind::CFileInfo fi;
+ while (enumerator.Next(fi))
+ {
+ if (fi.IsDir())
+ continue;
+ RINOK(LoadDll(folderPrefix + fi.Name, true));
+ }
+ return S_OK;
+}
+
+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);
+ #endif
+
+ Formats.Clear();
+
+ #ifdef EXTERNAL_CODECS
+ MainDll_ErrorPath.Empty();
+ Codecs.Clear();
+ Hashers.Clear();
+ #endif
+
+ for (UInt32 i = 0; i < g_NumArcs; i++)
+ {
+ const CArcInfo &arc = *g_Arcs[i];
+ CArcInfoEx item;
+
+ item.Name = arc.Name;
+ item.CreateInArchive = arc.CreateInArchive;
+ item.IsArcFunc = arc.IsArc;
+ item.Flags = arc.Flags;
+
+ {
+ UString e, ae;
+ if (arc.Ext)
+ e = arc.Ext;
+ if (arc.AddExt)
+ ae = arc.AddExt;
+ item.AddExts(e, ae);
+ }
+
+ #ifndef _SFX
+
+ item.CreateOutArchive = arc.CreateOutArchive;
+ item.UpdateEnabled = (arc.CreateOutArchive != NULL);
+ item.SignatureOffset = arc.SignatureOffset;
+ // item.Version = MY_VER_MIX;
+ item.NewInterface = true;
+
+ if (arc.IsMultiSignature())
+ ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);
+ else
+ item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
+
+ #endif
+
+ Formats.Add(item);
+ }
+
+ #ifdef EXTERNAL_CODECS
+ const FString baseFolder = GetBaseFolderPrefixFromRegistry();
+ {
+ 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;
+}
+
+#ifndef _SFX
+
+int CCodecs::FindFormatForArchiveName(const UString &arcPath) const
+{
+ 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.IsEqualTo_Ascii_NoCase("exe"))
+ return -1;
+ FOR_VECTOR (i, Formats)
+ {
+ const CArcInfoEx &arc = Formats[i];
+ /*
+ if (!arc.UpdateEnabled)
+ continue;
+ */
+ if (arc.FindExtension(ext) >= 0)
+ return i;
+ }
+ return -1;
+}
+
+int CCodecs::FindFormatForExtension(const UString &ext) const
+{
+ if (ext.IsEmpty())
+ return -1;
+ FOR_VECTOR (i, Formats)
+ if (Formats[i].FindExtension(ext) >= 0)
+ return i;
+ return -1;
+}
+
+int CCodecs::FindFormatForArchiveType(const UString &arcType) const
+{
+ FOR_VECTOR (i, Formats)
+ if (Formats[i].Name.IsEqualTo_NoCase(arcType))
+ return i;
+ return -1;
+}
+
+bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const
+{
+ formatIndices.Clear();
+ for (unsigned pos = 0; pos < arcType.Len();)
+ {
+ int pos2 = arcType.Find(L'.', pos);
+ if (pos2 < 0)
+ pos2 = arcType.Len();
+ const UString name = arcType.Mid(pos, pos2 - pos);
+ if (name.IsEmpty())
+ return false;
+ int index = FindFormatForArchiveType(name);
+ if (index < 0 && name != L"*")
+ {
+ formatIndices.Clear();
+ return false;
+ }
+ formatIndices.Add(index);
+ pos = pos2 + 1;
+ }
+ return true;
+}
+
+#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
+
+#ifdef EXPORT_CODECS
+
+extern unsigned g_NumCodecs;
+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
+
+extern unsigned g_NumHashers;
+STDAPI CreateHasher(UInt32 index, IHasher **hasher);
+STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
+#define NUM_EXPORT_HASHERS g_NumHashers
+
+#else // EXPORT_CODECS
+
+#define NUM_EXPORT_CODECS 0
+#define NUM_EXPORT_HASHERS 0
+
+#endif // EXPORT_CODECS
+
+STDMETHODIMP CCodecs::GetNumMethods(UInt32 *numMethods)
+{
+ *numMethods = NUM_EXPORT_CODECS
+ #ifdef EXTERNAL_CODECS
+ + Codecs.Size()
+ #endif
+ ;
+ return S_OK;
+}
+
+STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumCodecs)
+ return GetMethodProperty(index, propID, value);
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
+
+ if (propID == NMethodPropID::kDecoderIsAssigned ||
+ propID == NMethodPropID::kEncoderIsAssigned)
+ {
+ NCOM::CPropVariant prop;
+ prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ?
+ ci.DecoderIsAssigned :
+ ci.EncoderIsAssigned);
+ prop.Detach(value);
+ return S_OK;
+ }
+ const CCodecLib &lib = Libs[ci.LibIndex];
+ return lib.GetMethodProperty(ci.CodecIndex, propID, value);
+ #else
+ return E_FAIL;
+ #endif
+}
+
+STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumCodecs)
+ return CreateDecoder(index, iid, coder);
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
+ if (ci.DecoderIsAssigned)
+ {
+ const CCodecLib &lib = Libs[ci.LibIndex];
+ if (lib.CreateDecoder)
+ return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);
+ if (lib.CreateObject)
+ return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
+ }
+ return S_OK;
+ #else
+ return E_FAIL;
+ #endif
+}
+
+STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumCodecs)
+ return CreateEncoder(index, iid, coder);
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
+ if (ci.EncoderIsAssigned)
+ {
+ const CCodecLib &lib = Libs[ci.LibIndex];
+ if (lib.CreateEncoder)
+ return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);
+ if (lib.CreateObject)
+ return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
+ }
+ return S_OK;
+ #else
+ return E_FAIL;
+ #endif
+}
+
+
+STDMETHODIMP_(UInt32) CCodecs::GetNumHashers()
+{
+ return NUM_EXPORT_HASHERS
+ #ifdef EXTERNAL_CODECS
+ + Hashers.Size()
+ #endif
+ ;
+}
+
+STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumHashers)
+ return ::GetHasherProp(index, propID, value);
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
+ return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value);
+ #else
+ return E_FAIL;
+ #endif
+}
+
+STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumHashers)
+ return CreateHasher(index, hasher);
+ #endif
+ #ifdef EXTERNAL_CODECS
+ const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
+ return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher);
+ #else
+ return E_FAIL;
+ #endif
+}
+
+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;
+ #else
+ return -1;
+ #endif
+}
+
+int CCodecs::GetHasherLibIndex(UInt32 index)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumHashers)
+ return -1;
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
+ return ci.LibIndex;
+ #else
+ return -1;
+ #endif
+}
+
+bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumCodecs)
+ {
+ NCOM::CPropVariant prop;
+ if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &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].DecoderIsAssigned;
+ #else
+ return false;
+ #endif
+}
+
+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));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ id = prop.uhVal.QuadPart;
+ return S_OK;
+}
+
+AString CCodecs::GetCodec_Name(UInt32 index)
+{
+ AString s;
+ NCOM::CPropVariant prop;
+ if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
+ if (prop.vt == VT_BSTR)
+ s.SetFromWStr_if_Ascii(prop.bstrVal);
+ return s;
+}
+
+UInt64 CCodecs::GetHasherId(UInt32 index)
+{
+ NCOM::CPropVariant prop;
+ if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK)
+ return 0;
+ if (prop.vt != VT_UI8)
+ return 0;
+ return prop.uhVal.QuadPart;
+}
+
+AString CCodecs::GetHasherName(UInt32 index)
+{
+ AString s;
+ NCOM::CPropVariant prop;
+ if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)
+ if (prop.vt == VT_BSTR)
+ s.SetFromWStr_if_Ascii(prop.bstrVal);
+ return s;
+}
+
+UInt32 CCodecs::GetHasherDigestSize(UInt32 index)
+{
+ NCOM::CPropVariant prop;
+ RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop));
+ if (prop.vt != VT_UI4)
+ return 0;
+ return prop.ulVal;
+}
+
+#endif // EXTERNAL_CODECS
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.h
new file mode 100644
index 0000000000..9ba36d3e9e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.h
@@ -0,0 +1,424 @@
+// LoadCodecs.h
+
+#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"
+
+#ifdef EXTERNAL_CODECS
+#include "../../../Windows/DLL.h"
+#endif
+
+#include "../../ICoder.h"
+
+#include "../../Archive/IArchive.h"
+
+
+#ifdef EXTERNAL_CODECS
+
+struct CDllCodecInfo
+{
+ unsigned LibIndex;
+ UInt32 CodecIndex;
+ bool EncoderIsAssigned;
+ bool DecoderIsAssigned;
+ CLSID Encoder;
+ CLSID Decoder;
+};
+
+struct CDllHasherInfo
+{
+ unsigned LibIndex;
+ UInt32 HasherIndex;
+};
+
+#endif
+
+struct CArcExtInfo
+{
+ UString Ext;
+ UString AddExt;
+
+ CArcExtInfo() {}
+ CArcExtInfo(const UString &ext): Ext(ext) {}
+ CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}
+};
+
+
+struct CArcInfoEx
+{
+ UInt32 Flags;
+
+ Func_CreateInArchive CreateInArchive;
+ Func_IsArc IsArcFunc;
+
+ UString Name;
+ CObjectVector<CArcExtInfo> Exts;
+
+ #ifndef _SFX
+ Func_CreateOutArchive CreateOutArchive;
+ bool UpdateEnabled;
+ bool NewInterface;
+ // UInt32 Version;
+ UInt32 SignatureOffset;
+ CObjectVector<CByteBuffer> Signatures;
+ #ifdef NEW_FOLDER_INTERFACE
+ UStringVector AssociateExts;
+ #endif
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ int LibIndex;
+ UInt32 FormatIndex;
+ CLSID ClassID;
+ #endif
+
+ bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }
+ bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
+
+ bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }
+ bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }
+ bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; }
+ bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; }
+
+ bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; }
+ bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; }
+ bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; }
+ bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }
+ bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }
+
+ UString GetMainExt() const
+ {
+ if (Exts.IsEmpty())
+ return UString();
+ return Exts[0].Ext;
+ }
+ int FindExtension(const UString &ext) const;
+
+ /*
+ UString GetAllExtensions() const
+ {
+ UString s;
+ for (int i = 0; i < Exts.Size(); i++)
+ {
+ if (i > 0)
+ s += ' ';
+ s += Exts[i].Ext;
+ }
+ return s;
+ }
+ */
+
+ void AddExts(const UString &ext, const UString &addExt);
+
+ bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }
+ // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }
+
+ CArcInfoEx():
+ Flags(0),
+ CreateInArchive(NULL),
+ IsArcFunc(NULL)
+ #ifndef _SFX
+ , CreateOutArchive(NULL)
+ , UpdateEnabled(false)
+ , NewInterface(false)
+ // , Version(0)
+ , SignatureOffset(0)
+ #endif
+ #ifdef EXTERNAL_CODECS
+ , LibIndex(-1)
+ #endif
+ {}
+};
+
+#ifdef NEW_FOLDER_INTERFACE
+
+struct CCodecIcons
+{
+ struct CIconPair
+ {
+ UString Ext;
+ 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
+ #endif
+{
+ NWindows::NDLL::CLibrary Lib;
+ FString Path;
+
+ Func_CreateObject CreateObject;
+ 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():
+ CreateObject(NULL),
+ GetMethodProperty(NULL),
+ CreateDecoder(NULL),
+ CreateEncoder(NULL),
+ SetCodecs(NULL)
+ {}
+};
+
+#endif
+
+
+class CCodecs:
+ #ifdef EXTERNAL_CODECS
+ public ICompressCodecsInfo,
+ public IHashers,
+ #else
+ public IUnknown,
+ #endif
+ public CMyUnknownImp
+{
+ CLASS_NO_COPY(CCodecs);
+public:
+ #ifdef EXTERNAL_CODECS
+
+ CObjectVector<CCodecLib> Libs;
+ FString MainDll_ErrorPath;
+
+ 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, bool *loadedOK = NULL);
+ HRESULT LoadDllsFromFolder(const FString &folderPrefix);
+
+ 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
+
+ CObjectVector<CArcInfoEx> Formats;
+
+ #ifdef EXTERNAL_CODECS
+ CRecordVector<CDllCodecInfo> Codecs;
+ CRecordVector<CDllHasherInfo> Hashers;
+ #endif
+
+ bool CaseSensitiveChange;
+ bool CaseSensitive;
+
+ CCodecs():
+ #ifdef EXTERNAL_CODECS
+ NeedSetLibCodecs(true),
+ #endif
+ CaseSensitiveChange(false),
+ CaseSensitive(false)
+ {}
+
+ ~CCodecs()
+ {
+ // OutputDebugStringA("~CCodecs");
+ }
+
+ const wchar_t *GetFormatNamePtr(int formatIndex) const
+ {
+ return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name;
+ }
+
+ HRESULT Load();
+
+ #ifndef _SFX
+ int FindFormatForArchiveName(const UString &arcPath) const;
+ int FindFormatForExtension(const UString &ext) const;
+ int FindFormatForArchiveType(const UString &arcType) const;
+ bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+
+ MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)
+
+ STDMETHOD(GetNumMethods)(UInt32 *numMethods);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ 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);
+ STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);
+
+ #else
+
+ MY_UNKNOWN_IMP
+
+ #endif // EXTERNAL_CODECS
+
+
+ #ifdef EXTERNAL_CODECS
+
+ 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);
+ AString GetHasherName(UInt32 index);
+ UInt32 GetHasherDigestSize(UInt32 index);
+
+ #endif
+
+ HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const
+ {
+ const CArcInfoEx &ai = Formats[formatIndex];
+ #ifdef EXTERNAL_CODECS
+ if (ai.LibIndex < 0)
+ #endif
+ {
+ COM_TRY_BEGIN
+ archive = ai.CreateInArchive();
+ return S_OK;
+ COM_TRY_END
+ }
+ #ifdef EXTERNAL_CODECS
+ return CreateArchiveHandler(ai, false, (void **)&archive);
+ #endif
+ }
+
+ #ifndef _SFX
+
+ HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const
+ {
+ const CArcInfoEx &ai = Formats[formatIndex];
+ #ifdef EXTERNAL_CODECS
+ if (ai.LibIndex < 0)
+ #endif
+ {
+ COM_TRY_BEGIN
+ archive = ai.CreateOutArchive();
+ return S_OK;
+ COM_TRY_END
+ }
+
+ #ifdef EXTERNAL_CODECS
+ return CreateArchiveHandler(ai, true, (void **)&archive);
+ #endif
+ }
+
+ int FindOutFormatFromName(const UString &name) const
+ {
+ FOR_VECTOR (i, Formats)
+ {
+ const CArcInfoEx &arc = Formats[i];
+ if (!arc.UpdateEnabled)
+ continue;
+ if (arc.Name.IsEqualTo_NoCase(name))
+ return i;
+ }
+ return -1;
+ }
+
+ #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/other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.cpp
new file mode 100644
index 0000000000..9549269147
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -0,0 +1,3550 @@
+// OpenArchive.cpp
+
+#include "StdAfx.h"
+
+// #define SHOW_DEBUG_INFO
+
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "DefaultName.h"
+#include "OpenArchive.h"
+
+#ifndef _SFX
+#include "SetProperties.h"
+#endif
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+// increase it, if you need to support larger SFX stubs
+static const UInt64 kMaxCheckStartPosition = 1 << 23;
+
+/*
+Open:
+ - formatIndex >= 0 (exact Format)
+ 1) Open with main type. Archive handler is allowed to use archive start finder.
+ Warning, if there is tail.
+
+ - formatIndex = -1 (Parser:0) (default)
+ - same as #1 but doesn't return Parser
+
+ - formatIndex = -2 (#1)
+ - file has supported extension (like a.7z)
+ Open with that main type (only starting from start of file).
+ - open OK:
+ - if there is no tail - return OK
+ - if there is tail:
+ - archive is not "Self Exe" - return OK with Warning, that there is tail
+ - archive is "Self Exe"
+ ignore "Self Exe" stub, and tries to open tail
+ - tail can be open as archive - shows that archive and stub size property.
+ - tail can't be open as archive - shows Parser ???
+ - open FAIL:
+ Try to open with all other types from offset 0 only.
+ If some open type is OK and physical archive size is uequal or larger
+ than file size, then return that archive with warning that can not be open as [extension type].
+ If extension was EXE, it will try to open as unknown_extension case
+ - file has unknown extension (like a.hhh)
+ It tries to open via parser code.
+ - if there is full archive or tail archive and unknown block or "Self Exe"
+ at front, it shows tail archive and stub size property.
+ - in another cases, if there is some archive inside file, it returns parser/
+ - in another cases, it retuens S_FALSE
+
+
+ - formatIndex = -3 (#2)
+ - same as #1, but
+ - stub (EXE) + archive is open in Parser
+
+ - formatIndex = -4 (#3)
+ - returns only Parser. skip full file archive. And show other sub-archives
+
+ - formatIndex = -5 (#4)
+ - returns only Parser. skip full file archive. And show other sub-archives for each byte pos
+
+*/
+
+
+
+
+using namespace NWindows;
+
+/*
+#ifdef _SFX
+#define OPEN_PROPS_PARAM
+#else
+#define OPEN_PROPS_PARAM , props
+#endif
+*/
+
+/*
+CArc::~CArc()
+{
+ GetRawProps.Release();
+ Archive.Release();
+ printf("\nCArc::~CArc()\n");
+}
+*/
+
+#ifndef _SFX
+
+namespace NArchive {
+namespace NParser {
+
+struct CParseItem
+{
+ UInt64 Offset;
+ UInt64 Size;
+ // UInt64 OkSize;
+ UString Name;
+ UString Extension;
+ FILETIME FileTime;
+ UString Comment;
+ UString ArcType;
+
+ bool FileTime_Defined;
+ bool UnpackSize_Defined;
+ bool NumSubDirs_Defined;
+ bool NumSubFiles_Defined;
+
+ bool IsSelfExe;
+ bool IsNotArcType;
+
+ UInt64 UnpackSize;
+ UInt64 NumSubDirs;
+ UInt64 NumSubFiles;
+
+ int FormatIndex;
+
+ bool LenIsUnknown;
+
+ CParseItem():
+ LenIsUnknown(false),
+ FileTime_Defined(false),
+ UnpackSize_Defined(false),
+ NumSubFiles_Defined(false),
+ NumSubDirs_Defined(false),
+ IsSelfExe(false),
+ IsNotArcType(false)
+ // OkSize(0)
+ {}
+
+ /*
+ bool IsEqualTo(const CParseItem &item) const
+ {
+ return Offset == item.Offset && Size == item.Size;
+ }
+ */
+
+ void NormalizeOffset()
+ {
+ if ((Int64)Offset < 0)
+ {
+ Size += Offset;
+ // OkSize += Offset;
+ Offset = 0;
+ }
+ }
+};
+
+class CHandler:
+ public IInArchive,
+ public IInArchiveGetStream,
+ public CMyUnknownImp
+{
+public:
+ CObjectVector<CParseItem> _items;
+ UInt64 _maxEndOffset;
+ CMyComPtr<IInStream> _stream;
+
+ MY_UNKNOWN_IMP2(
+ IInArchive,
+ IInArchiveGetStream)
+
+ INTERFACE_IInArchive(;)
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+
+ UInt64 GetLastEnd() const
+ {
+ if (_items.IsEmpty())
+ return 0;
+ const CParseItem &back = _items.Back();
+ return back.Offset + back.Size;
+ }
+
+ void AddUnknownItem(UInt64 next);
+ int FindInsertPos(const CParseItem &item) const;
+ void AddItem(const CParseItem &item);
+
+ CHandler(): _maxEndOffset(0) {}
+};
+
+int CHandler::FindInsertPos(const CParseItem &item) const
+{
+ unsigned left = 0, right = _items.Size();
+ while (left != right)
+ {
+ unsigned mid = (left + right) / 2;
+ const CParseItem & midItem = _items[mid];
+ if (item.Offset < midItem.Offset)
+ right = mid;
+ else if (item.Offset > midItem.Offset)
+ left = mid + 1;
+ else if (item.Size < midItem.Size)
+ right = mid;
+ else if (item.Size > midItem.Size)
+ left = mid + 1;
+ else
+ {
+ left = mid + 1;
+ // return -1;
+ }
+ }
+ return left;
+}
+
+void CHandler::AddUnknownItem(UInt64 next)
+{
+ /*
+ UInt64 prevEnd = 0;
+ if (!_items.IsEmpty())
+ {
+ const CParseItem &back = _items.Back();
+ prevEnd = back.Offset + back.Size;
+ }
+ */
+ if (_maxEndOffset < next)
+ {
+ CParseItem item2;
+ item2.Offset = _maxEndOffset;
+ item2.Size = next - _maxEndOffset;
+ _maxEndOffset = next;
+ _items.Add(item2);
+ }
+ else if (_maxEndOffset > next && !_items.IsEmpty())
+ {
+ CParseItem &back = _items.Back();
+ if (back.LenIsUnknown)
+ {
+ back.Size = next - back.Offset;
+ _maxEndOffset = next;
+ }
+ }
+}
+
+void CHandler::AddItem(const CParseItem &item)
+{
+ AddUnknownItem(item.Offset);
+ int pos = FindInsertPos(item);
+ if (pos >= 0)
+ {
+ _items.Insert(pos, item);
+ UInt64 next = item.Offset + item.Size;
+ if (_maxEndOffset < next)
+ _maxEndOffset = next;
+ }
+}
+
+/*
+static const CStatProp kProps[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidMTime, VT_FILETIME},
+ { NULL, kpidType, VT_BSTR},
+ { NULL, kpidComment, VT_BSTR},
+ { NULL, kpidOffset, VT_UI8},
+ { NULL, kpidUnpackSize, VT_UI8},
+// { NULL, kpidNumSubDirs, VT_UI8},
+};
+*/
+
+static const Byte kProps[] =
+{
+ kpidPath,
+ kpidSize,
+ kpidMTime,
+ kpidType,
+ kpidComment,
+ kpidOffset,
+ kpidUnpackSize
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ {
+ Close();
+ _stream = stream;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _items.Clear();
+ _stream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _items.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+
+ const CParseItem &item = _items[index];
+
+ switch (propID)
+ {
+ case kpidPath:
+ {
+ char sz[32];
+ ConvertUInt32ToString(index + 1, sz);
+ UString s(sz);
+ if (!item.Name.IsEmpty())
+ {
+ s += '.';
+ s += item.Name;
+ }
+ if (!item.Extension.IsEmpty())
+ {
+ s += '.';
+ s += item.Extension;
+ }
+ prop = s; break;
+ }
+ case kpidSize:
+ case kpidPackSize: prop = item.Size; break;
+ case kpidOffset: prop = item.Offset; break;
+ case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break;
+ case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break;
+ case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break;
+ case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break;
+ case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break;
+ case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+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();
+ if (_stream && numItems == 0)
+ return S_OK;
+ UInt64 totalSize = 0;
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ totalSize += _items[allFilesMode ? i : indices[i]].Size;
+ extractCallback->SetTotal(totalSize);
+
+ totalSize = 0;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_stream);
+
+ CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+ for (i = 0; i < numItems; i++)
+ {
+ lps->InSize = totalSize;
+ lps->OutSize = totalSize;
+ RINOK(lps->SetCur());
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+ Int32 index = allFilesMode ? i : indices[i];
+ const CParseItem &item = _items[index];
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ UInt64 unpackSize = item.Size;
+ totalSize += unpackSize;
+ bool skipMode = false;
+ if (!testMode && !realOutStream)
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ outStreamSpec->SetStream(realOutStream);
+ realOutStream.Release();
+ outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
+
+ Int32 opRes = NExtract::NOperationResult::kOK;
+ RINOK(_stream->Seek(item.Offset, STREAM_SEEK_SET, NULL));
+ streamSpec->Init(unpackSize);
+ RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+
+ if (outStreamSpec->GetRem() != 0)
+ opRes = NExtract::NOperationResult::kDataError;
+ outStreamSpec->ReleaseStream();
+ RINOK(extractCallback->SetOperationResult(opRes));
+ }
+
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ COM_TRY_BEGIN
+ const CParseItem &item = _items[index];
+ return CreateLimitedInStream(_stream, item.Offset, item.Size, stream);
+ COM_TRY_END
+}
+
+}}
+
+#endif
+
+HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw()
+{
+ NCOM::CPropVariant prop;
+ result = false;
+ RINOK(arc->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_BOOL)
+ result = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw()
+{
+ return Archive_GetItemBoolProp(arc, index, kpidIsDir, result);
+}
+
+HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw()
+{
+ return Archive_GetItemBoolProp(arc, index, kpidIsAux, result);
+}
+
+HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw()
+{
+ return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result);
+}
+
+HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) throw()
+{
+ return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);
+}
+
+static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) throw()
+{
+ NCOM::CPropVariant prop;
+ result = false;
+ RINOK(arc->GetArchiveProperty(propid, &prop));
+ if (prop.vt == VT_BOOL)
+ result = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined)
+{
+ defined = false;
+ NCOM::CPropVariant prop;
+ RINOK(arc->GetArchiveProperty(propid, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI4: result = prop.ulVal; defined = true; break;
+ case VT_I4: result = (Int64)prop.lVal; defined = true; break;
+ case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; defined = true; break;
+ case VT_I8: result = (UInt64)prop.hVal.QuadPart; defined = true; break;
+ case VT_EMPTY: break;
+ default: return E_FAIL;
+ }
+ return S_OK;
+}
+
+static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined)
+{
+ defined = false;
+ NCOM::CPropVariant prop;
+ RINOK(arc->GetArchiveProperty(propid, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI4: result = prop.ulVal; defined = true; break;
+ case VT_I4: result = prop.lVal; defined = true; break;
+ case VT_UI8: result = (Int64)prop.uhVal.QuadPart; defined = true; break;
+ case VT_I8: result = (Int64)prop.hVal.QuadPart; defined = true; break;
+ case VT_EMPTY: break;
+ default: return E_FAIL;
+ }
+ 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 (;;)
+ {
+ #ifdef MY_CPU_LE
+ const void *p;
+ UInt32 size;
+ UInt32 propType;
+ RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType));
+ if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
+ s = (const wchar_t *)p;
+ else
+ #endif
+ {
+ NCOM::CPropVariant prop;
+ RINOK(Archive->GetProperty(curIndex, kpidName, &prop));
+ if (prop.vt == VT_BSTR && prop.bstrVal)
+ s.SetFromBstr(prop.bstrVal);
+ else if (prop.vt == VT_EMPTY)
+ s.Empty();
+ else
+ return E_FAIL;
+ }
+
+ 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 &s2 = parts[parts.Size() - 2];
+ s2 += ':';
+ s2 += 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;
+ curIndex = curParent;
+ }
+}
+
+#endif
+
+HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
+{
+ #ifdef MY_CPU_LE
+ if (GetRawProps)
+ {
+ const void *p;
+ UInt32 size;
+ UInt32 propType;
+ if (!IsTree)
+ {
+ if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK &&
+ propType == NPropDataType::kUtf16z)
+ {
+ unsigned len = size / 2 - 1;
+ wchar_t *s = result.GetBuf(len);
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = GetUi16(p);
+ p = (const void *)((const Byte *)p + 2);
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ if (c == L'/')
+ c = WCHAR_PATH_SEPARATOR;
+ #endif
+ *s++ = c;
+ }
+ *s = 0;
+ result.ReleaseBuf_SetLen(len);
+ if (len != 0)
+ return S_OK;
+ }
+ }
+ /*
+ 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 (;;)
+ {
+ UInt32 parent = (UInt32)(Int32)-1;
+ UInt32 parentType = 0;
+ if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)
+ 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 &&
+ p2 && propType == NPropDataType::kUtf16z)
+ break;
+ totalSize += size2;
+ }
+ }
+
+ if (isOK)
+ {
+ wchar_t *sz = result.GetBuf_SetEnd(totalSize / 2);
+ UInt32 pos = totalSize - size;
+ memcpy((Byte *)sz + pos, p, size);
+ UInt32 index2 = index;
+ for (;;)
+ {
+ UInt32 parent = (UInt32)(Int32)-1;
+ UInt32 parentType = 0;
+ 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;
+ if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)
+ break;
+ pos -= size2;
+ memcpy((Byte *)sz + pos, p2, size2);
+ sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':';
+ }
+ #ifdef _WIN32
+ // result.Replace(L'/', WCHAR_PATH_SEPARATOR);
+ #endif
+ return S_OK;
+ }
+ }
+ */
+ }
+ #endif
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(Archive->GetProperty(index, kpidPath, &prop));
+ if (prop.vt == VT_BSTR && prop.bstrVal)
+ result.SetFromBstr(prop.bstrVal);
+ else if (prop.vt == VT_EMPTY)
+ result.Empty();
+ else
+ return E_FAIL;
+ }
+
+ 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;
+ RINOK(Archive->GetProperty(index, kpidExtension, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ result += '.';
+ result += prop.bstrVal;
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ }
+ return S_OK;
+}
+
+HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const
+{
+ RINOK(GetItemPath(index, result));
+ if (Ask_Deleted)
+ {
+ bool isDeleted = false;
+ RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted));
+ if (isDeleted)
+ result.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR);
+ }
+ 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[(unsigned)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)
+{
+ NCOM::CPropVariant prop;
+ defined = false;
+ size = 0;
+ RINOK(archive->GetProperty(index, kpidSize, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI1: size = prop.bVal; break;
+ case VT_UI2: size = prop.uiVal; break;
+ case VT_UI4: size = prop.ulVal; break;
+ case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;
+ case VT_EMPTY: return S_OK;
+ default: return E_FAIL;
+ }
+ defined = true;
+ return S_OK;
+}
+
+#endif
+
+HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const
+{
+ NCOM::CPropVariant prop;
+ defined = false;
+ size = 0;
+ RINOK(Archive->GetProperty(index, kpidSize, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI1: size = prop.bVal; break;
+ case VT_UI2: size = prop.uiVal; break;
+ case VT_UI4: size = prop.ulVal; break;
+ case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;
+ case VT_EMPTY: return S_OK;
+ default: return E_FAIL;
+ }
+ defined = true;
+ return S_OK;
+}
+
+HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const
+{
+ NCOM::CPropVariant prop;
+ defined = false;
+ ft.dwHighDateTime = ft.dwLowDateTime = 0;
+ RINOK(Archive->GetProperty(index, kpidMTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ ft = prop.filetime;
+ defined = true;
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ else if (MTimeDefined)
+ {
+ ft = MTime;
+ defined = true;
+ }
+ return S_OK;
+}
+
+#ifndef _SFX
+
+static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
+{
+ for (size_t i = 0; i < size; i++)
+ if (p1[i] != p2[i])
+ return false;
+ return true;
+}
+
+static void MakeCheckOrder(CCodecs *codecs,
+ CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2,
+ const Byte *data, size_t dataSize)
+{
+ for (unsigned i = 0; i < numTypes; i++)
+ {
+ int index = orderIndices[i];
+ if (index < 0)
+ continue;
+ const CArcInfoEx &ai = codecs->Formats[(unsigned)index];
+ if (ai.SignatureOffset != 0)
+ {
+ orderIndices2.Add(index);
+ orderIndices[i] = -1;
+ continue;
+ }
+
+ const CObjectVector<CByteBuffer> &sigs = ai.Signatures;
+ FOR_VECTOR (k, sigs)
+ {
+ const CByteBuffer &sig = sigs[k];
+ if (sig.Size() == 0 && dataSize == 0 ||
+ sig.Size() != 0 && sig.Size() <= dataSize &&
+ TestSignature(data, sig, sig.Size()))
+ {
+ orderIndices2.Add(index);
+ orderIndices[i] = -1;
+ break;
+ }
+ }
+ }
+}
+
+#endif
+
+#ifdef UNDER_CE
+ static const unsigned kNumHashBytes = 1;
+ #define HASH_VAL(buf) ((buf)[0])
+#else
+ static const unsigned kNumHashBytes = 2;
+ // #define HASH_VAL(buf) ((buf)[0] | ((UInt32)(buf)[1] << 8))
+ #define HASH_VAL(buf) GetUi16(buf)
+#endif
+
+
+#ifndef _SFX
+
+static bool IsExeExt(const UString &ext)
+{
+ return ext.IsEqualTo_Ascii_NoCase("exe");
+}
+
+static const char * const k_PreArcFormats[] =
+{
+ "pe"
+ , "elf"
+ , "macho"
+ , "mub"
+ , "te"
+};
+
+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]))
+ return true;
+ return false;
+}
+
+
+static bool IsPreArcFormat(const CArcInfoEx &ai)
+{
+ if (ai.Flags_PreArc())
+ return true;
+ return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats));
+}
+
+static const char * const k_Formats_with_simple_signuature[] =
+{
+ "7z"
+ , "xz"
+ , "rar"
+ , "bzip2"
+ , "gzip"
+ , "cab"
+ , "wim"
+ , "rpm"
+ , "vhd"
+ , "xar"
+};
+
+static bool IsNewStyleSignature(const CArcInfoEx &ai)
+{
+ // if (ai.Version >= 0x91F)
+ if (ai.NewInterface)
+ return true;
+ return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, ARRAY_SIZE(k_Formats_with_simple_signuature));
+}
+
+class CArchiveOpenCallback_Offset:
+ public IArchiveOpenCallback,
+ public IArchiveOpenVolumeCallback,
+ #ifndef _NO_CRYPTO
+ public ICryptoGetTextPassword,
+ #endif
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<IArchiveOpenCallback> Callback;
+ CMyComPtr<IArchiveOpenVolumeCallback> OpenVolumeCallback;
+ UInt64 Files;
+ UInt64 Offset;
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
+ #endif
+
+ MY_QUERYINTERFACE_BEGIN2(IArchiveOpenCallback)
+ MY_QUERYINTERFACE_ENTRY(IArchiveOpenVolumeCallback)
+ #ifndef _NO_CRYPTO
+ MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ INTERFACE_IArchiveOpenCallback(;)
+ INTERFACE_IArchiveOpenVolumeCallback(;)
+ #ifndef _NO_CRYPTO
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+ #endif
+};
+
+#ifndef _NO_CRYPTO
+STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+ if (GetTextPassword)
+ return GetTextPassword->CryptoGetTextPassword(password);
+ return E_NOTIMPL;
+ COM_TRY_END
+}
+#endif
+
+STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes)
+{
+ if (!Callback)
+ return S_OK;
+ UInt64 value = Offset;
+ if (bytes)
+ value += *bytes;
+ return Callback->SetCompleted(&Files, &value);
+}
+
+STDMETHODIMP CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value)
+{
+ if (OpenVolumeCallback)
+ return OpenVolumeCallback->GetProperty(propID, value);
+ NCOM::PropVariant_Clear(value);
+ return S_OK;
+ // return E_NOTIMPL;
+}
+
+STDMETHODIMP CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream)
+{
+ if (OpenVolumeCallback)
+ return OpenVolumeCallback->GetStream(name, inStream);
+ return S_FALSE;
+}
+
+#endif
+
+
+UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)
+{
+ if (isDefinedProp != NULL)
+ *isDefinedProp = false;
+
+ switch (prop.vt)
+ {
+ case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart;
+ case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal;
+ case VT_EMPTY: return 0;
+ default: throw 151199;
+ }
+}
+
+void CArcErrorInfo::ClearErrors()
+{
+ // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!!
+
+ ThereIsTail = false;
+ UnexpecedEnd = false;
+ IgnoreTail = false;
+ // NonZerosTail = false;
+ ErrorFlags_Defined = false;
+ ErrorFlags = 0;
+ WarningFlags = 0;
+ TailSize = 0;
+
+ ErrorMessage.Empty();
+ WarningMessage.Empty();
+}
+
+HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes)
+{
+ // OkPhySize_Defined = false;
+ PhySizeDefined = false;
+ PhySize = 0;
+ Offset = 0;
+ AvailPhySize = FileSize - startPos;
+
+ ErrorInfo.ClearErrors();
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop));
+ ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined);
+ }
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop));
+ ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop);
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidError, &prop));
+ if (prop.vt != VT_EMPTY)
+ 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");
+ }
+
+ if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())
+ {
+ RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySizeDefined));
+ /*
+ RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined));
+ if (!OkPhySize_Defined)
+ {
+ OkPhySize_Defined = PhySizeDefined;
+ OkPhySize = PhySize;
+ }
+ */
+
+ bool offsetDefined;
+ RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined));
+
+ Int64 globalOffset = startPos + Offset;
+ AvailPhySize = FileSize - globalOffset;
+ if (PhySizeDefined)
+ {
+ UInt64 endPos = globalOffset + PhySize;
+ if (endPos < FileSize)
+ {
+ AvailPhySize = PhySize;
+ ErrorInfo.ThereIsTail = true;
+ ErrorInfo.TailSize = FileSize - endPos;
+ }
+ else if (endPos > FileSize)
+ ErrorInfo.UnexpecedEnd = true;
+ }
+ }
+
+ return S_OK;
+}
+
+/*
+static PrintNumber(const char *s, int n)
+{
+ char temp[100];
+ sprintf(temp, "%s %d", s, n);
+ OutputDebugStringA(temp);
+}
+*/
+
+HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive)
+{
+ // OutputDebugStringA("a1");
+ // PrintNumber("formatIndex", formatIndex);
+
+ RINOK(op.codecs->CreateInArchive(formatIndex, archive));
+ // OutputDebugStringA("a2");
+ if (!archive)
+ return S_OK;
+
+ #ifdef EXTERNAL_CODECS
+ if (op.codecs->NeedSetLibCodecs)
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
+ if (ai.LibIndex >= 0 ?
+ !op.codecs->Libs[ai.LibIndex].SetCodecs :
+ !op.codecs->Libs.IsEmpty())
+ {
+ CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
+ archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+ if (setCompressCodecsInfo)
+ {
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs));
+ }
+ }
+ }
+ #endif
+
+
+ #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
+ to open archive, if there is tail after executable (for SFX cases) */
+ CMyComPtr<IArchiveAllowTail> allowTail;
+ archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail);
+ if (allowTail)
+ allowTail->AllowTail(BoolToInt(true));
+ }
+
+ if (op.props)
+ {
+ /*
+ FOR_VECTOR (y, op.props)
+ {
+ const COptionalOpenProperties &optProps = (*op.props)[y];
+ if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0)
+ {
+ RINOK(SetProperties(archive, optProps.Props));
+ break;
+ }
+ }
+ */
+ RINOK(SetProperties(archive, *op.props));
+ }
+
+ #endif
+ return S_OK;
+}
+
+#ifndef _SFX
+
+static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi)
+{
+ pi.Extension = ai.GetMainExt();
+ pi.FileTime_Defined = false;
+ pi.ArcType = ai.Name;
+
+ RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType));
+
+ // RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe));
+ pi.IsSelfExe = ai.Flags_PreArc();
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidMTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ pi.FileTime_Defined = true;
+ pi.FileTime = prop.filetime;
+ }
+ }
+
+ if (!pi.FileTime_Defined)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidCTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ pi.FileTime_Defined = true;
+ pi.FileTime = prop.filetime;
+ }
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidName, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ pi.Name.SetFromBstr(prop.bstrVal);
+ pi.Extension.Empty();
+ }
+ else
+ {
+ RINOK(archive->GetArchiveProperty(kpidExtension, &prop));
+ if (prop.vt == VT_BSTR)
+ pi.Extension.SetFromBstr(prop.bstrVal);
+ }
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidShortComment, &prop));
+ if (prop.vt == VT_BSTR)
+ pi.Comment.SetFromBstr(prop.bstrVal);
+ }
+
+
+ UInt32 numItems;
+ RINOK(archive->GetNumberOfItems(&numItems));
+
+ // pi.NumSubFiles = numItems;
+ // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined));
+ // if (!pi.UnpackSize_Defined)
+ {
+ pi.NumSubFiles = 0;
+ pi.NumSubDirs = 0;
+ pi.UnpackSize = 0;
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ UInt64 size = 0;
+ bool defined = false;
+ Archive_GetItem_Size(archive, i, size, defined);
+ if (defined)
+ {
+ pi.UnpackSize_Defined = true;
+ pi.UnpackSize += size;
+ }
+
+ bool isDir = false;
+ Archive_IsItem_Dir(archive, i, isDir);
+ if (isDir)
+ pi.NumSubDirs++;
+ else
+ pi.NumSubFiles++;
+ }
+ if (pi.NumSubDirs != 0)
+ pi.NumSubDirs_Defined = true;
+ pi.NumSubFiles_Defined = true;
+ }
+
+ return S_OK;
+}
+
+#endif
+
+HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset)
+{
+ if (!op.stream)
+ return S_OK;
+ RINOK(op.stream->Seek(offset, STREAM_SEEK_SET, NULL));
+ const UInt32 kBufSize = 1 << 11;
+ Byte buf[kBufSize];
+
+ for (;;)
+ {
+ UInt32 processed = 0;
+ RINOK(op.stream->Read(buf, kBufSize, &processed));
+ if (processed == 0)
+ {
+ // ErrorInfo.NonZerosTail = false;
+ ErrorInfo.IgnoreTail = true;
+ return S_OK;
+ }
+ for (size_t i = 0; i < processed; i++)
+ {
+ if (buf[i] != 0)
+ {
+ // ErrorInfo.IgnoreTail = false;
+ // ErrorInfo.NonZerosTail = true;
+ return S_OK;
+ }
+ }
+ }
+}
+
+#ifndef _SFX
+
+class CExtractCallback_To_OpenCallback:
+ public IArchiveExtractCallback,
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<IArchiveOpenCallback> Callback;
+ UInt64 Files;
+ UInt64 Offset;
+
+ MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICompressProgressInfo)
+ INTERFACE_IArchiveExtractCallback(;)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+ void Init(IArchiveOpenCallback *callback)
+ {
+ Callback = callback;
+ Files = 0;
+ Offset = 0;
+ }
+};
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ if (Callback)
+ {
+ UInt64 value = Offset;
+ if (inSize)
+ value += *inSize;
+ return Callback->SetCompleted(&Files, &value);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */)
+{
+ *outStream = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */)
+{
+ return S_OK;
+}
+
+static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize,
+ IInStream *stream, const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openCallback,
+ IArchiveExtractCallback *extractCallback)
+{
+ /*
+ if (needPhySize)
+ {
+ CMyComPtr<IArchiveOpen2> open2;
+ archive->QueryInterface(IID_IArchiveOpen2, (void **)&open2);
+ if (open2)
+ return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback);
+ }
+ */
+ RINOK(archive->Open(stream, maxCheckStartPosition, openCallback));
+ if (needPhySize)
+ {
+ bool phySize_Defined = false;
+ UInt64 phySize = 0;
+ RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined));
+ if (phySize_Defined)
+ return S_OK;
+
+ bool phySizeCantBeDetected = false;;
+ RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected));
+
+ if (!phySizeCantBeDetected)
+ {
+ RINOK(archive->Extract(0, (UInt32)(Int32)-1, BoolToInt(true), extractCallback));
+ }
+ }
+ return S_OK;
+}
+
+static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name)
+{
+ FOR_VECTOR (i, orderIndices)
+ if (StringsAreEqualNoCase_Ascii(codecs->Formats[orderIndices[i]].Name, name))
+ return i;
+ return -1;
+}
+
+#endif
+
+HRESULT CArc::OpenStream2(const COpenOptions &op)
+{
+ // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout);
+
+ Archive.Release();
+ GetRawProps.Release();
+ GetRootProps.Release();
+
+ ErrorInfo.ClearErrors();
+ ErrorInfo.ErrorFormatIndex = -1;
+
+ IsParseArc = false;
+ ArcStreamOffset = 0;
+
+ // OutputDebugStringA("1");
+ // OutputDebugStringW(Path);
+
+ const UString fileName = ExtractFileNameFromPath(Path);
+ UString extension;
+ {
+ int dotPos = fileName.ReverseFind_Dot();
+ if (dotPos >= 0)
+ extension = fileName.Ptr(dotPos + 1);
+ }
+
+ CIntVector orderIndices;
+
+ bool searchMarkerInHandler = false;
+ #ifdef _SFX
+ searchMarkerInHandler = true;
+ #endif
+
+ CBoolArr isMainFormatArr(op.codecs->Formats.Size());
+ {
+ FOR_VECTOR(i, op.codecs->Formats)
+ isMainFormatArr[i] = false;
+ }
+
+ UInt64 maxStartOffset =
+ op.openType.MaxStartOffset_Defined ?
+ op.openType.MaxStartOffset :
+ kMaxCheckStartPosition;
+
+ #ifndef _SFX
+ bool isUnknownExt = false;
+ #endif
+
+ bool isForced = false;
+ unsigned numMainTypes = 0;
+ int formatIndex = op.openType.FormatIndex;
+
+ if (formatIndex >= 0)
+ {
+ isForced = true;
+ orderIndices.Add(formatIndex);
+ numMainTypes = 1;
+ isMainFormatArr[(unsigned)formatIndex] = true;
+
+ searchMarkerInHandler = true;
+ }
+ else
+ {
+ unsigned numFinded = 0;
+ #ifndef _SFX
+ bool isPrearcExt = false;
+ #endif
+
+ {
+ #ifndef _SFX
+
+ bool isZip = false;
+ bool isRar = false;
+
+ const wchar_t c = extension[0];
+ if (c == 'z' || c == 'Z' || c == 'r' || c == 'R')
+ {
+ bool isNumber = false;
+ for (unsigned k = 1;; k++)
+ {
+ const wchar_t d = extension[k];
+ if (d == 0)
+ break;
+ if (d < '0' || d > '9')
+ {
+ isNumber = false;
+ break;
+ }
+ isNumber = true;
+ }
+ if (isNumber)
+ if (c == 'z' || c == 'Z')
+ isZip = true;
+ else
+ isRar = true;
+ }
+
+ #endif
+
+ FOR_VECTOR (i, op.codecs->Formats)
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[i];
+
+ if (IgnoreSplit || !op.openType.CanReturnArc)
+ if (ai.IsSplit())
+ continue;
+ if (op.excludedFormats->FindInSorted(i) >= 0)
+ continue;
+
+ #ifndef _SFX
+ if (IsPreArcFormat(ai))
+ isPrearcExt = true;
+ #endif
+
+ if (ai.FindExtension(extension) >= 0
+ #ifndef _SFX
+ || isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip")
+ || isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar")
+ #endif
+ )
+ {
+ // PrintNumber("orderIndices.Insert", i);
+ orderIndices.Insert(numFinded++, i);
+ isMainFormatArr[i] = true;
+ }
+ else
+ orderIndices.Add(i);
+ }
+ }
+
+ if (!op.stream)
+ {
+ if (numFinded != 1)
+ return E_NOTIMPL;
+ orderIndices.DeleteFrom(1);
+ }
+ // PrintNumber("numFinded", numFinded );
+
+ /*
+ if (op.openOnlySpecifiedByExtension)
+ {
+ if (numFinded != 0 && !IsExeExt(extension))
+ orderIndices.DeleteFrom(numFinded);
+ }
+ */
+
+ #ifndef _SFX
+
+ if (op.stream && orderIndices.Size() >= 2)
+ {
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ CByteBuffer byteBuffer;
+ CIntVector orderIndices2;
+ if (numFinded == 0 || IsExeExt(extension))
+ {
+ // signature search was here
+ }
+ else if (extension.IsEqualTo("000") || extension.IsEqualTo("001"))
+ {
+ int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar");
+ if (i >= 0)
+ {
+ const size_t kBufSize = (1 << 10);
+ byteBuffer.Alloc(kBufSize);
+ size_t processedSize = kBufSize;
+ RINOK(ReadStream(op.stream, byteBuffer, &processedSize));
+ if (processedSize >= 16)
+ {
+ const Byte *buf = byteBuffer;
+ const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };
+ if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0)
+ {
+ orderIndices2.Add(orderIndices[i]);
+ orderIndices[i] = -1;
+ if (i >= (int)numFinded)
+ numFinded++;
+ }
+ }
+ }
+ }
+ else
+ {
+ const size_t kBufSize = (1 << 10);
+ byteBuffer.Alloc(kBufSize);
+ size_t processedSize = kBufSize;
+ RINOK(ReadStream(op.stream, byteBuffer, &processedSize));
+ if (processedSize == 0)
+ return S_FALSE;
+
+ /*
+ check type order:
+ 1) matched extension, no signuature
+ 2) matched extension, matched signuature
+ // 3) no signuature
+ // 4) matched signuature
+ */
+
+ MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0);
+ MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize);
+ // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0);
+ // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize);
+ }
+
+ FOR_VECTOR (i, orderIndices)
+ {
+ int val = orderIndices[i];
+ if (val != -1)
+ orderIndices2.Add(val);
+ }
+ orderIndices = orderIndices2;
+ }
+
+ if (orderIndices.Size() >= 2)
+ {
+ int iIso = FindFormatForArchiveType(op.codecs, orderIndices, "iso");
+ int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf");
+ if (iUdf > iIso && iIso >= 0)
+ {
+ int isoIndex = orderIndices[iIso];
+ int udfIndex = orderIndices[iUdf];
+ orderIndices[iUdf] = isoIndex;
+ orderIndices[iIso] = udfIndex;
+ }
+ }
+
+ numMainTypes = numFinded;
+ isUnknownExt = (numMainTypes == 0) || isPrearcExt;
+
+ #else // _SFX
+
+ numMainTypes = orderIndices.Size();
+
+ // we need correct numMainTypes for mutlivolume SFX (if some volume is missing)
+ if (numFinded != 0)
+ numMainTypes = numFinded;
+
+ #endif
+ }
+
+ UInt64 fileSize = 0;
+ if (op.stream)
+ {
+ RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+ FileSize = fileSize;
+
+
+ #ifndef _SFX
+
+ CBoolArr skipFrontalFormat(op.codecs->Formats.Size());
+ {
+ FOR_VECTOR(i, op.codecs->Formats)
+ skipFrontalFormat[i] = false;
+ }
+
+ #endif
+
+ const COpenType &mode = op.openType;
+
+
+
+
+
+ if (mode.CanReturnArc)
+ {
+ // ---------- OPEN main type by extenssion ----------
+
+ unsigned numCheckTypes = orderIndices.Size();
+ if (formatIndex >= 0)
+ numCheckTypes = numMainTypes;
+
+ for (unsigned i = 0; i < numCheckTypes; i++)
+ {
+ FormatIndex = orderIndices[i];
+
+ bool exactOnly = false;
+
+ #ifndef _SFX
+
+ const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
+ // OutputDebugStringW(ai.Name);
+ if (i >= numMainTypes)
+ {
+ if (!ai.Flags_BackwardOpen()
+ // && !ai.Flags_PureStartOpen()
+ )
+ continue;
+ exactOnly = true;
+ }
+
+ #endif
+
+ // Some handlers do not set total bytes. So we set it here
+ if (op.callback)
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+
+ if (op.stream)
+ {
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+
+ CMyComPtr<IInArchive> archive;
+
+ RINOK(PrepareToOpen(op, FormatIndex, archive));
+ if (!archive)
+ continue;
+
+ HRESULT result;
+ if (op.stream)
+ {
+ UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0;
+ result = archive->Open(op.stream, &searchLimit, op.callback);
+ }
+ else
+ {
+ CMyComPtr<IArchiveOpenSeq> openSeq;
+ archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);
+ if (!openSeq)
+ return E_NOTIMPL;
+ result = openSeq->OpenSeq(op.seqStream);
+ }
+
+ RINOK(ReadBasicProps(archive, 0, result));
+
+ if (result == S_FALSE)
+ {
+ bool isArc = ErrorInfo.IsArc_After_NonOpen();
+
+ #ifndef _SFX
+ // if it's archive, we allow another open attempt for parser
+ if (!mode.CanReturnParser || !isArc)
+ skipFrontalFormat[(unsigned)FormatIndex] = true;
+ #endif
+
+ if (exactOnly)
+ continue;
+
+ if (i == 0 && numMainTypes == 1)
+ {
+ // we set NonOpenErrorInfo, only if there is only one main format (defined by extension).
+ ErrorInfo.ErrorFormatIndex = FormatIndex;
+ NonOpen_ErrorInfo = ErrorInfo;
+
+ if (!mode.CanReturnParser && isArc)
+ {
+ // if (formatIndex < 0 && !searchMarkerInHandler)
+ {
+ // if bad archive was detected, we don't need additional open attempts
+ #ifndef _SFX
+ if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */)
+ #endif
+ return S_FALSE;
+ }
+ }
+ }
+
+ /*
+ #ifndef _SFX
+ if (IsExeExt(extension) || ai.Flags_PreArc())
+ {
+ // openOnlyFullArc = false;
+ // canReturnTailArc = true;
+ // limitSignatureSearch = true;
+ }
+ #endif
+ */
+
+ continue;
+ }
+
+ RINOK(result);
+
+ #ifndef _SFX
+
+ bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];
+ const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
+
+ bool thereIsTail = ErrorInfo.ThereIsTail;
+ if (thereIsTail && mode.ZerosTailIsAllowed)
+ {
+ RINOK(CheckZerosTail(op, Offset + PhySize));
+ if (ErrorInfo.IgnoreTail)
+ thereIsTail = false;
+ }
+
+ if (Offset > 0)
+ {
+ if (exactOnly
+ || !searchMarkerInHandler
+ || !specFlags.CanReturn_NonStart()
+ || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset))
+ continue;
+ }
+ if (thereIsTail)
+ {
+ if (Offset > 0)
+ {
+ if (!specFlags.CanReturnMid)
+ continue;
+ }
+ else if (!specFlags.CanReturnFrontal)
+ continue;
+ }
+
+ if (Offset > 0 || thereIsTail)
+ {
+ if (formatIndex < 0)
+ {
+ if (IsPreArcFormat(ai))
+ {
+ // openOnlyFullArc = false;
+ // canReturnTailArc = true;
+ /*
+ if (mode.SkipSfxStub)
+ limitSignatureSearch = true;
+ */
+ // if (mode.SkipSfxStub)
+ {
+ // skipFrontalFormat[FormatIndex] = true;
+ continue;
+ }
+ }
+ }
+ }
+
+ #endif
+
+ Archive = archive;
+ return S_OK;
+ }
+ }
+
+
+
+ #ifndef _SFX
+
+ if (!op.stream)
+ return S_FALSE;
+
+ if (formatIndex >= 0 && !mode.CanReturnParser)
+ {
+ if (mode.MaxStartOffset_Defined)
+ {
+ if (mode.MaxStartOffset == 0)
+ return S_FALSE;
+ }
+ else
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
+ if (ai.FindExtension(extension) >= 0)
+ {
+ if (ai.Flags_FindSignature() && searchMarkerInHandler)
+ return S_FALSE;
+ }
+ }
+ }
+
+ NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler;
+ CMyComPtr<IInArchive> handler = handlerSpec;
+
+ CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec;
+ extractCallback_To_OpenCallback_Spec->Init(op.callback);
+
+ {
+ // ---------- Check all possible START archives ----------
+ // this code is better for full file archives than Parser's code.
+
+ CByteBuffer byteBuffer;
+ bool endOfFile = false;
+ size_t processedSize;
+ {
+ size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF)
+ if (bufSize > fileSize)
+ {
+ bufSize = (size_t)fileSize;
+ endOfFile = true;
+ }
+ byteBuffer.Alloc(bufSize);
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ processedSize = bufSize;
+ RINOK(ReadStream(op.stream, byteBuffer, &processedSize));
+ if (processedSize == 0)
+ return S_FALSE;
+ if (processedSize < bufSize)
+ endOfFile = true;
+ }
+ CUIntVector sortedFormats;
+
+ unsigned i;
+
+ int splitIndex = -1;
+
+ for (i = 0; i < orderIndices.Size(); i++)
+ {
+ unsigned form = orderIndices[i];
+ if (skipFrontalFormat[form])
+ continue;
+ const CArcInfoEx &ai = op.codecs->Formats[form];
+ if (ai.IsSplit())
+ {
+ splitIndex = form;
+ continue;
+ }
+
+ if (ai.IsArcFunc)
+ {
+ UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize);
+ if (isArcRes == k_IsArc_Res_NO)
+ continue;
+ if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)
+ continue;
+ // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue;
+ sortedFormats.Insert(0, form);
+ continue;
+ }
+
+ bool isNewStyleSignature = IsNewStyleSignature(ai);
+ bool needCheck = !isNewStyleSignature
+ || ai.Signatures.IsEmpty()
+ || ai.Flags_PureStartOpen()
+ || ai.Flags_StartOpen()
+ || ai.Flags_BackwardOpen();
+
+ if (isNewStyleSignature && !ai.Signatures.IsEmpty())
+ {
+ unsigned k;
+ for (k = 0; k < ai.Signatures.Size(); k++)
+ {
+ const CByteBuffer &sig = ai.Signatures[k];
+ UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();
+ if (processedSize < signatureEnd)
+ {
+ if (!endOfFile)
+ needCheck = true;
+ }
+ else if (memcmp(sig, byteBuffer + ai.SignatureOffset, sig.Size()) == 0)
+ break;
+ }
+ if (k != ai.Signatures.Size())
+ {
+ sortedFormats.Insert(0, form);
+ continue;
+ }
+ }
+ if (needCheck)
+ sortedFormats.Add(form);
+ }
+
+ if (splitIndex >= 0)
+ sortedFormats.Insert(0, splitIndex);
+
+ for (i = 0; i < sortedFormats.Size(); i++)
+ {
+ FormatIndex = sortedFormats[i];
+ const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
+
+ if (op.callback)
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+
+ CMyComPtr<IInArchive> archive;
+ RINOK(PrepareToOpen(op, FormatIndex, archive));
+ if (!archive)
+ continue;
+
+ PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name));
+ HRESULT result;
+ {
+ UInt64 searchLimit = 0;
+ /*
+ if (mode.CanReturnArc)
+ result = archive->Open(op.stream, &searchLimit, op.callback);
+ else
+ */
+ result = OpenArchiveSpec(archive, !mode.CanReturnArc, op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback);
+ }
+
+ if (result == S_FALSE)
+ {
+ skipFrontalFormat[(unsigned)FormatIndex] = true;
+ // FIXME: maybe we must use LenIsUnknown.
+ // printf(" OpenForSize Error");
+ continue;
+ }
+ RINOK(result);
+
+ RINOK(ReadBasicProps(archive, 0, result));
+
+ if (Offset > 0)
+ {
+ continue; // good handler doesn't return such Offset > 0
+ // but there are some cases like false prefixed PK00 archive, when
+ // we can support it?
+ }
+
+ NArchive::NParser::CParseItem pi;
+ pi.Offset = Offset;
+ pi.Size = AvailPhySize;
+
+ // bool needScan = false;
+
+ if (!PhySizeDefined)
+ {
+ // it's for Z format
+ pi.LenIsUnknown = true;
+ // needScan = true;
+ // phySize = arcRem;
+ // nextNeedCheckStartOpen = false;
+ }
+
+ /*
+ if (OkPhySize_Defined)
+ pi.OkSize = pi.OkPhySize;
+ else
+ pi.OkSize = pi.Size;
+ */
+
+ pi.NormalizeOffset();
+ // printf(" phySize = %8d", (unsigned)phySize);
+
+
+ if (mode.CanReturnArc)
+ {
+ bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];
+ const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
+ bool openCur = false;
+
+ if (!ErrorInfo.ThereIsTail)
+ openCur = true;
+ else
+ {
+ if (mode.ZerosTailIsAllowed)
+ {
+ RINOK(CheckZerosTail(op, Offset + PhySize));
+ if (ErrorInfo.IgnoreTail)
+ openCur = true;
+ }
+ if (!openCur)
+ {
+ openCur = specFlags.CanReturnFrontal;
+ if (formatIndex < 0) // format is not forced
+ {
+ if (IsPreArcFormat(ai))
+ {
+ // if (mode.SkipSfxStub)
+ {
+ openCur = false;
+ }
+ }
+ }
+ }
+ }
+
+ if (openCur)
+ {
+ InStream = op.stream;
+ Archive = archive;
+ return S_OK;
+ }
+ }
+
+ skipFrontalFormat[(unsigned)FormatIndex] = true;
+
+
+ // if (!mode.CanReturnArc)
+ /*
+ if (!ErrorInfo.ThereIsTail)
+ continue;
+ */
+ if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)
+ continue;
+
+ // printf("\nAdd offset = %d", (int)pi.Offset);
+ RINOK(ReadParseItemProps(archive, ai, pi));
+ handlerSpec->AddItem(pi);
+ }
+ }
+
+
+
+
+
+ // ---------- PARSER ----------
+
+ CUIntVector arc2sig; // formatIndex to signatureIndex
+ CUIntVector sig2arc; // signatureIndex to formatIndex;
+ {
+ unsigned sum = 0;
+ FOR_VECTOR (i, op.codecs->Formats)
+ {
+ arc2sig.Add(sum);
+ const CObjectVector<CByteBuffer> &sigs = op.codecs->Formats[i].Signatures;
+ sum += sigs.Size();
+ FOR_VECTOR (k, sigs)
+ sig2arc.Add(i);
+ }
+ }
+
+ {
+ const size_t kBeforeSize = 1 << 16;
+ const size_t kAfterSize = 1 << 20;
+ const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize
+
+ const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8);
+ CByteArr hashBuffer(kNumVals);
+ Byte *hash = hashBuffer;
+ memset(hash, 0xFF, kNumVals);
+ Byte prevs[256];
+ memset(prevs, 0xFF, sizeof(prevs));
+ if (sig2arc.Size() >= 0xFF)
+ return S_FALSE;
+
+ CUIntVector difficultFormats;
+ CBoolArr difficultBools(256);
+ {
+ for (unsigned i = 0; i < 256; i++)
+ difficultBools[i] = false;
+ }
+
+ bool thereAreHandlersForSearch = false;
+
+ // UInt32 maxSignatureEnd = 0;
+
+ FOR_VECTOR (i, orderIndices)
+ {
+ int index = orderIndices[i];
+ if (index < 0)
+ continue;
+ const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index];
+ bool isDifficult = false;
+ // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31)
+ if (!ai.NewInterface)
+ isDifficult = true;
+ else
+ {
+ if (ai.Flags_StartOpen())
+ isDifficult = true;
+ FOR_VECTOR (k, ai.Signatures)
+ {
+ const CByteBuffer &sig = ai.Signatures[k];
+ /*
+ UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();
+ if (maxSignatureEnd < signatureEnd)
+ maxSignatureEnd = signatureEnd;
+ */
+ if (sig.Size() < kNumHashBytes)
+ {
+ isDifficult = true;
+ continue;
+ }
+ thereAreHandlersForSearch = true;
+ UInt32 v = HASH_VAL(sig);
+ unsigned sigIndex = arc2sig[(unsigned)index] + k;
+ prevs[sigIndex] = hash[v];
+ hash[v] = (Byte)sigIndex;
+ }
+ }
+ if (isDifficult)
+ {
+ difficultFormats.Add(index);
+ difficultBools[(unsigned)index] = true;
+ }
+ }
+
+ if (!thereAreHandlersForSearch)
+ {
+ // openOnlyFullArc = true;
+ // canReturnTailArc = true;
+ }
+
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+
+ CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream;
+ CMyComPtr<IInStream> limitedStream = limitedStreamSpec;
+ limitedStreamSpec->SetStream(op.stream);
+
+ CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL;
+ CMyComPtr<IArchiveOpenCallback> openCallback_Offset;
+ if (op.callback)
+ {
+ openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
+ openCallback_Offset = openCallback_Offset_Spec;
+ openCallback_Offset_Spec->Callback = op.callback;
+ openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback);
+ #ifndef _NO_CRYPTO
+ openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);
+ #endif
+ }
+
+ if (op.callback)
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+
+ CByteBuffer &byteBuffer = limitedStreamSpec->Buffer;
+ byteBuffer.Alloc(kBufSize);
+
+ UInt64 callbackPrev = 0;
+ bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos.
+
+ bool endOfFile = false;
+ UInt64 bufPhyPos = 0;
+ size_t bytesInBuf = 0;
+ // UInt64 prevPos = 0;
+
+ // ---------- Main Scan Loop ----------
+
+ UInt64 pos = 0;
+
+ if (!mode.EachPos && handlerSpec->_items.Size() == 1)
+ {
+ NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];
+ if (!pi.LenIsUnknown && pi.Offset == 0)
+ pos = pi.Size;
+ }
+
+ for (;;)
+ {
+ // printf("\nPos = %d", (int)pos);
+ UInt64 posInBuf = pos - bufPhyPos;
+
+ // if (pos > ((UInt64)1 << 35)) break;
+
+ if (!endOfFile)
+ {
+ if (bytesInBuf < kBufSize)
+ {
+ size_t processedSize = kBufSize - bytesInBuf;
+ // printf("\nRead ask = %d", (unsigned)processedSize);
+ UInt64 seekPos = bufPhyPos + bytesInBuf;
+ RINOK(op.stream->Seek(bufPhyPos + bytesInBuf, STREAM_SEEK_SET, NULL));
+ RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize));
+ // printf(" processed = %d", (unsigned)processedSize);
+ if (processedSize == 0)
+ {
+ fileSize = seekPos;
+ endOfFile = true;
+ }
+ else
+ {
+ bytesInBuf += processedSize;
+ limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos);
+ }
+ continue;
+ }
+
+ if (bytesInBuf < posInBuf)
+ {
+ UInt64 skipSize = posInBuf - bytesInBuf;
+ if (skipSize <= kBeforeSize)
+ {
+ size_t keepSize = (size_t)(kBeforeSize - skipSize);
+ // printf("\nmemmove skip = %d", (int)keepSize);
+ memmove(byteBuffer, byteBuffer + bytesInBuf - keepSize, keepSize);
+ bytesInBuf = keepSize;
+ bufPhyPos = pos - keepSize;
+ continue;
+ }
+ // printf("\nSkip %d", (int)(skipSize - kBeforeSize));
+ // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL));
+ bytesInBuf = 0;
+ bufPhyPos = pos - kBeforeSize;
+ continue;
+ }
+
+ if (bytesInBuf - posInBuf < kAfterSize)
+ {
+ size_t beg = (size_t)posInBuf - kBeforeSize;
+ // printf("\nmemmove for after beg = %d", (int)beg);
+ memmove(byteBuffer, byteBuffer + beg, bytesInBuf - beg);
+ bufPhyPos += beg;
+ bytesInBuf -= beg;
+ continue;
+ }
+ }
+
+ if (bytesInBuf <= (size_t)posInBuf)
+ break;
+
+ bool useOffsetCallback = false;
+ if (openCallback_Offset)
+ {
+ openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
+ openCallback_Offset_Spec->Offset = pos;
+
+ useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1);
+
+ if (pos >= callbackPrev + (1 << 23))
+ {
+ RINOK(openCallback_Offset_Spec->SetCompleted(NULL, NULL));
+ callbackPrev = pos;
+ }
+ }
+
+ {
+ UInt64 endPos = bufPhyPos + bytesInBuf;
+ if (fileSize < endPos)
+ {
+ FileSize = fileSize; // why ????
+ fileSize = endPos;
+ }
+ }
+
+ size_t availSize = bytesInBuf - (size_t)posInBuf;
+ if (availSize < kNumHashBytes)
+ break;
+ size_t scanSize = availSize -
+ ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes);
+
+ {
+ /*
+ UInt64 scanLimit = openOnlyFullArc ?
+ maxSignatureEnd :
+ op.openType.ScanSize + maxSignatureEnd;
+ */
+ if (!mode.CanReturnParser)
+ {
+ if (pos > maxStartOffset)
+ break;
+ UInt64 remScan = maxStartOffset - pos;
+ if (scanSize > remScan)
+ scanSize = (size_t)remScan;
+ }
+ }
+
+ scanSize++;
+
+ const Byte *buf = byteBuffer + (size_t)posInBuf;
+ const Byte *bufLimit = buf + scanSize;
+ size_t ppp = 0;
+
+ if (!needCheckStartOpen)
+ {
+ for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++);
+ ppp = buf - (byteBuffer + (size_t)posInBuf);
+ pos += ppp;
+ if (buf == bufLimit)
+ continue;
+ }
+
+ UInt32 v = HASH_VAL(buf);
+ bool nextNeedCheckStartOpen = true;
+ unsigned i = hash[v];
+ unsigned indexOfDifficult = 0;
+
+ // ---------- Open Loop for Current Pos ----------
+ bool wasOpen = false;
+
+ for (;;)
+ {
+ unsigned index;
+ bool isDifficult;
+ if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size())
+ {
+ index = difficultFormats[indexOfDifficult++];
+ isDifficult = true;
+ }
+ else
+ {
+ if (i == 0xFF)
+ break;
+ index = sig2arc[i];
+ unsigned sigIndex = i - arc2sig[index];
+ i = prevs[i];
+ if (needCheckStartOpen && difficultBools[index])
+ continue;
+ const CArcInfoEx &ai = op.codecs->Formats[index];
+
+ if (pos < ai.SignatureOffset)
+ continue;
+
+ /*
+ if (openOnlyFullArc)
+ if (pos != ai.SignatureOffset)
+ continue;
+ */
+
+ const CByteBuffer &sig = ai.Signatures[sigIndex];
+
+ if (ppp + sig.Size() > availSize
+ || !TestSignature(buf, sig, sig.Size()))
+ continue;
+ // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos));
+ // prevPos = pos;
+ isDifficult = false;
+ }
+
+ const CArcInfoEx &ai = op.codecs->Formats[index];
+
+
+ if ((isDifficult && pos == 0) || ai.SignatureOffset == pos)
+ {
+ // we don't check same archive second time */
+ if (skipFrontalFormat[index])
+ continue;
+ }
+
+ UInt64 startArcPos = pos;
+ if (!isDifficult)
+ {
+ if (pos < ai.SignatureOffset)
+ continue;
+ startArcPos = pos - ai.SignatureOffset;
+ /*
+ // we don't need the check for Z files
+ if (startArcPos < handlerSpec->GetLastEnd())
+ continue;
+ */
+ }
+
+ if (ai.IsArcFunc && startArcPos >= bufPhyPos)
+ {
+ size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos);
+ if (offsetInBuf < bytesInBuf)
+ {
+ UInt32 isArcRes = ai.IsArcFunc(byteBuffer + offsetInBuf, bytesInBuf - offsetInBuf);
+ if (isArcRes == k_IsArc_Res_NO)
+ continue;
+ if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)
+ continue;
+ /*
+ if (isArcRes == k_IsArc_Res_YES_LOW_PROB)
+ {
+ // if (pos != ai.SignatureOffset)
+ continue;
+ }
+ */
+ }
+ // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name);
+ }
+
+ /*
+ if (pos == 67109888)
+ pos = pos;
+ */
+ PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name));
+
+ bool isMainFormat = isMainFormatArr[index];
+ const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
+
+ CMyComPtr<IInArchive> archive;
+ RINOK(PrepareToOpen(op, index, archive));
+ if (!archive)
+ return E_FAIL;
+
+ // OutputDebugStringW(ai.Name);
+
+ UInt64 rem = fileSize - startArcPos;
+
+ UInt64 arcStreamOffset = 0;
+
+ if (ai.Flags_UseGlobalOffset())
+ {
+ limitedStreamSpec->InitAndSeek(0, fileSize);
+ limitedStream->Seek(startArcPos, STREAM_SEEK_SET, NULL);
+ }
+ else
+ {
+ limitedStreamSpec->InitAndSeek(startArcPos, rem);
+ arcStreamOffset = startArcPos;
+ }
+
+ UInt64 maxCheckStartPosition = 0;
+
+ if (openCallback_Offset)
+ {
+ openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
+ openCallback_Offset_Spec->Offset = startArcPos;
+ }
+
+ // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);
+ extractCallback_To_OpenCallback_Spec->Files = 0;
+ extractCallback_To_OpenCallback_Spec->Offset = startArcPos;
+
+ HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition,
+ useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback,
+ extractCallback_To_OpenCallback);
+
+ RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result));
+
+ bool isOpen = false;
+ if (result == S_FALSE)
+ {
+ if (!mode.CanReturnParser)
+ {
+ if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen())
+ {
+ ErrorInfo.ErrorFormatIndex = index;
+ NonOpen_ErrorInfo = ErrorInfo;
+ // if archive was detected, we don't need additional open attempts
+ return S_FALSE;
+ }
+ continue;
+ }
+ if (!ErrorInfo.IsArc_After_NonOpen() || !PhySizeDefined || PhySize == 0)
+ continue;
+ }
+ else
+ {
+ isOpen = true;
+ RINOK(result);
+ PRF(printf(" OK "));
+ }
+
+ // fprintf(stderr, "\n %8X %S", startArcPos, Path);
+ // printf("\nOpen OK: %S", ai.Name);
+
+
+ NArchive::NParser::CParseItem pi;
+ pi.Offset = startArcPos;
+
+ if (ai.Flags_UseGlobalOffset())
+ pi.Offset = Offset;
+ else if (Offset != 0)
+ return E_FAIL;
+ UInt64 arcRem = FileSize - pi.Offset;
+ UInt64 phySize = arcRem;
+ bool phySizeDefined = PhySizeDefined;
+ if (phySizeDefined)
+ {
+ if (pi.Offset + PhySize > FileSize)
+ {
+ // ErrorInfo.ThereIsTail = true;
+ PhySize = FileSize - pi.Offset;
+ }
+ phySize = PhySize;
+ }
+ if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63))
+ return E_FAIL;
+
+ /*
+ if (!ai.UseGlobalOffset)
+ {
+ if (phySize > arcRem)
+ {
+ ThereIsTail = true;
+ phySize = arcRem;
+ }
+ }
+ */
+
+ bool needScan = false;
+
+
+ if (isOpen && !phySizeDefined)
+ {
+ // it's for Z format
+ pi.LenIsUnknown = true;
+ needScan = true;
+ phySize = arcRem;
+ nextNeedCheckStartOpen = false;
+ }
+
+ pi.Size = phySize;
+ /*
+ if (OkPhySize_Defined)
+ pi.OkSize = OkPhySize;
+ */
+ pi.NormalizeOffset();
+ // printf(" phySize = %8d", (unsigned)phySize);
+
+ /*
+ if (needSkipFullArc)
+ if (pi.Offset == 0 && phySizeDefined && pi.Size >= fileSize)
+ continue;
+ */
+ if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)
+ {
+ // it's possible for dmg archives
+ if (!mode.CanReturnArc)
+ continue;
+ }
+
+ if (mode.EachPos)
+ pos++;
+ else if (needScan)
+ {
+ pos++;
+ /*
+ if (!OkPhySize_Defined)
+ pos++;
+ else
+ pos = pi.Offset + pi.OkSize;
+ */
+ }
+ else
+ pos = pi.Offset + pi.Size;
+
+
+ RINOK(ReadParseItemProps(archive, ai, pi));
+
+ if (pi.Offset < startArcPos && !mode.EachPos /* && phySizeDefined */)
+ {
+ /* It's for DMG format.
+ This code deletes all previous items that are included to current item */
+
+ while (!handlerSpec->_items.IsEmpty())
+ {
+ {
+ const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back();
+ if (back.Offset < pi.Offset)
+ break;
+ if (back.Offset + back.Size > pi.Offset + pi.Size)
+ break;
+ }
+ handlerSpec->_items.DeleteBack();
+ }
+ }
+
+
+ if (isOpen && mode.CanReturnArc && phySizeDefined)
+ {
+ // if (pi.Offset + pi.Size >= fileSize)
+ bool openCur = false;
+
+ bool thereIsTail = ErrorInfo.ThereIsTail;
+ if (thereIsTail && mode.ZerosTailIsAllowed)
+ {
+ RINOK(CheckZerosTail(op, arcStreamOffset + Offset + PhySize));
+ if (ErrorInfo.IgnoreTail)
+ thereIsTail = false;
+ }
+
+ if (pi.Offset != 0)
+ {
+ if (!pi.IsNotArcType)
+ if (thereIsTail)
+ openCur = specFlags.CanReturnMid;
+ else
+ openCur = specFlags.CanReturnTail;
+ }
+ else
+ {
+ if (!thereIsTail)
+ openCur = true;
+ else
+ openCur = specFlags.CanReturnFrontal;
+
+
+ if (formatIndex >= -2)
+ openCur = true;
+ }
+ if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */)
+ openCur = false;
+
+ // We open file as SFX, if there is front archive or first archive is "Self Executable"
+ if (!openCur && !pi.IsSelfExe && !thereIsTail &&
+ (!pi.IsNotArcType || pi.Offset == 0))
+ {
+ if (handlerSpec->_items.IsEmpty())
+ {
+ if (specFlags.CanReturnTail)
+ openCur = true;
+ }
+ else if (handlerSpec->_items.Size() == 1)
+ {
+ if (handlerSpec->_items[0].IsSelfExe)
+ {
+ if (mode.SpecUnknownExt.CanReturnTail)
+ openCur = true;
+ }
+ }
+ }
+
+ if (openCur)
+ {
+ InStream = op.stream;
+ Archive = archive;
+ FormatIndex = index;
+ ArcStreamOffset = arcStreamOffset;
+ return S_OK;
+ }
+ }
+
+ /*
+ if (openOnlyFullArc)
+ {
+ ErrorInfo.ClearErrors();
+ return S_FALSE;
+ }
+ */
+
+ pi.FormatIndex = index;
+
+ // printf("\nAdd offset = %d", (int)pi.Offset);
+ handlerSpec->AddItem(pi);
+ wasOpen = true;
+ break;
+ }
+ // ---------- End of Open Loop for Current Pos ----------
+
+ if (!wasOpen)
+ pos++;
+ needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen);
+ }
+ // ---------- End of Main Scan Loop ----------
+
+ /*
+ if (handlerSpec->_items.Size() == 1)
+ {
+ const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];
+ if (pi.Size == fileSize && pi.Offset == 0)
+ {
+ Archive = archive;
+ FormatIndex2 = pi.FormatIndex;
+ return S_OK;
+ }
+ }
+ */
+
+ if (mode.CanReturnParser)
+ {
+ bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing
+ handlerSpec->AddUnknownItem(fileSize);
+ if (handlerSpec->_items.Size() == 0)
+ return S_FALSE;
+ if (returnParser || handlerSpec->_items.Size() != 1)
+ {
+ // return S_FALSE;
+ handlerSpec->_stream = op.stream;
+ Archive = handler;
+ ErrorInfo.ClearErrors();
+ IsParseArc = true;
+ FormatIndex = -1; // It's parser
+ Offset = 0;
+ return S_OK;
+ }
+ }
+ }
+
+ #endif
+
+ if (!Archive)
+ return S_FALSE;
+ return S_OK;
+}
+
+HRESULT CArc::OpenStream(const COpenOptions &op)
+{
+ RINOK(OpenStream2(op));
+ // PrintNumber("op.formatIndex 3", op.formatIndex);
+
+ if (Archive)
+ {
+ GetRawProps.Release();
+ GetRootProps.Release();
+ Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps);
+ Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps);
+
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted));
+ 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_Dot();
+ if (dotPos >= 0)
+ extension = fileName.Ptr(dotPos + 1);
+ }
+
+ DefaultName.Empty();
+ if (FormatIndex >= 0)
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
+ if (ai.Exts.Size() == 0)
+ DefaultName = GetDefaultName2(fileName, UString(), UString());
+ else
+ {
+ int subExtIndex = ai.FindExtension(extension);
+ if (subExtIndex < 0)
+ subExtIndex = 0;
+ const CArcExtInfo &extInfo = ai.Exts[subExtIndex];
+ DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+#ifdef _SFX
+
+#ifdef _WIN32
+ #define k_ExeExt ".exe"
+ static const unsigned k_ExeExt_Len = 4;
+#else
+ #define k_ExeExt ""
+ static const unsigned k_ExeExt_Len = 0;
+#endif
+
+#endif
+
+HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
+{
+ CMyComPtr<IInStream> fileStream;
+ CMyComPtr<ISequentialInStream> seqStream;
+ CInFileStream *fileStreamSpec = NULL;
+
+ if (op.stdInMode)
+ {
+ seqStream = new CStdInFileStream;
+ op.seqStream = seqStream;
+ }
+ else if (!op.stream)
+ {
+ fileStreamSpec = new CInFileStream;
+ fileStream = fileStreamSpec;
+ Path = filePath;
+ if (!fileStreamSpec->Open(us2fs(Path)))
+ {
+ return GetLastError();
+ }
+ op.stream = fileStream;
+ #ifdef _SFX
+ IgnoreSplit = true;
+ #endif
+ }
+
+ /*
+ if (callback)
+ {
+ UInt64 fileSize;
+ RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ RINOK(op.callback->SetTotal(NULL, &fileSize))
+ }
+ */
+
+ HRESULT res = OpenStream(op);
+ IgnoreSplit = false;
+
+ #ifdef _SFX
+
+ if (res != S_FALSE
+ || !fileStreamSpec
+ || !op.callbackSpec
+ || NonOpen_ErrorInfo.IsArc_After_NonOpen())
+ return res;
+
+ {
+ if (filePath.Len() > k_ExeExt_Len
+ && 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)
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[i];
+ if (ai.IsSplit())
+ continue;
+ UString path3 = path2;
+ path3 += '.';
+ path3 += ai.GetMainExt(); // "7z" for SFX.
+ Path = path3;
+ Path += ".001";
+ bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));
+ if (!isOk)
+ {
+ Path = path3;
+ isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));
+ }
+ if (isOk)
+ {
+ if (fileStreamSpec->Open(us2fs(Path)))
+ {
+ op.stream = fileStream;
+ NonOpen_ErrorInfo.ClearErrors_Full();
+ if (OpenStream(op) == S_OK)
+ return S_OK;
+ }
+ }
+ }
+ }
+ }
+
+ #endif
+
+ return res;
+}
+
+void CArchiveLink::KeepModeForNextOpen()
+{
+ for (unsigned i = Arcs.Size(); i != 0;)
+ {
+ i--;
+ CMyComPtr<IArchiveKeepModeForNextOpen> keep;
+ Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep);
+ if (keep)
+ keep->KeepModeForNextOpen();
+ }
+}
+
+HRESULT CArchiveLink::Close()
+{
+ for (unsigned i = Arcs.Size(); i != 0;)
+ {
+ i--;
+ RINOK(Arcs[i].Close());
+ }
+ IsOpen = false;
+ // ErrorsText.Empty();
+ return S_OK;
+}
+
+void CArchiveLink::Release()
+{
+ // NonOpenErrorFormatIndex = -1;
+ NonOpen_ErrorInfo.ClearErrors();
+ NonOpen_ArcPath.Empty();
+ while (!Arcs.IsEmpty())
+ Arcs.DeleteBack();
+}
+
+/*
+void CArchiveLink::Set_ErrorsText()
+{
+ FOR_VECTOR(i, Arcs)
+ {
+ const CArc &arc = Arcs[i];
+ if (!arc.ErrorFlagsText.IsEmpty())
+ {
+ if (!ErrorsText.IsEmpty())
+ ErrorsText.Add_LF();
+ ErrorsText += GetUnicodeString(arc.ErrorFlagsText);
+ }
+ if (!arc.ErrorMessage.IsEmpty())
+ {
+ if (!ErrorsText.IsEmpty())
+ ErrorsText.Add_LF();
+ ErrorsText += arc.ErrorMessage;
+ }
+
+ if (!arc.WarningMessage.IsEmpty())
+ {
+ if (!ErrorsText.IsEmpty())
+ ErrorsText.Add_LF();
+ ErrorsText += arc.WarningMessage;
+ }
+ }
+}
+*/
+
+HRESULT CArchiveLink::Open(COpenOptions &op)
+{
+ Release();
+ if (op.types->Size() >= 32)
+ return E_NOTIMPL;
+
+ HRESULT resSpec;
+
+ for (;;)
+ {
+ resSpec = S_OK;
+
+ op.openType = COpenType();
+ if (op.types->Size() >= 1)
+ {
+ COpenType latest;
+ if (Arcs.Size() < op.types->Size())
+ latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];
+ else
+ {
+ latest = (*op.types)[0];
+ if (!latest.Recursive)
+ break;
+ }
+ op.openType = latest;
+ }
+ else if (Arcs.Size() >= 32)
+ break;
+
+ /*
+ op.formatIndex = -1;
+ if (op.types->Size() >= 1)
+ {
+ int latest;
+ if (Arcs.Size() < op.types->Size())
+ latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];
+ else
+ {
+ latest = (*op.types)[0];
+ if (latest != -2 && latest != -3)
+ break;
+ }
+ if (latest >= 0)
+ op.formatIndex = latest;
+ else if (latest == -1 || latest == -2)
+ {
+ // default
+ }
+ else if (latest == -3)
+ op.formatIndex = -2;
+ else
+ op.formatIndex = latest + 2;
+ }
+ else if (Arcs.Size() >= 32)
+ break;
+ */
+
+ if (Arcs.IsEmpty())
+ {
+ CArc arc;
+ arc.filePath = op.filePath;
+ arc.Path = op.filePath;
+ arc.SubfileIndex = (UInt32)(Int32)-1;
+ HRESULT result = arc.OpenStreamOrFile(op);
+ if (result != S_OK)
+ {
+ if (result == S_FALSE)
+ {
+ NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo;
+ // NonOpenErrorFormatIndex = arc.ErrorFormatIndex;
+ NonOpen_ArcPath = arc.Path;
+ }
+ return result;
+ }
+ Arcs.Add(arc);
+ continue;
+ }
+
+ // PrintNumber("op.formatIndex 11", op.formatIndex);
+
+ const CArc &arc = Arcs.Back();
+
+ if (op.types->Size() > Arcs.Size())
+ resSpec = E_NOTIMPL;
+
+ UInt32 mainSubfile;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop));
+ if (prop.vt == VT_UI4)
+ mainSubfile = prop.ulVal;
+ else
+ break;
+ UInt32 numItems;
+ RINOK(arc.Archive->GetNumberOfItems(&numItems));
+ if (mainSubfile >= numItems)
+ break;
+ }
+
+
+ CMyComPtr<IInArchiveGetStream> getStream;
+ if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream)
+ break;
+
+ CMyComPtr<ISequentialInStream> subSeqStream;
+ if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream)
+ break;
+
+ CMyComPtr<IInStream> subStream;
+ if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream)
+ break;
+
+ CArc arc2;
+ RINOK(arc.GetItemPath(mainSubfile, arc2.Path));
+
+ bool zerosTailIsAllowed;
+ RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed));
+
+
+ if (op.callback)
+ {
+ CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
+ op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
+ if (setSubArchiveName)
+ setSubArchiveName->SetSubArchiveName(arc2.Path);
+ }
+
+ arc2.SubfileIndex = mainSubfile;
+
+ // CIntVector incl;
+ CIntVector excl;
+
+ COpenOptions op2;
+ #ifndef _SFX
+ op2.props = op.props;
+ #endif
+ op2.codecs = op.codecs;
+ // op2.types = &incl;
+ op2.openType = op.openType;
+ op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed;
+ op2.excludedFormats = &excl;
+ op2.stdInMode = false;
+ op2.stream = subStream;
+ op2.filePath = arc2.Path;
+ op2.callback = op.callback;
+ op2.callbackSpec = op.callbackSpec;
+
+
+ HRESULT result = arc2.OpenStream(op2);
+ resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE);
+ if (result == S_FALSE)
+ {
+ NonOpen_ErrorInfo = arc2.ErrorInfo;
+ NonOpen_ArcPath = arc2.Path;
+ break;
+ }
+ RINOK(result);
+ RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));
+ Arcs.Add(arc2);
+ }
+ IsOpen = !Arcs.IsEmpty();
+ return resSpec;
+}
+
+HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI)
+{
+ VolumesSize = 0;
+ COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
+ CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec;
+ openCallbackSpec->Callback = callbackUI;
+
+ FString prefix, name;
+
+ if (!op.stream && !op.stdInMode)
+ {
+ NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name);
+ openCallbackSpec->Init(prefix, name);
+ }
+ else
+ {
+ openCallbackSpec->SetSubArchiveName(op.filePath);
+ }
+
+ op.callback = callback;
+ op.callbackSpec = openCallbackSpec;
+
+ HRESULT res = Open(op);
+
+ PasswordWasAsked = openCallbackSpec->PasswordWasAsked;
+ // Password = openCallbackSpec->Password;
+
+ RINOK(res);
+ // VolumePaths.Add(fs2us(prefix + name));
+
+ FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed)
+ {
+ if (openCallbackSpec->FileNames_WasUsed[i])
+ {
+ VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]);
+ VolumesSize += openCallbackSpec->FileSizes[i];
+ }
+ }
+ // VolumesSize = openCallbackSpec->TotalSize;
+ return S_OK;
+}
+
+HRESULT CArc::ReOpen(const COpenOptions &op)
+{
+ ErrorInfo.ClearErrors();
+ ErrorInfo.ErrorFormatIndex = -1;
+
+ UInt64 fileSize = 0;
+ if (op.stream)
+ {
+ RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+ FileSize = fileSize;
+
+ CMyComPtr<IInStream> stream2;
+ Int64 globalOffset = GetGlobalOffset();
+ if (globalOffset <= 0)
+ stream2 = op.stream;
+ else
+ {
+ CTailInStream *tailStreamSpec = new CTailInStream;
+ stream2 = tailStreamSpec;
+ tailStreamSpec->Stream = op.stream;
+ tailStreamSpec->Offset = globalOffset;
+ tailStreamSpec->Init();
+ RINOK(tailStreamSpec->SeekToStart());
+ }
+
+ // There are archives with embedded STUBs (like ZIP), so we must support signature scanning
+ // But for another archives we can use 0 here. So the code can be fixed !!!
+ UInt64 maxStartPosition = kMaxCheckStartPosition;
+ HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback);
+
+ if (res == S_OK)
+ {
+ RINOK(ReadBasicProps(Archive, globalOffset, res));
+ ArcStreamOffset = globalOffset;
+ if (ArcStreamOffset != 0)
+ InStream = op.stream;
+ }
+ 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)
+{
+ if (Arcs.Size() > 1)
+ return E_NOTIMPL;
+
+ CObjectVector<COpenType> inc;
+ CIntVector excl;
+
+ op.types = &inc;
+ op.excludedFormats = &excl;
+ op.stdInMode = false;
+ op.stream = NULL;
+ if (Arcs.Size() == 0) // ???
+ return Open2(op, NULL);
+
+ 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);
+ if (!fileStreamSpec->Open(us2fs(op.filePath)))
+ return GetLastError();
+ op.stream = stream;
+
+ CArc &arc = Arcs[0];
+ HRESULT res = arc.ReOpen(op);
+
+ PasswordWasAsked = openCallbackSpec->PasswordWasAsked;
+ // Password = openCallbackSpec->Password;
+
+ IsOpen = (res == S_OK);
+ return res;
+}
+
+#ifndef _SFX
+
+bool ParseComplexSize(const wchar_t *s, UInt64 &result)
+{
+ result = 0;
+ const wchar_t *end;
+ UInt64 number = ConvertStringToUInt64(s, &end);
+ if (end == s)
+ return false;
+ if (*end == 0)
+ {
+ result = number;
+ return true;
+ }
+ if (end[1] != 0)
+ return false;
+ unsigned numBits;
+ switch (MyCharLower_Ascii(*end))
+ {
+ case 'b': result = number; return true;
+ case 'k': numBits = 10; break;
+ case 'm': numBits = 20; break;
+ case 'g': numBits = 30; break;
+ case 't': numBits = 40; break;
+ default: return false;
+ }
+ if (number >= ((UInt64)1 << (64 - numBits)))
+ return false;
+ result = number << numBits;
+ return true;
+}
+
+static bool ParseTypeParams(const UString &s, COpenType &type)
+{
+ if (s[0] == 0)
+ return true;
+ if (s[1] == 0)
+ {
+ switch ((unsigned)(Byte)s[0])
+ {
+ case 'e': type.EachPos = true; return true;
+ case 'a': type.CanReturnArc = true; return true;
+ case 'r': type.Recursive = true; return true;
+ }
+ return false;
+ }
+ if (s[0] == 's')
+ {
+ UInt64 result;
+ if (!ParseComplexSize(s.Ptr(1), result))
+ return false;
+ type.MaxStartOffset = result;
+ type.MaxStartOffset_Defined = true;
+ return true;
+ }
+
+ return false;
+}
+
+bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
+{
+ int pos2 = s.Find(L':');
+
+ {
+ UString name;
+ if (pos2 < 0)
+ {
+ name = s;
+ pos2 = s.Len();
+ }
+ else
+ {
+ name = s.Left(pos2);
+ pos2++;
+ }
+
+ int index = codecs.FindFormatForArchiveType(name);
+ type.Recursive = false;
+
+ if (index < 0)
+ {
+ if (name[0] == '*')
+ {
+ if (name[1] != 0)
+ return false;
+ }
+ else if (name[0] == '#')
+ {
+ if (name[1] != 0)
+ return false;
+ type.CanReturnArc = false;
+ type.CanReturnParser = true;
+ }
+ else
+ return false;
+ }
+
+ type.FormatIndex = index;
+
+ }
+
+ for (unsigned i = pos2; i < s.Len();)
+ {
+ int next = s.Find(L':', i);
+ if (next < 0)
+ next = s.Len();
+ const UString name = s.Mid(i, next - i);
+ if (name.IsEmpty())
+ return false;
+ if (!ParseTypeParams(name, type))
+ return false;
+ i = next + 1;
+ }
+
+ return true;
+}
+
+bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types)
+{
+ types.Clear();
+ for (unsigned pos = 0; pos < s.Len();)
+ {
+ int pos2 = s.Find(L'.', pos);
+ if (pos2 < 0)
+ pos2 = s.Len();
+ UString name = s.Mid(pos, pos2 - pos);
+ if (name.IsEmpty())
+ return false;
+ COpenType type;
+ if (!ParseType(codecs, name, type))
+ return false;
+ types.Add(type);
+ pos = pos2 + 1;
+ }
+ return true;
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.h
new file mode 100644
index 0000000000..033cb960f3
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.h
@@ -0,0 +1,436 @@
+// OpenArchive.h
+
+#ifndef __OPEN_ARCHIVE_H
+#define __OPEN_ARCHIVE_H
+
+#include "../../../Windows/PropVariant.h"
+
+#include "ArchiveOpenCallback.h"
+#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_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
+{
+ UString FormatName;
+ CObjectVector<CProperty> Props;
+};
+*/
+
+#ifdef _SFX
+#define OPEN_PROPS_DECL
+#else
+#define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
+// #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
+#endif
+
+struct COpenSpecFlags
+{
+ // bool CanReturnFull;
+ bool CanReturnFrontal;
+ bool CanReturnTail;
+ bool CanReturnMid;
+
+ bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
+
+ COpenSpecFlags():
+ // CanReturnFull(true),
+ CanReturnFrontal(false),
+ CanReturnTail(false),
+ CanReturnMid(false)
+ {}
+};
+
+struct COpenType
+{
+ int FormatIndex;
+
+ COpenSpecFlags SpecForcedType;
+ COpenSpecFlags SpecMainType;
+ COpenSpecFlags SpecWrongExt;
+ COpenSpecFlags SpecUnknownExt;
+
+ bool Recursive;
+
+ bool CanReturnArc;
+ bool CanReturnParser;
+ bool EachPos;
+
+ // bool SkipSfxStub;
+ // bool ExeAsUnknown;
+
+ bool ZerosTailIsAllowed;
+
+ bool MaxStartOffset_Defined;
+ UInt64 MaxStartOffset;
+
+ const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
+ {
+ return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
+ }
+
+ COpenType():
+ FormatIndex(-1),
+ Recursive(true),
+ EachPos(false),
+ CanReturnArc(true),
+ CanReturnParser(false),
+ // SkipSfxStub(true),
+ // ExeAsUnknown(true),
+ ZerosTailIsAllowed(false),
+ MaxStartOffset_Defined(false),
+ MaxStartOffset(0)
+ {
+ SpecForcedType.CanReturnFrontal = true;
+ SpecForcedType.CanReturnTail = true;
+ SpecForcedType.CanReturnMid = true;
+
+ SpecMainType.CanReturnFrontal = true;
+
+ SpecUnknownExt.CanReturnTail = true; // for sfx
+ SpecUnknownExt.CanReturnMid = true;
+ SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
+
+ // ZerosTailIsAllowed = true;
+ }
+};
+
+struct COpenOptions
+{
+ CCodecs *codecs;
+ COpenType openType;
+ const CObjectVector<COpenType> *types;
+ const CIntVector *excludedFormats;
+
+ IInStream *stream;
+ ISequentialInStream *seqStream;
+ IArchiveOpenCallback *callback;
+ COpenCallbackImp *callbackSpec;
+ OPEN_PROPS_DECL
+ // bool openOnlySpecifiedByExtension,
+
+ bool stdInMode;
+ UString filePath;
+
+ COpenOptions():
+ codecs(NULL),
+ types(NULL),
+ excludedFormats(NULL),
+ stream(NULL),
+ seqStream(NULL),
+ callback(NULL),
+ callbackSpec(NULL),
+ stdInMode(false)
+ {}
+
+};
+
+UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
+
+struct CArcErrorInfo
+{
+ bool ThereIsTail;
+ bool UnexpecedEnd;
+ bool IgnoreTail; // all are zeros
+ // bool NonZerosTail;
+ bool ErrorFlags_Defined;
+ UInt32 ErrorFlags;
+ UInt32 WarningFlags;
+ int ErrorFormatIndex; // - 1 means no Error.
+ // if FormatIndex == ErrorFormatIndex, the archive is open with offset
+ UInt64 TailSize;
+
+ /* if CArc is Open OK with some format:
+ - ErrorFormatIndex shows error format index, if extension is incorrect
+ - other variables show message and warnings of archive that is open */
+
+ UString ErrorMessage;
+ UString WarningMessage;
+
+ // call IsArc_After_NonOpen only if Open returns S_FALSE
+ bool IsArc_After_NonOpen() const
+ {
+ return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
+ }
+
+
+ CArcErrorInfo():
+ ThereIsTail(false),
+ UnexpecedEnd(false),
+ IgnoreTail(false),
+ // NonZerosTail(false),
+ ErrorFlags_Defined(false),
+ ErrorFlags(0),
+ WarningFlags(0),
+ ErrorFormatIndex(-1),
+ TailSize(0)
+ {}
+
+ void ClearErrors();
+
+ void ClearErrors_Full()
+ {
+ ErrorFormatIndex = -1;
+ ClearErrors();
+ }
+
+ bool IsThereErrorOrWarning() const
+ {
+ return ErrorFlags != 0
+ || WarningFlags != 0
+ || NeedTailWarning()
+ || UnexpecedEnd
+ || !ErrorMessage.IsEmpty()
+ || !WarningMessage.IsEmpty();
+ }
+
+ bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
+ bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
+
+ bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
+
+ UInt32 GetWarningFlags() const
+ {
+ UInt32 a = WarningFlags;
+ if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)
+ a |= kpv_ErrorFlags_DataAfterEnd;
+ return a;
+ }
+
+ UInt32 GetErrorFlags() const
+ {
+ UInt32 a = ErrorFlags;
+ if (UnexpecedEnd)
+ a |= kpv_ErrorFlags_UnexpectedEnd;
+ return a;
+ }
+};
+
+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;
+ // we use InStream in 2 cases (ArcStreamOffset != 0):
+ // 1) if we use additional cache stream
+ // 2) we reopen sfx archive with CTailInStream
+
+ CMyComPtr<IArchiveGetRawProps> GetRawProps;
+ CMyComPtr<IArchiveGetRootProps> GetRootProps;
+
+ CArcErrorInfo ErrorInfo; // for OK archives
+ CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
+
+ UString Path;
+ UString filePath;
+ UString DefaultName;
+ int FormatIndex; // - 1 means Parser.
+ int SubfileIndex;
+ FILETIME MTime;
+ bool MTimeDefined;
+
+ Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
+ UInt64 PhySize;
+ // UInt64 OkPhySize;
+ bool PhySizeDefined;
+ // bool OkPhySize_Defined;
+ UInt64 FileSize;
+ UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
+ // bool offsetDefined;
+
+ UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; }
+
+ UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
+ Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive
+
+ // AString ErrorFlagsText;
+
+ bool IsParseArc;
+
+ bool IsTree;
+ bool IsReadOnly;
+
+ bool Ask_Deleted;
+ bool Ask_AltStream;
+ bool Ask_Aux;
+ bool Ask_INode;
+
+ bool IgnoreSplit; // don't try split handler
+
+ // void Set_ErrorFlagsText();
+
+ CArc():
+ MTimeDefined(false),
+ IsTree(false),
+ IsReadOnly(false),
+ Ask_Deleted(false),
+ Ask_AltStream(false),
+ Ask_Aux(false),
+ Ask_INode(false),
+ IgnoreSplit(false)
+ {}
+
+ HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);
+
+ // ~CArc();
+
+ HRESULT Close()
+ {
+ InStream.Release();
+ return Archive->Close();
+ }
+
+ 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;
+ HRESULT IsItemAnti(UInt32 index, bool &result) const
+ { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
+
+
+ HRESULT OpenStream(const COpenOptions &options);
+ HRESULT OpenStreamOrFile(COpenOptions &options);
+
+ HRESULT ReOpen(const COpenOptions &options);
+
+ HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
+};
+
+struct CArchiveLink
+{
+ CObjectVector<CArc> Arcs;
+ UStringVector VolumePaths;
+ UInt64 VolumesSize;
+ bool IsOpen;
+
+ bool PasswordWasAsked;
+ // UString Password;
+
+ // int NonOpenErrorFormatIndex; // - 1 means no Error.
+ UString NonOpen_ArcPath;
+
+ CArcErrorInfo NonOpen_ErrorInfo;
+
+ // UString ErrorsText;
+ // void Set_ErrorsText();
+
+ CArchiveLink():
+ VolumesSize(0),
+ IsOpen(false),
+ PasswordWasAsked(false)
+ {}
+
+ void KeepModeForNextOpen();
+ HRESULT Close();
+ void Release();
+ ~CArchiveLink() { Release(); }
+
+ const CArc *GetArc() const { return &Arcs.Back(); }
+ IInArchive *GetArchive() const { return Arcs.Back().Archive; }
+ IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
+ IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
+
+ HRESULT Open(COpenOptions &options);
+ HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
+ HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);
+
+ HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)
+ {
+ HRESULT result = Open3(options, callbackUI);
+ if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
+ result = S_FALSE;
+ return result;
+ }
+
+ HRESULT ReOpen(COpenOptions &options);
+};
+
+bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
+
+
+struct CDirPathSortPair
+{
+ unsigned Len;
+ unsigned Index;
+
+ void SetNumSlashes(const FChar *s);
+
+ int Compare(const CDirPathSortPair &a) const
+ {
+ // We need sorting order where parent items will be after child items
+ if (Len < a.Len) return 1;
+ if (Len > a.Len) return -1;
+ if (Index < a.Index) return -1;
+ if (Index > a.Index) return 1;
+ return 0;
+ }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.cpp
new file mode 100644
index 0000000000..bb9c89f2dc
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -0,0 +1,668 @@
+// PropIDUtils.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/FileIO.h"
+#include "../../../Windows/PropVariantConv.h"
+
+#include "../../PropID.h"
+
+#include "PropIDUtils.h"
+
+#define Get16(x) GetUi16(x)
+#define Get32(x) GetUi32(x)
+
+using namespace NWindows;
+
+static const unsigned kNumWinAtrribFlags = 21;
+static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
+
+/*
+FILE_ATTRIBUTE_
+
+0 READONLY
+1 HIDDEN
+2 SYSTEM
+3 (Volume label - obsolete)
+4 DIRECTORY
+5 ARCHIVE
+6 DEVICE
+7 NORMAL
+8 TEMPORARY
+9 SPARSE_FILE
+10 REPARSE_POINT
+11 COMPRESSED
+12 OFFLINE
+13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer)
+14 ENCRYPTED
+15 INTEGRITY_STREAM (V - ReFS Win8/Win2012)
+16 VIRTUAL (reserved)
+17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib)
+18 RECALL_ON_OPEN or EA
+19 PINNED
+20 UNPINNED
+21 STRICTLY_SEQUENTIAL
+22 RECALL_ON_DATA_ACCESS
+*/
+
+
+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()
+{
+ /*
+ some programs store posix attributes in high 16 bits.
+ p7zip - stores additional 0x8000 flag marker.
+ macos - stores additional 0x4000 flag marker.
+ info-zip - no additional marker.
+ */
+
+ bool isPosix = ((wa & 0xF0000000) != 0);
+
+ UInt32 posix = 0;
+ if (isPosix)
+ {
+ posix = wa >> 16;
+ wa &= (UInt32)0x3FFF;
+ }
+
+ for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
+ {
+ UInt32 flag = (1 << i);
+ if ((wa & flag) != 0)
+ {
+ char c = g_WinAttribChars[i];
+ if (c != '.')
+ {
+ wa &= ~flag;
+ // if (i != 7) // we can disable N (NORMAL) printing
+ *s++ = c;
+ }
+ }
+ }
+
+ if (wa != 0)
+ {
+ *s++ = ' ';
+ ConvertUInt32ToHex8Digits(wa, s);
+ s += strlen(s);
+ }
+
+ *s = 0;
+
+ if (isPosix)
+ {
+ *s++ = ' ';
+ ConvertPosixAttribToString(s, posix);
+ }
+}
+
+
+void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw()
+{
+ *dest = 0;
+
+ if (prop.vt == VT_FILETIME)
+ {
+ const FILETIME &ft = prop.filetime;
+ if ((ft.dwHighDateTime == 0 &&
+ ft.dwLowDateTime == 0))
+ return;
+ ConvertUtcFileTimeToString(prop.filetime, dest, level);
+ return;
+ }
+
+ switch (propID)
+ {
+ case kpidCRC:
+ {
+ if (prop.vt != VT_UI4)
+ break;
+ ConvertUInt32ToHex8Digits(prop.ulVal, dest);
+ return;
+ }
+ case kpidAttrib:
+ {
+ if (prop.vt != VT_UI4)
+ break;
+ 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;
+ ConvertPosixAttribToString(dest, prop.ulVal);
+ return;
+ }
+ case kpidINode:
+ {
+ if (prop.vt != VT_UI8)
+ break;
+ ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest);
+ dest += strlen(dest);
+ *dest++ = '-';
+ UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1);
+ ConvertUInt64ToString(low, dest);
+ return;
+ }
+ case kpidVa:
+ {
+ UInt64 v = 0;
+ if (prop.vt == VT_UI4)
+ v = prop.ulVal;
+ else if (prop.vt == VT_UI8)
+ v = (UInt64)prop.uhVal.QuadPart;
+ else
+ break;
+ dest[0] = '0';
+ dest[1] = 'x';
+ ConvertUInt64ToHex(v, dest + 2);
+ return;
+ }
+ }
+
+ ConvertPropVariantToShortString(prop, dest);
+}
+
+void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level)
+{
+ if (prop.vt == VT_BSTR)
+ {
+ dest.SetFromBstr(prop.bstrVal);
+ return;
+ }
+ char temp[64];
+ ConvertPropertyToShortString2(temp, prop, propID, level);
+ dest = temp;
+}
+
+static inline unsigned GetHex(unsigned v)
+{
+ return (v < 10) ? ('0' + v) : ('A' + (v - 10));
+}
+
+#ifndef _SFX
+
+static inline void AddHexToString(AString &res, unsigned v)
+{
+ res += (char)GetHex(v >> 4);
+ res += (char)GetHex(v & 0xF);
+}
+
+/*
+static AString Data_To_Hex(const Byte *data, size_t size)
+{
+ AString s;
+ for (size_t i = 0; i < size; i++)
+ AddHexToString(s, data[i]);
+ return s;
+}
+*/
+
+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"
+};
+
+struct CSecID2Name
+{
+ UInt32 n;
+ const char *sz;
+};
+
+static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id)
+{
+ for (unsigned i = 0; i < num; i++)
+ if (pairs[i].n == id)
+ return i;
+ return -1;
+}
+
+static const CSecID2Name sid_32_Names[] =
+{
+ { 544, "Administrators" },
+ { 545, "Users" },
+ { 546, "Guests" },
+ { 547, "PowerUsers" },
+ { 548, "AccountOperators" },
+ { 549, "ServerOperators" },
+ { 550, "PrintOperators" },
+ { 551, "BackupOperators" },
+ { 552, "Replicators" },
+ { 553, "Backup Operators" },
+ { 554, "PreWindows2000CompatibleAccess" },
+ { 555, "RemoteDesktopUsers" },
+ { 556, "NetworkConfigurationOperators" },
+ { 557, "IncomingForestTrustBuilders" },
+ { 558, "PerformanceMonitorUsers" },
+ { 559, "PerformanceLogUsers" },
+ { 560, "WindowsAuthorizationAccessGroup" },
+ { 561, "TerminalServerLicenseServers" },
+ { 562, "DistributedCOMUsers" },
+ { 569, "CryptographicOperators" },
+ { 573, "EventLogReaders" },
+ { 574, "CertificateServiceDCOMAccess" }
+};
+
+static const CSecID2Name sid_21_Names[] =
+{
+ { 500, "Administrator" },
+ { 501, "Guest" },
+ { 502, "KRBTGT" },
+ { 512, "DomainAdmins" },
+ { 513, "DomainUsers" },
+ { 515, "DomainComputers" },
+ { 516, "DomainControllers" },
+ { 517, "CertPublishers" },
+ { 518, "SchemaAdmins" },
+ { 519, "EnterpriseAdmins" },
+ { 520, "GroupPolicyCreatorOwners" },
+ { 553, "RASandIASServers" },
+ { 553, "RASandIASServers" },
+ { 571, "AllowedRODCPasswordReplicationGroup" },
+ { 572, "DeniedRODCPasswordReplicationGroup" }
+};
+
+struct CServicesToName
+{
+ UInt32 n[5];
+ const char *sz;
+};
+
+static const CServicesToName services_to_name[] =
+{
+ { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" }
+};
+
+static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
+{
+ sidSize = 0;
+ if (lim < 8)
+ {
+ s += "ERROR";
+ return;
+ }
+ UInt32 rev = p[0];
+ if (rev != 1)
+ {
+ s += "UNSUPPORTED";
+ return;
+ }
+ UInt32 num = p[1];
+ if (8 + num * 4 > lim)
+ {
+ s += "ERROR";
+ return;
+ }
+ sidSize = 8 + num * 4;
+ UInt32 authority = GetBe32(p + 4);
+
+ if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)
+ {
+ UInt32 v0 = Get32(p + 8);
+ if (v0 < ARRAY_SIZE(sidNames))
+ {
+ s += sidNames[v0];
+ return;
+ }
+ if (v0 == 32 && num == 2)
+ {
+ UInt32 v1 = Get32(p + 12);
+ int index = FindPairIndex(sid_32_Names, ARRAY_SIZE(sid_32_Names), v1);
+ if (index >= 0)
+ {
+ s += sid_32_Names[(unsigned)index].sz;
+ return;
+ }
+ }
+ if (v0 == 21 && num == 5)
+ {
+ UInt32 v4 = Get32(p + 8 + 4 * 4);
+ int index = FindPairIndex(sid_21_Names, ARRAY_SIZE(sid_21_Names), v4);
+ if (index >= 0)
+ {
+ s += sid_21_Names[(unsigned)index].sz;
+ return;
+ }
+ }
+ if (v0 == 80 && num == 6)
+ {
+ for (unsigned i = 0; i < ARRAY_SIZE(services_to_name); i++)
+ {
+ const CServicesToName &sn = services_to_name[i];
+ int j;
+ for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++);
+ if (j == 5)
+ {
+ s += sn.sz;
+ return;
+ }
+ }
+ }
+ }
+
+ s += "S-1-";
+ if (p[2] == 0 && p[3] == 0)
+ s.Add_UInt32(authority);
+ else
+ {
+ s += "0x";
+ for (int i = 2; i < 8; i++)
+ AddHexToString(s, p[i]);
+ }
+ for (UInt32 i = 0; i < num; i++)
+ {
+ s += '-';
+ s.Add_UInt32(Get32(p + 8 + i * 4));
+ }
+}
+
+static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)
+{
+ if (pos > size)
+ {
+ s += "ERROR";
+ return;
+ }
+ UInt32 sidSize = 0;
+ ParseSid(s, p + pos, size - pos, sidSize);
+}
+
+static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)
+{
+ UInt32 control = Get16(p + 2);
+ if ((flags & control) == 0)
+ return;
+ UInt32 pos = Get32(p + offset);
+ s.Add_Space();
+ s += strName;
+ if (pos >= size)
+ return;
+ p += pos;
+ size -= pos;
+ if (size < 8)
+ return;
+ if (Get16(p) != 2) // revision
+ return;
+ UInt32 num = Get32(p + 4);
+ s.Add_UInt32(num);
+
+ /*
+ UInt32 aclSize = Get16(p + 2);
+ if (num >= (1 << 16))
+ return;
+ if (aclSize > size)
+ return;
+ size = aclSize;
+ size -= 8;
+ p += 8;
+ for (UInt32 i = 0 ; i < num; i++)
+ {
+ if (size <= 8)
+ return;
+ // Byte type = p[0];
+ // Byte flags = p[1];
+ // UInt32 aceSize = Get16(p + 2);
+ // UInt32 mask = Get32(p + 4);
+ p += 8;
+ size -= 8;
+
+ UInt32 sidSize = 0;
+ s.Add_Space();
+ ParseSid(s, p, size, sidSize);
+ if (sidSize == 0)
+ return;
+ p += sidSize;
+ size -= sidSize;
+ }
+
+ // the tail can contain zeros. So (size != 0) is not ERROR
+ // if (size != 0) s += " ERROR";
+ */
+}
+
+#define MY_SE_OWNER_DEFAULTED (0x0001)
+#define MY_SE_GROUP_DEFAULTED (0x0002)
+#define MY_SE_DACL_PRESENT (0x0004)
+#define MY_SE_DACL_DEFAULTED (0x0008)
+#define MY_SE_SACL_PRESENT (0x0010)
+#define MY_SE_SACL_DEFAULTED (0x0020)
+#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100)
+#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200)
+#define MY_SE_DACL_AUTO_INHERITED (0x0400)
+#define MY_SE_SACL_AUTO_INHERITED (0x0800)
+#define MY_SE_DACL_PROTECTED (0x1000)
+#define MY_SE_SACL_PROTECTED (0x2000)
+#define MY_SE_RM_CONTROL_VALID (0x4000)
+#define MY_SE_SELF_RELATIVE (0x8000)
+
+void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
+{
+ s.Empty();
+ if (size < 20 || size > (1 << 18))
+ {
+ s += "ERROR";
+ return;
+ }
+ if (Get16(data) != 1) // revision
+ {
+ s += "UNSUPPORTED";
+ return;
+ }
+ ParseOwner(s, data, size, Get32(data + 4));
+ s.Add_Space();
+ ParseOwner(s, data, size, Get32(data + 8));
+ ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
+ ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
+ s.Add_Space();
+ s.Add_UInt32(size);
+ // s += '\n';
+ // s += Data_To_Hex(data, size);
+}
+
+#ifdef _WIN32
+
+static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw()
+{
+ if (pos >= size)
+ return false;
+ size -= pos;
+ if (size < 8)
+ return false;
+ UInt32 rev = data[pos];
+ if (rev != 1)
+ return false;
+ UInt32 num = data[pos + 1];
+ return (8 + num * 4 <= size);
+}
+
+static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) throw()
+{
+ UInt32 control = Get16(p + 2);
+ if ((flags & control) == 0)
+ return true;
+ UInt32 pos = Get32(p + offset);
+ if (pos >= size)
+ return false;
+ p += pos;
+ size -= pos;
+ if (size < 8)
+ return false;
+ UInt32 aclSize = Get16(p + 2);
+ return (aclSize <= size);
+}
+
+bool CheckNtSecure(const Byte *data, UInt32 size) throw()
+{
+ if (size < 20)
+ return false;
+ if (Get16(data) != 1) // revision
+ return true; // windows function can handle such error, so we allow it
+ if (size > (1 << 18))
+ return false;
+ if (!CheckSid(data, size, Get32(data + 4))) return false;
+ if (!CheckSid(data, size, Get32(data + 8))) return false;
+ if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false;
+ if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false;
+ return true;
+}
+
+#endif
+
+
+
+// IO_REPARSE_TAG_*
+
+static const CSecID2Name k_ReparseTags[] =
+{
+ { 0xA0000003, "MOUNT_POINT" },
+ { 0xC0000004, "HSM" },
+ { 0x80000005, "DRIVE_EXTENDER" },
+ { 0x80000006, "HSM2" },
+ { 0x80000007, "SIS" },
+ { 0x80000008, "WIM" },
+ { 0x80000009, "CSV" },
+ { 0x8000000A, "DFS" },
+ { 0x8000000B, "FILTER_MANAGER" },
+ { 0xA000000C, "SYMLINK" },
+ { 0xA0000010, "IIS_CACHE" },
+ { 0x80000012, "DFSR" },
+ { 0x80000013, "DEDUP" },
+ { 0xC0000014, "APPXSTRM" },
+ { 0x80000014, "NFS" },
+ { 0x80000015, "FILE_PLACEHOLDER" },
+ { 0x80000016, "DFM" },
+ { 0x80000017, "WOF" }
+};
+
+bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
+{
+ s.Empty();
+ NFile::CReparseAttr attr;
+ DWORD errorCode = 0;
+ if (attr.Parse(data, size, errorCode))
+ {
+ if (!attr.IsSymLink())
+ s += "Junction: ";
+ s += attr.GetPath();
+ if (!attr.IsOkNamePair())
+ {
+ s += " : ";
+ s += attr.PrintName;
+ }
+ return true;
+ }
+
+ if (size < 8)
+ return false;
+ UInt32 tag = Get32(data);
+ UInt32 len = Get16(data + 4);
+ if (len + 8 > size)
+ return false;
+ if (Get16(data + 6) != 0) // padding
+ return false;
+
+ /*
+ #define _my_IO_REPARSE_TAG_DEDUP (0x80000013L)
+ if (tag == _my_IO_REPARSE_TAG_DEDUP)
+ {
+ }
+ */
+
+ {
+ int index = FindPairIndex(k_ReparseTags, ARRAY_SIZE(k_ReparseTags), tag);
+ if (index >= 0)
+ s += k_ReparseTags[(unsigned)index].sz;
+ else
+ {
+ s += "REPARSE:";
+ char hex[16];
+ ConvertUInt32ToHex8Digits(tag, hex);
+ s += hex;
+ }
+ }
+
+ s += ":";
+ s.Add_UInt32(len);
+
+ if (len != 0)
+ {
+ s.Add_Space();
+
+ data += 8;
+
+ for (UInt32 i = 0; i < len; i++)
+ {
+ if (i >= 8)
+ {
+ s += "...";
+ break;
+ }
+ unsigned b = data[i];
+ s += (char)GetHex((b >> 4) & 0xF);
+ s += (char)GetHex(b & 0xF);
+ }
+ }
+
+ return true;
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.h
new file mode 100644
index 0000000000..e94e6d798c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.h
@@ -0,0 +1,18 @@
+// PropIDUtils.h
+
+#ifndef __PROPID_UTILS_H
+#define __PROPID_UTILS_H
+
+#include "../../../Common/MyString.h"
+
+// provide at least 64 bytes for buffer including zero-end
+void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw();
+void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0);
+
+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) throw();;
+
+void ConvertWinAttribToString(char *s, UInt32 wa) throw();
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/Property.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Property.h
new file mode 100644
index 0000000000..31234ad3c5
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Property.h
@@ -0,0 +1,14 @@
+// Property.h
+
+#ifndef __7Z_PROPERTY_H
+#define __7Z_PROPERTY_H
+
+#include "../../../Common/MyString.h"
+
+struct CProperty
+{
+ UString Name;
+ UString Value;
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.cpp
new file mode 100644
index 0000000000..3cd4d57184
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.cpp
@@ -0,0 +1,80 @@
+// SetProperties.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyString.h"
+#include "../../../Common/StringToInt.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "SetProperties.h"
+
+using namespace NWindows;
+using namespace NCOM;
+
+static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
+{
+ const wchar_t *end;
+ UInt64 result = ConvertStringToUInt64(s, &end);
+ if (*end != 0 || s.IsEmpty())
+ prop = s;
+ else if (result <= (UInt32)0xFFFFFFFF)
+ prop = (UInt32)result;
+ else
+ prop = result;
+}
+
+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties)
+{
+ if (properties.IsEmpty())
+ return S_OK;
+ CMyComPtr<ISetProperties> setProperties;
+ unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties);
+ if (!setProperties)
+ return S_OK;
+
+ UStringVector realNames;
+ CPropVariant *values = new CPropVariant[properties.Size()];
+ try
+ {
+ unsigned i;
+ for (i = 0; i < properties.Size(); i++)
+ {
+ const CProperty &property = properties[i];
+ NCOM::CPropVariant propVariant;
+ UString name = property.Name;
+ if (property.Value.IsEmpty())
+ {
+ if (!name.IsEmpty())
+ {
+ wchar_t c = name.Back();
+ if (c == L'-')
+ propVariant = false;
+ else if (c == L'+')
+ propVariant = true;
+ if (propVariant.vt != VT_EMPTY)
+ name.DeleteBack();
+ }
+ }
+ else
+ ParseNumberString(property.Value, propVariant);
+ realNames.Add(name);
+ values[i] = propVariant;
+ }
+ CRecordVector<const wchar_t *> names;
+ for (i = 0; i < realNames.Size(); i++)
+ names.Add((const wchar_t *)realNames[i]);
+
+ RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));
+ }
+ catch(...)
+ {
+ delete []values;
+ throw;
+ }
+ delete []values;
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.h
new file mode 100644
index 0000000000..64c947cf86
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.h
@@ -0,0 +1,10 @@
+// SetProperties.h
+
+#ifndef __SETPROPERTIES_H
+#define __SETPROPERTIES_H
+
+#include "Property.h"
+
+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.cpp
new file mode 100644
index 0000000000..f73ece86e0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.cpp
@@ -0,0 +1,25 @@
+// SortUtils.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/Wildcard.h"
+
+#include "SortUtils.h"
+
+static int CompareStrings(const unsigned *p1, const unsigned *p2, void *param)
+{
+ const UStringVector &strings = *(const UStringVector *)param;
+ return CompareFileNames(strings[*p1], strings[*p2]);
+}
+
+void SortFileNames(const UStringVector &strings, CUIntVector &indices)
+{
+ const unsigned numItems = strings.Size();
+ indices.ClearAndSetSize(numItems);
+ if (numItems == 0)
+ return;
+ unsigned *vals = &indices[0];
+ for (unsigned i = 0; i < numItems; i++)
+ vals[i] = i;
+ indices.Sort(CompareStrings, (void *)&strings);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.h
new file mode 100644
index 0000000000..82d5e4cb2e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.h
@@ -0,0 +1,10 @@
+// SortUtils.h
+
+#ifndef __SORT_UTLS_H
+#define __SORT_UTLS_H
+
+#include "../../../Common/MyString.h"
+
+void SortFileNames(const UStringVector &strings, CUIntVector &indices);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.cpp
new file mode 100644
index 0000000000..56bba9a1f0
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.cpp
@@ -0,0 +1,19 @@
+// TempFiles.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Windows/FileDir.h"
+
+#include "TempFiles.h"
+
+using namespace NWindows;
+using namespace NFile;
+
+void CTempFiles::Clear()
+{
+ while (!Paths.IsEmpty())
+ {
+ NDir::DeleteFileAlways(Paths.Back());
+ Paths.DeleteBack();
+ }
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.h
new file mode 100644
index 0000000000..f62192dd5b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.h
@@ -0,0 +1,16 @@
+// TempFiles.h
+
+#ifndef __TEMP_FILES_H
+#define __TEMP_FILES_H
+
+#include "../../../Common/MyString.h"
+
+class CTempFiles
+{
+ void Clear();
+public:
+ FStringVector Paths;
+ ~CTempFiles() { Clear(); }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.cpp
new file mode 100644
index 0000000000..fc1eede4d5
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.cpp
@@ -0,0 +1,1667 @@
+// Update.cpp
+
+#include "StdAfx.h"
+
+#include "Update.h"
+
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
+#include "../../../Windows/TimeUtils.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/LimitedStreams.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "../Common/DirItem.h"
+#include "../Common/EnumDirItems.h"
+#include "../Common/OpenArchive.h"
+#include "../Common/UpdateProduce.h"
+
+#include "EnumDirItems.h"
+#include "SetProperties.h"
+#include "TempFiles.h"
+#include "UpdateCallback.h"
+
+static const char * const kUpdateIsNotSupoorted =
+ "update operations are not supported for this archive";
+
+static const char * const kUpdateIsNotSupoorted_MultiVol =
+ "Updating for multivolume archives is not implemented";
+
+using namespace NWindows;
+using namespace NCOM;
+using namespace NFile;
+using namespace NDir;
+using namespace NName;
+
+static CFSTR const 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;
+ FString pathPrefix = path + FCHAR_PATH_SEPARATOR;
+ {
+ NFind::CEnumerator enumerator;
+ enumerator.SetDirPrefix(pathPrefix);
+ while (enumerator.Next(fileInfo))
+ {
+ if (fileInfo.IsDir())
+ if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name))
+ return false;
+ }
+ }
+ /*
+ // we don't need clear read-only for folders
+ if (!MySetFileAttributes(path, 0))
+ return false;
+ */
+ return RemoveDir(path);
+}
+
+
+using namespace NUpdateArchive;
+
+class COutMultiVolStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+ unsigned _streamIndex; // required stream
+ UInt64 _offsetPos; // offset from start of _streamIndex index
+ UInt64 _absPos;
+ UInt64 _length;
+
+ struct CAltStreamInfo
+ {
+ COutFileStream *StreamSpec;
+ CMyComPtr<IOutStream> Stream;
+ FString Name;
+ UInt64 Pos;
+ UInt64 RealSize;
+ };
+ CObjectVector<CAltStreamInfo> Streams;
+public:
+ // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+ CRecordVector<UInt64> Sizes;
+ FString Prefix;
+ CTempFiles *TempFiles;
+
+ void Init()
+ {
+ _streamIndex = 0;
+ _offsetPos = 0;
+ _absPos = 0;
+ _length = 0;
+ }
+
+ 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);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+ STDMETHOD(SetSize)(UInt64 newSize);
+};
+
+// static NSynchronization::CCriticalSection g_TempPathsCS;
+
+HRESULT COutMultiVolStream::Close()
+{
+ HRESULT res = S_OK;
+ FOR_VECTOR (i, Streams)
+ {
+ COutFileStream *s = Streams[i].StreamSpec;
+ if (s)
+ {
+ HRESULT res2 = s->Close();
+ if (res2 != S_OK)
+ res = res2;
+ }
+ }
+ return res;
+}
+
+bool COutMultiVolStream::SetMTime(const FILETIME *mTime)
+{
+ bool res = true;
+ FOR_VECTOR (i, Streams)
+ {
+ COutFileStream *s = Streams[i].StreamSpec;
+ if (s)
+ if (!s->SetMTime(mTime))
+ res = false;
+ }
+ return res;
+}
+
+STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ while (size > 0)
+ {
+ if (_streamIndex >= Streams.Size())
+ {
+ CAltStreamInfo altStream;
+
+ FString name;
+ name.Add_UInt32(_streamIndex + 1);
+ 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))
+ return ::GetLastError();
+ {
+ // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
+ TempFiles->Paths.Add(name);
+ }
+
+ altStream.Pos = 0;
+ altStream.RealSize = 0;
+ altStream.Name = name;
+ Streams.Add(altStream);
+ continue;
+ }
+ CAltStreamInfo &altStream = Streams[_streamIndex];
+
+ unsigned index = _streamIndex;
+ if (index >= Sizes.Size())
+ index = Sizes.Size() - 1;
+ UInt64 volSize = Sizes[index];
+
+ if (_offsetPos >= volSize)
+ {
+ _offsetPos -= volSize;
+ _streamIndex++;
+ continue;
+ }
+ if (_offsetPos != altStream.Pos)
+ {
+ // CMyComPtr<IOutStream> outStream;
+ // RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream));
+ RINOK(altStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
+ altStream.Pos = _offsetPos;
+ }
+
+ UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - altStream.Pos);
+ UInt32 realProcessed;
+ RINOK(altStream.Stream->Write(data, curSize, &realProcessed));
+ data = (void *)((Byte *)data + realProcessed);
+ size -= realProcessed;
+ altStream.Pos += realProcessed;
+ _offsetPos += realProcessed;
+ _absPos += realProcessed;
+ if (_absPos > _length)
+ _length = _absPos;
+ if (_offsetPos > altStream.RealSize)
+ altStream.RealSize = _offsetPos;
+ if (processedSize)
+ *processedSize += realProcessed;
+ if (altStream.Pos == volSize)
+ {
+ _streamIndex++;
+ _offsetPos = 0;
+ }
+ if (realProcessed == 0 && curSize != 0)
+ return E_FAIL;
+ break;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ if (seekOrigin >= 3)
+ return STG_E_INVALIDFUNCTION;
+ switch (seekOrigin)
+ {
+ case STREAM_SEEK_SET: _absPos = offset; break;
+ case STREAM_SEEK_CUR: _absPos += offset; break;
+ case STREAM_SEEK_END: _absPos = _length + offset; break;
+ }
+ _offsetPos = _absPos;
+ if (newPosition)
+ *newPosition = _absPos;
+ _streamIndex = 0;
+ return S_OK;
+}
+
+STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)
+{
+ unsigned i = 0;
+ while (i < Streams.Size())
+ {
+ CAltStreamInfo &altStream = Streams[i++];
+ if ((UInt64)newSize < altStream.RealSize)
+ {
+ RINOK(altStream.Stream->SetSize(newSize));
+ altStream.RealSize = newSize;
+ break;
+ }
+ newSize -= altStream.RealSize;
+ }
+ while (i < Streams.Size())
+ {
+ {
+ CAltStreamInfo &altStream = Streams.Back();
+ altStream.Stream.Release();
+ DeleteFileAlways(altStream.Name);
+ }
+ Streams.DeleteBack();
+ }
+ _offsetPos = _absPos;
+ _streamIndex = 0;
+ _length = newSize;
+ return S_OK;
+}
+
+void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)
+{
+ OriginalPath = path;
+
+ SplitPathToParts_2(path, Prefix, Name);
+
+ if (mode == k_ArcNameMode_Add)
+ return;
+ if (mode == k_ArcNameMode_Exact)
+ {
+ BaseExtension.Empty();
+ return;
+ }
+
+ int dotPos = Name.ReverseFind_Dot();
+ if (dotPos < 0)
+ return;
+ if ((unsigned)dotPos == Name.Len() - 1)
+ {
+ Name.DeleteBack();
+ BaseExtension.Empty();
+ return;
+ }
+ const UString ext = Name.Ptr(dotPos + 1);
+ if (BaseExtension.IsEqualTo_NoCase(ext))
+ {
+ BaseExtension = ext;
+ Name.DeleteFrom(dotPos);
+ }
+ else
+ BaseExtension.Empty();
+}
+
+UString CArchivePath::GetFinalPath() const
+{
+ UString path = GetPathWithoutExt();
+ if (!BaseExtension.IsEmpty())
+ {
+ path += '.';
+ path += BaseExtension;
+ }
+ return path;
+}
+
+UString CArchivePath::GetFinalVolPath() const
+{
+ UString path = GetPathWithoutExt();
+ if (!BaseExtension.IsEmpty())
+ {
+ path += '.';
+ path += VolExtension;
+ }
+ return path;
+}
+
+FString CArchivePath::GetTempPath() const
+{
+ FString path = TempPrefix;
+ path += us2fs(Name);
+ if (!BaseExtension.IsEmpty())
+ {
+ path += '.';
+ path += us2fs(BaseExtension);
+ }
+ path += ".tmp";
+ path += TempPostfix;
+ return path;
+}
+
+static const char * const kDefaultArcType = "7z";
+static const char * const kDefaultArcExt = "7z";
+static const char * const kSFXExtension =
+ #ifdef _WIN32
+ "exe";
+ #else
+ "";
+ #endif
+
+bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs,
+ const CObjectVector<COpenType> &types, const UString &arcPath)
+{
+ if (types.Size() > 1)
+ return false;
+ // int arcTypeIndex = -1;
+ if (types.Size() != 0)
+ {
+ MethodMode.Type = types[0];
+ MethodMode.Type_Defined = true;
+ }
+ if (MethodMode.Type.FormatIndex < 0)
+ {
+ // MethodMode.Type = -1;
+ MethodMode.Type = COpenType();
+ if (ArcNameMode != k_ArcNameMode_Add)
+ {
+ MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath);
+ if (MethodMode.Type.FormatIndex >= 0)
+ MethodMode.Type_Defined = true;
+ }
+ }
+ return true;
+}
+
+bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
+{
+ UString typeExt;
+ int formatIndex = MethodMode.Type.FormatIndex;
+ if (formatIndex < 0)
+ {
+ typeExt = kDefaultArcExt;
+ }
+ else
+ {
+ const CArcInfoEx &arcInfo = codecs->Formats[formatIndex];
+ if (!arcInfo.UpdateEnabled)
+ return false;
+ typeExt = arcInfo.GetMainExt();
+ }
+ UString ext = typeExt;
+ if (SfxMode)
+ ext = kSFXExtension;
+ ArchivePath.BaseExtension = ext;
+ ArchivePath.VolExtension = typeExt;
+ ArchivePath.ParseFromPath(arcPath, ArcNameMode);
+ FOR_VECTOR (i, Commands)
+ {
+ CUpdateArchiveCommand &uc = Commands[i];
+ uc.ArchivePath.BaseExtension = ext;
+ uc.ArchivePath.VolExtension = typeExt;
+ uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode);
+ }
+ return true;
+}
+
+
+struct CUpdateProduceCallbackImp: public IUpdateProduceCallback
+{
+ const CObjectVector<CArcItem> *_arcItems;
+ IUpdateCallbackUI *_callback;
+ CDirItemsStat *_stat;
+
+ CUpdateProduceCallbackImp(
+ const CObjectVector<CArcItem> *a,
+ CDirItemsStat *stat,
+ IUpdateCallbackUI *callback):
+ _arcItems(a),
+ _stat(stat),
+ _callback(callback) {}
+
+ virtual HRESULT ShowDeleteFile(unsigned arcIndex);
+};
+
+
+HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex)
+{
+ const CArcItem &ai = (*_arcItems)[arcIndex];
+ {
+ CDirItemsStat &stat = *_stat;
+ if (ai.IsDir)
+ stat.NumDirs++;
+ else if (ai.IsAltStream)
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += ai.Size;
+ }
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += ai.Size;
+ }
+ }
+ return _callback->ShowDeleteFile(ai.Name, ai.IsDir);
+}
+
+bool CRenamePair::Prepare()
+{
+ if (RecursedType != NRecursedType::kNonRecursed)
+ return false;
+ if (!WildcardParsing)
+ return true;
+ return !DoesNameContainWildcard(OldName);
+}
+
+extern bool g_CaseSensitive;
+
+static unsigned CompareTwoNames(const wchar_t *s1, const wchar_t *s2)
+{
+ for (unsigned i = 0;; i++)
+ {
+ wchar_t c1 = s1[i];
+ wchar_t c2 = s2[i];
+ if (c1 == 0 || c2 == 0)
+ return i;
+ if (c1 == c2)
+ continue;
+ if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2)))
+ continue;
+ if (IsPathSepar(c1) && IsPathSepar(c2))
+ continue;
+ return i;
+ }
+}
+
+bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const
+{
+ unsigned num = CompareTwoNames(OldName, src);
+ if (OldName[num] == 0)
+ {
+ if (src[num] != 0 && !IsPathSepar(src[num]) && num != 0 && !IsPathSepar(src[num - 1]))
+ return false;
+ }
+ else
+ {
+ // OldName[num] != 0
+ // OldName = "1\1a.txt"
+ // src = "1"
+
+ if (!isFolder
+ || src[num] != 0
+ || !IsPathSepar(OldName[num])
+ || OldName[num + 1] != 0)
+ return false;
+ }
+ dest = NewName + src.Ptr(num);
+ return true;
+}
+
+#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,
+ CArchivePath &archivePath,
+ const CObjectVector<CArcItem> &arcItems,
+ Byte *processedItemsStatuses,
+ const CDirItems &dirItems,
+ const CDirItem *parentDirItem,
+ CTempFiles &tempFiles,
+ CUpdateErrorInfo &errorInfo,
+ IUpdateCallbackUI *callback,
+ CFinishArchiveStat &st)
+{
+ CMyComPtr<IOutArchive> outArchive;
+ int formatIndex = options.MethodMode.Type.FormatIndex;
+
+ if (arc)
+ {
+ formatIndex = arc->FormatIndex;
+ if (formatIndex < 0)
+ return E_NOTIMPL;
+ CMyComPtr<IInArchive> archive2 = arc->Archive;
+ HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
+ if (result != S_OK)
+ throw kUpdateIsNotSupoorted;
+ }
+ else
+ {
+ RINOK(codecs->CreateOutArchive(formatIndex, outArchive));
+
+ #ifdef EXTERNAL_CODECS
+ {
+ CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
+ outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+ if (setCompressCodecsInfo)
+ {
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
+ }
+ }
+ #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;
+ }
+ }
+
+ {
+ const CArcInfoEx &arcInfo = codecs->Formats[formatIndex];
+ if (options.AltStreams.Val && !arcInfo.Flags_AltStreams())
+ return E_NOTIMPL;
+ if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure())
+ return E_NOTIMPL;
+ }
+
+ CRecordVector<CUpdatePair2> updatePairs2;
+
+ UStringVector newNames;
+
+ CArcToDoStat stat2;
+
+ if (options.RenamePairs.Size() != 0)
+ {
+ FOR_VECTOR (i, arcItems)
+ {
+ const CArcItem &ai = arcItems[i];
+ bool needRename = false;
+ UString dest;
+
+ if (ai.Censored)
+ {
+ FOR_VECTOR (j, options.RenamePairs)
+ {
+ const CRenamePair &rp = options.RenamePairs[j];
+ if (rp.GetNewPath(ai.IsDir, ai.Name, dest))
+ {
+ needRename = true;
+ break;
+ }
+
+ #ifdef SUPPORT_ALT_STREAMS
+ if (ai.IsAltStream)
+ {
+ int colonPos = FindAltStreamColon_in_Path(ai.Name);
+ if (colonPos >= 0)
+ {
+ UString mainName = ai.Name.Left(colonPos);
+ /*
+ actually we must improve that code to support cases
+ with folder renaming like: rn arc dir1\ dir2\
+ */
+ if (rp.GetNewPath(false, mainName, dest))
+ {
+ needRename = true;
+ dest += ':';
+ dest += ai.Name.Ptr(colonPos + 1);
+ break;
+ }
+ }
+ }
+ #endif
+ }
+ }
+
+ CUpdatePair2 up2;
+ up2.SetAs_NoChangeArcItem(ai.IndexInServer);
+ if (needRename)
+ {
+ up2.NewProps = true;
+ RINOK(arc->IsItemAnti(i, up2.IsAnti));
+ up2.NewNameIndex = newNames.Add(dest);
+ }
+ updatePairs2.Add(up2);
+ }
+ }
+ else
+ {
+ CRecordVector<CUpdatePair> updatePairs;
+ GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!
+ CUpdateProduceCallbackImp upCallback(&arcItems, &stat2.DeleteData, callback);
+
+ UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL);
+ }
+
+ {
+ FOR_VECTOR (i, updatePairs2)
+ {
+ const CUpdatePair2 &up = updatePairs2[i];
+
+ // 17.01: anti-item is (up.NewData && (p.UseArcProps in most cases))
+
+ if (up.NewData && !up.UseArcProps)
+ {
+ if (up.ExistOnDisk())
+ {
+ CDirItemsStat2 &stat = stat2.NewData;
+ const CDirItem &di = dirItems.Items[up.DirIndex];
+ if (di.IsDir())
+ {
+ if (up.IsAnti)
+ stat.Anti_NumDirs++;
+ else
+ stat.NumDirs++;
+ }
+ else if (di.IsAltStream)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumAltStreams++;
+ else
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += di.Size;
+ }
+ }
+ else
+ {
+ if (up.IsAnti)
+ stat.Anti_NumFiles++;
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += di.Size;
+ }
+ }
+ }
+ }
+ else if (up.ArcIndex >= 0)
+ {
+ CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData);
+ const CArcItem &ai = arcItems[up.ArcIndex];
+ if (ai.IsDir)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumDirs++;
+ else
+ stat.NumDirs++;
+ }
+ else if (ai.IsAltStream)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumAltStreams++;
+ else
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += ai.Size;
+ }
+ }
+ else
+ {
+ if (up.IsAnti)
+ stat.Anti_NumFiles++;
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += ai.Size;
+ }
+ }
+ }
+ }
+ RINOK(callback->SetNumItems(stat2));
+ }
+
+ CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+ CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+
+ updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;
+ updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError;
+ updateCallbackSpec->StdInMode = options.StdInMode;
+ updateCallbackSpec->Callback = callback;
+
+ if (arc)
+ {
+ // we set Archive to allow to transfer GetProperty requests back to DLL.
+ updateCallbackSpec->Archive = arc->Archive;
+ }
+
+ updateCallbackSpec->DirItems = &dirItems;
+ updateCallbackSpec->ParentDirItem = parentDirItem;
+
+ updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val;
+ updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;
+ updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;
+
+ updateCallbackSpec->Arc = arc;
+ updateCallbackSpec->ArcItems = &arcItems;
+ updateCallbackSpec->UpdatePairs = &updatePairs2;
+
+ updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses;
+
+ if (options.RenamePairs.Size() != 0)
+ updateCallbackSpec->NewNames = &newNames;
+
+ CMyComPtr<IOutStream> outSeekStream;
+ CMyComPtr<ISequentialOutStream> outStream;
+
+ if (!options.StdOutMode)
+ {
+ FString dirPrefix;
+ if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix))
+ throw 1417161;
+ CreateComplexDir(dirPrefix);
+ }
+
+ COutFileStream *outStreamSpec = NULL;
+ CStdOutFileStream *stdOutFileStreamSpec = NULL;
+ COutMultiVolStream *volStreamSpec = NULL;
+
+ if (options.VolumesSizes.Size() == 0)
+ {
+ if (options.StdOutMode)
+ {
+ stdOutFileStreamSpec = new CStdOutFileStream;
+ outStream = stdOutFileStreamSpec;
+ }
+ else
+ {
+ outStreamSpec = new COutFileStream;
+ outSeekStream = outStreamSpec;
+ outStream = outSeekStream;
+ bool isOK = false;
+ FString realPath;
+
+ for (unsigned i = 0; i < (1 << 16); i++)
+ {
+ if (archivePath.Temp)
+ {
+ if (i > 0)
+ {
+ archivePath.TempPostfix.Empty();
+ archivePath.TempPostfix.Add_UInt32(i);
+ }
+ realPath = archivePath.GetTempPath();
+ }
+ else
+ realPath = us2fs(archivePath.GetFinalPath());
+ if (outStreamSpec->Create(realPath, false))
+ {
+ tempFiles.Paths.Add(realPath);
+ isOK = true;
+ break;
+ }
+ if (::GetLastError() != ERROR_FILE_EXISTS)
+ break;
+ if (!archivePath.Temp)
+ break;
+ }
+
+ if (!isOK)
+ return errorInfo.SetFromLastError("cannot open file", realPath);
+ }
+ }
+ else
+ {
+ if (options.StdOutMode)
+ return E_FAIL;
+ if (arc && arc->GetGlobalOffset() > 0)
+ return E_NOTIMPL;
+
+ volStreamSpec = new COutMultiVolStream;
+ outSeekStream = volStreamSpec;
+ outStream = outSeekStream;
+ volStreamSpec->Sizes = options.VolumesSizes;
+ volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath());
+ volStreamSpec->Prefix += '.';
+ volStreamSpec->TempFiles = &tempFiles;
+ volStreamSpec->Init();
+
+ /*
+ updateCallbackSpec->VolumesSizes = volumesSizes;
+ updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
+ if (!archivePath.VolExtension.IsEmpty())
+ updateCallbackSpec->VolExt = UString('.') + archivePath.VolExtension;
+ */
+ }
+
+ RINOK(SetProperties(outArchive, options.MethodMode.Properties));
+
+ if (options.SfxMode)
+ {
+ CInFileStream *sfxStreamSpec = new CInFileStream;
+ CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
+ if (!sfxStreamSpec->Open(options.SfxModule))
+ return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule);
+
+ CMyComPtr<ISequentialOutStream> sfxOutStream;
+ COutFileStream *outStreamSpec2 = NULL;
+ if (options.VolumesSizes.Size() == 0)
+ sfxOutStream = outStream;
+ else
+ {
+ outStreamSpec2 = new COutFileStream;
+ sfxOutStream = outStreamSpec2;
+ FString realPath = us2fs(archivePath.GetFinalPath());
+ if (!outStreamSpec2->Create(realPath, false))
+ 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 (outStreamSpec2)
+ {
+ RINOK(outStreamSpec2->Close());
+ }
+ }
+
+ CMyComPtr<ISequentialOutStream> tailStream;
+
+ if (options.SfxMode || !arc || arc->ArcStreamOffset == 0)
+ tailStream = outStream;
+ else
+ {
+ // Int64 globalOffset = arc->GetGlobalOffset();
+ RINOK(arc->InStream->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL));
+ if (options.StdOutMode)
+ tailStream = outStream;
+ else
+ {
+ CTailOutStream *tailStreamSpec = new CTailOutStream;
+ tailStream = tailStreamSpec;
+ tailStreamSpec->Stream = outSeekStream;
+ tailStreamSpec->Offset = arc->ArcStreamOffset;
+ tailStreamSpec->Init();
+ }
+ }
+
+
+ HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);
+ // 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)
+ {
+ FILETIME ft;
+ ft.dwLowDateTime = 0;
+ ft.dwHighDateTime = 0;
+ FOR_VECTOR (i, updatePairs2)
+ {
+ CUpdatePair2 &pair2 = updatePairs2[i];
+ const FILETIME *ft2 = NULL;
+ if (pair2.NewProps && pair2.DirIndex >= 0)
+ ft2 = &dirItems.Items[pair2.DirIndex].MTime;
+ else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
+ ft2 = &arcItems[pair2.ArcIndex].MTime;
+ if (ft2)
+ {
+ if (::CompareFileTime(&ft, ft2) < 0)
+ ft = *ft2;
+ }
+ }
+ if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
+ {
+ if (outStreamSpec)
+ outStreamSpec->SetMTime(&ft);
+ else if (volStreamSpec)
+ volStreamSpec->SetMTime(&ft);;
+ }
+ }
+
+ 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)
+ result = volStreamSpec->Close();
+ 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,
+ const CArc &arc,
+ CObjectVector<CArcItem> &arcItems)
+{
+ arcItems.Clear();
+ UInt32 numItems;
+ IInArchive *archive = arc.Archive;
+ RINOK(archive->GetNumberOfItems(&numItems));
+ arcItems.ClearAndReserve(numItems);
+
+ CReadArcItem item;
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ CArcItem ai;
+
+ 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(censor, item);
+
+ RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));
+ RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined));
+
+ {
+ CPropVariant prop;
+ RINOK(archive->GetProperty(i, kpidTimeType, &prop));
+ if (prop.vt == VT_UI4)
+ {
+ ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;
+ switch (ai.TimeType)
+ {
+ case NFileTimeType::kWindows:
+ case NFileTimeType::kUnix:
+ case NFileTimeType::kDOS:
+ break;
+ default:
+ return E_FAIL;
+ }
+ }
+ }
+
+ ai.IndexInServer = i;
+ arcItems.AddInReserved(ai);
+ }
+ return S_OK;
+}
+
+#if defined(_WIN32) && !defined(UNDER_CE)
+
+#include <mapi.h>
+
+#endif
+
+HRESULT UpdateArchive(
+ CCodecs *codecs,
+ const CObjectVector<COpenType> &types,
+ const UString &cmdArcPath2,
+ NWildcard::CCensor &censor,
+ CUpdateOptions &options,
+ CUpdateErrorInfo &errorInfo,
+ IOpenCallbackUI *openCallback,
+ IUpdateCallbackUI2 *callback,
+ bool needSetPath)
+{
+ if (options.StdOutMode && options.EMailMode)
+ return E_FAIL;
+
+ if (types.Size() > 1)
+ return E_NOTIMPL;
+
+ bool renameMode = !options.RenamePairs.IsEmpty();
+ if (renameMode)
+ {
+ if (options.Commands.Size() != 1)
+ return E_FAIL;
+ }
+
+ if (options.DeleteAfterCompressing)
+ {
+ if (options.Commands.Size() != 1)
+ return E_NOTIMPL;
+ const CActionSet &as = options.Commands[0].ActionSet;
+ for (int i = 2; i < NPairState::kNumValues; i++)
+ if (as.StateActions[i] != NPairAction::kCompress)
+ return E_NOTIMPL;
+ }
+
+ censor.AddPathsToCensor(options.PathMode);
+ #ifdef _WIN32
+ ConvertToLongNames(censor);
+ #endif
+ censor.ExtendExclude();
+
+
+ if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */))
+ return E_NOTIMPL;
+
+ if (options.SfxMode)
+ {
+ CProperty property;
+ property.Name = "rsfx";
+ options.MethodMode.Properties.Add(property);
+ if (options.SfxModule.IsEmpty())
+ {
+ errorInfo.Message = "SFX file is not specified";
+ return E_FAIL;
+ }
+ bool found = false;
+ if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0)
+ {
+ const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule;
+ if (NFind::DoesFileExist(fullName))
+ {
+ options.SfxModule = fullName;
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ if (!NFind::DoesFileExist(options.SfxModule))
+ return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule);
+ }
+ }
+
+ CArchiveLink arcLink;
+
+
+ if (needSetPath)
+ {
+ if (!options.InitFormatIndex(codecs, types, cmdArcPath2) ||
+ !options.SetArcPath(codecs, cmdArcPath2))
+ return E_NOTIMPL;
+ }
+
+ UString arcPath = options.ArchivePath.GetFinalPath();
+
+ if (!options.VolumesSizes.IsEmpty())
+ {
+ arcPath = options.ArchivePath.GetFinalVolPath();
+ arcPath += '.';
+ arcPath += "001";
+ }
+
+ if (cmdArcPath2.IsEmpty())
+ {
+ if (options.MethodMode.Type.FormatIndex < 0)
+ throw "type of archive is not specified";
+ }
+ else
+ {
+ NFind::CFileInfo fi;
+ if (!fi.Find(us2fs(arcPath)))
+ {
+ if (renameMode)
+ throw "can't find archive";;
+ if (options.MethodMode.Type.FormatIndex < 0)
+ {
+ if (!options.SetArcPath(codecs, cmdArcPath2))
+ return E_NOTIMPL;
+ }
+ }
+ else
+ {
+ if (fi.IsDir())
+ throw "there is no such archive";
+ if (fi.IsDevice)
+ return E_NOTIMPL;
+
+ if (!options.StdOutMode && options.UpdateArchiveItself)
+ if (fi.IsReadOnly())
+ {
+ errorInfo.SystemError = ERROR_ACCESS_DENIED;
+ errorInfo.Message = "The file is read-only";
+ errorInfo.FileNames.Add(arcPath);
+ return errorInfo.Get_HRESULT_Error();
+ }
+
+ if (options.VolumesSizes.Size() > 0)
+ {
+ errorInfo.FileNames.Add(us2fs(arcPath));
+ errorInfo.SystemError = (DWORD)E_NOTIMPL;
+ errorInfo.Message = kUpdateIsNotSupoorted_MultiVol;
+ return E_NOTIMPL;
+ }
+ CObjectVector<COpenType> types2;
+ // change it.
+ if (options.MethodMode.Type_Defined)
+ types2.Add(options.MethodMode.Type);
+ // We need to set Properties to open archive only in some cases (WIM archives).
+
+ CIntVector excl;
+ COpenOptions op;
+ #ifndef _SFX
+ op.props = &options.MethodMode.Properties;
+ #endif
+ op.codecs = codecs;
+ op.types = &types2;
+ op.excludedFormats = &excl;
+ op.stdInMode = false;
+ op.stream = NULL;
+ op.filePath = arcPath;
+
+ RINOK(callback->StartOpenArchive(arcPath));
+
+ HRESULT result = arcLink.Open_Strict(op, openCallback);
+
+ if (result == E_ABORT)
+ return result;
+
+ 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 = kUpdateIsNotSupoorted_MultiVol;
+ return E_NOTIMPL;
+ }
+
+ CArc &arc = arcLink.Arcs.Back();
+ arc.MTimeDefined = !fi.IsDevice;
+ arc.MTime = fi.MTime;
+
+ if (arc.ErrorInfo.ThereIsTail)
+ {
+ errorInfo.SystemError = (DWORD)E_NOTIMPL;
+ errorInfo.Message = "There is some data block after the end of the archive";
+ return E_NOTIMPL;
+ }
+ if (options.MethodMode.Type.FormatIndex < 0)
+ {
+ options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex;
+ if (!options.SetArcPath(codecs, cmdArcPath2))
+ return E_NOTIMPL;
+ }
+ }
+ }
+
+ if (options.MethodMode.Type.FormatIndex < 0)
+ {
+ options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType((UString)kDefaultArcType);
+ if (options.MethodMode.Type.FormatIndex < 0)
+ return E_NOTIMPL;
+ }
+
+ bool thereIsInArchive = arcLink.IsOpen;
+ if (!thereIsInArchive && renameMode)
+ return E_FAIL;
+
+ CDirItems dirItems;
+ dirItems.Callback = callback;
+
+ CDirItem parentDirItem;
+ CDirItem *parentDirItem_Ptr = NULL;
+
+ /*
+ FStringVector requestedPaths;
+ FStringVector *requestedPaths_Ptr = NULL;
+ if (options.DeleteAfterCompressing)
+ requestedPaths_Ptr = &requestedPaths;
+ */
+
+ if (options.StdInMode)
+ {
+ CDirItem di;
+ di.Name = options.StdInFileName;
+ di.Size = (UInt64)(Int64)-1;
+ di.Attrib = 0;
+ NTime::GetCurUtcFileTime(di.MTime);
+ di.CTime = di.ATime = di.MTime;
+ dirItems.Items.Add(di);
+ }
+ else
+ {
+ bool needScanning = false;
+
+ if (!renameMode)
+ FOR_VECTOR (i, options.Commands)
+ if (options.Commands[i].ActionSet.NeedScanning())
+ needScanning = true;
+
+ if (needScanning)
+ {
+ RINOK(callback->StartScanning());
+
+ dirItems.SymLinks = options.SymLinks.Val;
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ dirItems.ReadSecure = options.NtSecurity.Val;
+ #endif
+
+ dirItems.ScanAltStreams = options.AltStreams.Val;
+
+ HRESULT res = EnumerateItems(censor,
+ options.PathMode,
+ options.AddPathPrefix,
+ dirItems);
+
+ if (res != S_OK)
+ {
+ if (res != E_ABORT)
+ errorInfo.Message = "Scanning error";
+ return res;
+ }
+
+ RINOK(callback->FinishScanning(dirItems.Stat));
+
+ if (censor.Pairs.Size() == 1)
+ {
+ NFind::CFileInfo fi;
+ FString prefix = us2fs(censor.Pairs[0].Prefix);
+ prefix += '.';
+ // UString prefix = censor.Pairs[0].Prefix;
+ /*
+ if (prefix.Back() == WCHAR_PATH_SEPARATOR)
+ {
+ prefix.DeleteBack();
+ }
+ */
+ if (fi.Find(prefix))
+ if (fi.IsDir())
+ {
+ parentDirItem.Size = fi.Size;
+ parentDirItem.CTime = fi.CTime;
+ parentDirItem.ATime = fi.ATime;
+ parentDirItem.MTime = fi.MTime;
+ parentDirItem.Attrib = fi.Attrib;
+ parentDirItem_Ptr = &parentDirItem;
+
+ int secureIndex = -1;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (options.NtSecurity.Val)
+ dirItems.AddSecurityItem(prefix, secureIndex);
+ #endif
+ parentDirItem.SecureIndex = secureIndex;
+
+ parentDirItem_Ptr = &parentDirItem;
+ }
+ }
+ }
+ }
+
+ FString tempDirPrefix;
+ bool usesTempDir = false;
+
+ #ifdef _WIN32
+ CTempDir tempDirectory;
+ if (options.EMailMode && options.EMailRemoveAfter)
+ {
+ tempDirectory.Create(kTempFolderPrefix);
+ tempDirPrefix = tempDirectory.GetPath();
+ NormalizeDirPathPrefix(tempDirPrefix);
+ usesTempDir = true;
+ }
+ #endif
+
+ CTempFiles tempFiles;
+
+ bool createTempFile = false;
+
+ if (!options.StdOutMode && options.UpdateArchiveItself)
+ {
+ CArchivePath &ap = options.Commands[0].ArchivePath;
+ ap = options.ArchivePath;
+ // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
+ if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)
+ {
+ createTempFile = true;
+ ap.Temp = true;
+ if (!options.WorkingDir.IsEmpty())
+ ap.TempPrefix = options.WorkingDir;
+ else
+ ap.TempPrefix = us2fs(ap.Prefix);
+ NormalizeDirPathPrefix(ap.TempPrefix);
+ }
+ }
+
+ unsigned ci;
+
+ for (ci = 0; ci < options.Commands.Size(); ci++)
+ {
+ CArchivePath &ap = options.Commands[ci].ArchivePath;
+ if (usesTempDir)
+ {
+ // Check it
+ ap.Prefix = fs2us(tempDirPrefix);
+ // ap.Temp = true;
+ // ap.TempPrefix = tempDirPrefix;
+ }
+ if (!options.StdOutMode &&
+ (ci > 0 || !createTempFile))
+ {
+ const FString path = us2fs(ap.GetFinalPath());
+ if (NFind::DoesFileOrDirExist(path))
+ {
+ errorInfo.SystemError = ERROR_FILE_EXISTS;
+ errorInfo.Message = "The file already exists";
+ errorInfo.FileNames.Add(path);
+ return errorInfo.Get_HRESULT_Error();
+ }
+ }
+ }
+
+ CObjectVector<CArcItem> arcItems;
+ if (thereIsInArchive)
+ {
+ RINOK(EnumerateInArchiveItems(
+ // options.StoreAltStreams,
+ censor, arcLink.Arcs.Back(), arcItems));
+ }
+
+ /*
+ FStringVector processedFilePaths;
+ FStringVector *processedFilePaths_Ptr = NULL;
+ if (options.DeleteAfterCompressing)
+ processedFilePaths_Ptr = &processedFilePaths;
+ */
+
+ CByteBuffer processedItems;
+ if (options.DeleteAfterCompressing)
+ {
+ unsigned num = dirItems.Items.Size();
+ processedItems.Alloc(num);
+ for (unsigned i = 0; i < num; i++)
+ processedItems[i] = 0;
+ }
+
+ /*
+ #ifndef _NO_CRYPTO
+ if (arcLink.PasswordWasAsked)
+ {
+ // We set password, if open have requested password
+ RINOK(callback->SetPassword(arcLink.Password));
+ }
+ #endif
+ */
+
+ for (ci = 0; ci < options.Commands.Size(); ci++)
+ {
+ const CArc *arc = thereIsInArchive ? arcLink.GetArc() : NULL;
+ CUpdateArchiveCommand &command = options.Commands[ci];
+ UString name;
+ bool isUpdating;
+
+ if (options.StdOutMode)
+ {
+ name = "stdout";
+ isUpdating = thereIsInArchive;
+ }
+ else
+ {
+ name = command.ArchivePath.GetFinalPath();
+ isUpdating = (ci == 0 && options.UpdateArchiveItself && thereIsInArchive);
+ }
+
+ RINOK(callback->StartArchive(name, isUpdating))
+
+ CFinishArchiveStat st;
+
+ RINOK(Compress(options,
+ isUpdating,
+ codecs,
+ command.ActionSet,
+ arc,
+ command.ArchivePath,
+ arcItems,
+ options.DeleteAfterCompressing ? (Byte *)processedItems : NULL,
+
+ dirItems,
+ parentDirItem_Ptr,
+
+ tempFiles,
+ errorInfo, callback, st));
+
+ RINOK(callback->FinishArchive(st));
+ }
+
+
+ if (thereIsInArchive)
+ {
+ RINOK(arcLink.Close());
+ arcLink.Release();
+ }
+
+ tempFiles.Paths.Clear();
+ if (createTempFile)
+ {
+ try
+ {
+ CArchivePath &ap = options.Commands[0].ArchivePath;
+ const FString &tempPath = ap.GetTempPath();
+
+ // DWORD attrib = 0;
+ if (thereIsInArchive)
+ {
+ // attrib = NFind::GetFileAttrib(us2fs(arcPath));
+ if (!DeleteFileAlways(us2fs(arcPath)))
+ return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
+ }
+
+ if (!MyMoveFile(tempPath, us2fs(arcPath)))
+ {
+ errorInfo.SetFromLastError("cannot move the file", tempPath);
+ errorInfo.FileNames.Add(us2fs(arcPath));
+ return errorInfo.Get_HRESULT_Error();
+ }
+
+ /*
+ if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
+ {
+ DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath));
+ if (attrib2 != INVALID_FILE_ATTRIBUTES)
+ NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY);
+ }
+ */
+ }
+ catch(...)
+ {
+ throw;
+ }
+ }
+
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+
+ if (options.EMailMode)
+ {
+ NDLL::CLibrary mapiLib;
+ if (!mapiLib.Load(FTEXT("Mapi32.dll")))
+ {
+ errorInfo.SetFromLastError("cannot load Mapi32.dll");
+ return errorInfo.Get_HRESULT_Error();
+ }
+
+ /*
+ LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");
+ if (fnSend == 0)
+ {
+ errorInfo.SetFromLastError)("7-Zip cannot find MAPISendDocuments function");
+ return errorInfo.Get_HRESULT_Error();
+ }
+ */
+
+ LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail");
+ if (sendMail == 0)
+ {
+ 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 arcPath2;
+ if (!MyGetFullPathName(finalPath, arcPath2))
+ return errorInfo.SetFromLastError("GetFullPathName error", finalPath);
+ fullPaths.Add(arcPath2);
+ }
+
+ CCurrentDirRestorer curDirRestorer;
+
+ for (i = 0; i < fullPaths.Size(); i++)
+ {
+ const UString arcPath2 = fs2us(fullPaths[i]);
+ const UString fileName = ExtractFileNameFromPath(arcPath2);
+ const AString path (GetAnsiString(arcPath2));
+ const AString name (GetAnsiString(fileName));
+ // Warning!!! MAPISendDocuments function changes Current directory
+ // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
+
+ MapiFileDesc f;
+ memset(&f, 0, sizeof(f));
+ f.nPosition = 0xFFFFFFFF;
+ f.lpszPathName = (char *)(const char *)path;
+ f.lpszFileName = (char *)(const char *)name;
+
+ MapiMessage m;
+ memset(&m, 0, sizeof(m));
+ m.nFileCount = 1;
+ m.lpFiles = &f;
+
+ const AString addr (GetAnsiString(options.EMailAddress));
+ MapiRecipDesc rec;
+ if (!addr.IsEmpty())
+ {
+ memset(&rec, 0, sizeof(rec));
+ rec.ulRecipClass = MAPI_TO;
+ rec.lpszAddress = (char *)(const char *)addr;
+ m.nRecipCount = 1;
+ m.lpRecips = &rec;
+ }
+
+ sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
+ }
+ }
+
+ #endif
+
+ if (options.DeleteAfterCompressing)
+ {
+ CRecordVector<CDirPathSortPair> pairs;
+ FStringVector foldersNames;
+
+ unsigned i;
+
+ for (i = 0; i < dirItems.Items.Size(); i++)
+ {
+ const CDirItem &dirItem = dirItems.Items[i];
+ const FString phyPath = dirItems.GetPhyPath(i);
+ if (dirItem.IsDir())
+ {
+ CDirPathSortPair pair;
+ pair.Index = i;
+ pair.SetNumSlashes(phyPath);
+ pairs.Add(pair);
+ }
+ else
+ {
+ if (processedItems[i] != 0 || dirItem.Size == 0)
+ {
+ NFind::CFileInfo fileInfo;
+ if (fileInfo.Find(phyPath))
+ {
+ // maybe we must exclude also files with archive name: "a a.7z * -sdel"
+ if (fileInfo.Size == dirItem.Size
+ && CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0
+ && CompareFileTime(&fileInfo.CTime, &dirItem.CTime) == 0)
+ {
+ RINOK(callback->DeletingAfterArchiving(phyPath, false));
+ DeleteFileAlways(phyPath);
+ }
+ }
+ }
+ else
+ {
+ // file was skipped
+ /*
+ errorInfo.SystemError = 0;
+ errorInfo.Message = "file was not processed";
+ errorInfo.FileName = phyPath;
+ return E_FAIL;
+ */
+ }
+ }
+ }
+
+ pairs.Sort2();
+
+ for (i = 0; i < pairs.Size(); i++)
+ {
+ const FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
+ if (NFind::DoesDirExist(phyPath))
+ {
+ RINOK(callback->DeletingAfterArchiving(phyPath, true));
+ RemoveDir(phyPath);
+ }
+ }
+
+ RINOK(callback->FinishDeletingAfterArchiving());
+ }
+
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.h
new file mode 100644
index 0000000000..45b02d7408
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.h
@@ -0,0 +1,200 @@
+// Update.h
+
+#ifndef __COMMON_UPDATE_H
+#define __COMMON_UPDATE_H
+
+#include "../../../Common/Wildcard.h"
+
+#include "ArchiveOpenCallback.h"
+#include "LoadCodecs.h"
+#include "OpenArchive.h"
+#include "Property.h"
+#include "UpdateAction.h"
+#include "UpdateCallback.h"
+
+#include "DirItem.h"
+
+enum EArcNameMode
+{
+ k_ArcNameMode_Smart,
+ k_ArcNameMode_Exact,
+ k_ArcNameMode_Add,
+};
+
+struct CArchivePath
+{
+ UString OriginalPath;
+
+ UString Prefix; // path(folder) prefix including slash
+ UString Name; // base name
+ UString BaseExtension; // archive type extension or "exe" extension
+ UString VolExtension; // archive type extension for volumes
+
+ bool Temp;
+ FString TempPrefix; // path(folder) for temp location
+ FString TempPostfix;
+
+ CArchivePath(): Temp(false) {};
+
+ void ParseFromPath(const UString &path, EArcNameMode mode);
+ UString GetPathWithoutExt() const { return Prefix + Name; }
+ UString GetFinalPath() const;
+ UString GetFinalVolPath() const;
+ FString GetTempPath() const;
+};
+
+struct CUpdateArchiveCommand
+{
+ UString UserArchivePath;
+ CArchivePath ArchivePath;
+ NUpdateArchive::CActionSet ActionSet;
+};
+
+struct CCompressionMethodMode
+{
+ bool Type_Defined;
+ COpenType Type;
+ CObjectVector<CProperty> Properties;
+
+ CCompressionMethodMode(): Type_Defined(false) {}
+};
+
+namespace NRecursedType { enum EEnum
+{
+ kRecursed,
+ kWildcardOnlyRecursed,
+ kNonRecursed
+};}
+
+struct CRenamePair
+{
+ UString OldName;
+ UString NewName;
+ bool WildcardParsing;
+ NRecursedType::EEnum RecursedType;
+
+ CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {}
+
+ bool Prepare();
+ bool GetNewPath(bool isFolder, const UString &src, UString &dest) const;
+};
+
+struct CUpdateOptions
+{
+ CCompressionMethodMode MethodMode;
+
+ CObjectVector<CUpdateArchiveCommand> Commands;
+ bool UpdateArchiveItself;
+ CArchivePath ArchivePath;
+ EArcNameMode ArcNameMode;
+
+ bool SfxMode;
+ FString SfxModule;
+
+ bool OpenShareForWrite;
+ bool StopAfterOpenError;
+
+ bool StdInMode;
+ UString StdInFileName;
+ bool StdOutMode;
+
+ bool EMailMode;
+ bool EMailRemoveAfter;
+ UString EMailAddress;
+
+ FString WorkingDir;
+ NWildcard::ECensorPathMode PathMode;
+ UString AddPathPrefix;
+
+ CBoolPair NtSecurity;
+ CBoolPair AltStreams;
+ CBoolPair HardLinks;
+ CBoolPair SymLinks;
+
+ bool DeleteAfterCompressing;
+
+ bool SetArcMTime;
+
+ CObjectVector<CRenamePair> RenamePairs;
+
+ bool InitFormatIndex(const CCodecs *codecs, const CObjectVector<COpenType> &types, const UString &arcPath);
+ bool SetArcPath(const CCodecs *codecs, const UString &arcPath);
+
+ CUpdateOptions():
+ UpdateArchiveItself(true),
+ SfxMode(false),
+ StdInMode(false),
+ StdOutMode(false),
+ EMailMode(false),
+ EMailRemoveAfter(false),
+ OpenShareForWrite(false),
+ StopAfterOpenError(false),
+ ArcNameMode(k_ArcNameMode_Smart),
+ PathMode(NWildcard::k_RelatPath),
+
+ DeleteAfterCompressing(false),
+ SetArcMTime(false)
+
+ {};
+
+ void SetActionCommand_Add()
+ {
+ Commands.Clear();
+ CUpdateArchiveCommand c;
+ c.ActionSet = NUpdateArchive::k_ActionSet_Add;
+ Commands.Add(c);
+ }
+
+ CRecordVector<UInt64> VolumesSizes;
+};
+
+struct CUpdateErrorInfo
+{
+ DWORD SystemError;
+ 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 CFinishArchiveStat
+{
+ UInt64 OutArcFileSize;
+
+ CFinishArchiveStat(): OutArcFileSize(0) {}
+};
+
+#define INTERFACE_IUpdateCallbackUI2(x) \
+ INTERFACE_IUpdateCallbackUI(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 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(const CFinishArchiveStat &st) x; \
+ virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x; \
+ virtual HRESULT FinishDeletingAfterArchiving() x; \
+
+struct IUpdateCallbackUI2: public IUpdateCallbackUI, public IDirItemsCallback
+{
+ INTERFACE_IUpdateCallbackUI2(=0)
+};
+
+HRESULT UpdateArchive(
+ CCodecs *codecs,
+ const CObjectVector<COpenType> &types,
+ const UString &cmdArcPath2,
+ NWildcard::CCensor &censor,
+ CUpdateOptions &options,
+ CUpdateErrorInfo &errorInfo,
+ IOpenCallbackUI *openCallback,
+ IUpdateCallbackUI2 *callback,
+ bool needSetPath);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.cpp
new file mode 100644
index 0000000000..ba138d201c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.cpp
@@ -0,0 +1,64 @@
+// UpdateAction.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateAction.h"
+
+namespace NUpdateArchive {
+
+const CActionSet k_ActionSet_Add =
+{{
+ NPairAction::kCopy,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCompress,
+ NPairAction::kCompress,
+ NPairAction::kCompress,
+ NPairAction::kCompress
+}};
+
+const CActionSet k_ActionSet_Update =
+{{
+ NPairAction::kCopy,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress
+}};
+
+const CActionSet k_ActionSet_Fresh =
+{{
+ NPairAction::kCopy,
+ NPairAction::kCopy,
+ NPairAction::kIgnore,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress
+}};
+
+const CActionSet k_ActionSet_Sync =
+{{
+ NPairAction::kCopy,
+ NPairAction::kIgnore,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+ NPairAction::kCopy,
+ NPairAction::kCompress,
+}};
+
+const CActionSet k_ActionSet_Delete =
+{{
+ NPairAction::kCopy,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore,
+ NPairAction::kIgnore
+}};
+
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.h
new file mode 100644
index 0000000000..8d6002f0bd
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.h
@@ -0,0 +1,66 @@
+// UpdateAction.h
+
+#ifndef __UPDATE_ACTION_H
+#define __UPDATE_ACTION_H
+
+namespace NUpdateArchive {
+
+ namespace NPairState
+ {
+ const unsigned kNumValues = 7;
+ enum EEnum
+ {
+ kNotMasked = 0,
+ kOnlyInArchive,
+ kOnlyOnDisk,
+ kNewInArchive,
+ kOldInArchive,
+ kSameFiles,
+ kUnknowNewerFiles
+ };
+ }
+
+ namespace NPairAction
+ {
+ enum EEnum
+ {
+ kIgnore = 0,
+ kCopy,
+ kCompress,
+ kCompressAsAnti
+ };
+ }
+
+ struct CActionSet
+ {
+ NPairAction::EEnum StateActions[NPairState::kNumValues];
+
+ bool IsEqualTo(const CActionSet &a) const
+ {
+ for (unsigned i = 0; i < NPairState::kNumValues; i++)
+ if (StateActions[i] != a.StateActions[i])
+ return false;
+ return true;
+ }
+
+ bool NeedScanning() const
+ {
+ unsigned i;
+ for (i = 0; i < NPairState::kNumValues; i++)
+ if (StateActions[i] == NPairAction::kCompress)
+ return true;
+ for (i = 1; i < NPairState::kNumValues; i++)
+ if (StateActions[i] != NPairAction::kIgnore)
+ return true;
+ return false;
+ }
+ };
+
+ extern const CActionSet k_ActionSet_Add;
+ extern const CActionSet k_ActionSet_Update;
+ extern const CActionSet k_ActionSet_Fresh;
+ extern const CActionSet k_ActionSet_Sync;
+ extern const CActionSet k_ActionSet_Delete;
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.cpp
new file mode 100644
index 0000000000..9c165fe939
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -0,0 +1,771 @@
+// UpdateCallback.cpp
+
+#include "StdAfx.h"
+
+#ifndef _7ZIP_ST
+#include "../../../Windows/Synchronization.h"
+#endif
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
+
+#include "../../Common/StreamObjects.h"
+
+#include "UpdateCallback.h"
+
+#if defined(_WIN32) && !defined(UNDER_CE)
+#define _USE_SECURITY_CODE
+#include "../../../Windows/SecurityUtils.h"
+#endif
+
+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():
+ _hardIndex_From((UInt32)(Int32)-1),
+
+ Callback(NULL),
+
+ DirItems(NULL),
+ ParentDirItem(NULL),
+
+ Arc(NULL),
+ ArcItems(NULL),
+ UpdatePairs(NULL),
+ NewNames(NULL),
+ CommentIndex(-1),
+ Comment(NULL),
+
+ ShareForWrite(false),
+ StopAfterOpenError(false),
+ StdInMode(false),
+
+ KeepOriginalItemNames(false),
+ StoreNtSecurity(false),
+ StoreHardLinks(false),
+ StoreSymLinks(false),
+
+ ProcessedItemsStatuses(NULL)
+{
+ #ifdef _USE_SECURITY_CODE
+ _saclEnabled = InitLocalPrivileges();
+ #endif
+}
+
+
+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
+{
+ COM_TRY_BEGIN
+ return Callback->SetTotal(size);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
+{
+ COM_TRY_BEGIN
+ return Callback->SetCompleted(completeValue);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ COM_TRY_BEGIN
+ return Callback->SetRatioInfo(inSize, outSize);
+ COM_TRY_END
+}
+
+
+/*
+static const CStatProp kProps[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsDir, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidCTime, VT_FILETIME},
+ { NULL, kpidATime, VT_FILETIME},
+ { NULL, kpidMTime, VT_FILETIME},
+ { NULL, kpidAttrib, VT_UI4},
+ { NULL, kpidIsAnti, VT_BOOL}
+};
+
+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)
+{
+ return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator);
+}
+*/
+
+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
+ Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)
+{
+ COM_TRY_BEGIN
+ RINOK(Callback->CheckBreak());
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ if (newData) *newData = BoolToInt(up.NewData);
+ if (newProps) *newProps = BoolToInt(up.NewProps);
+ if (indexInArchive)
+ {
+ *indexInArchive = (UInt32)(Int32)-1;
+ if (up.ExistInArchive())
+ *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidIsDir: prop = true; break;
+ case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break;
+ case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break;
+ case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break;
+ case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
+{
+ *parentType = NParentType::kDir;
+ *parent = (UInt32)(Int32)-1;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps)
+{
+ *numProps = 0;
+ if (StoreNtSecurity)
+ *numProps = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
+{
+ *name = NULL;
+ *propID = kpidNtSecure;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID
+ #ifdef _USE_SECURITY_CODE
+ propID
+ #endif
+ , const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ *data = 0;
+ *dataSize = 0;
+ *propType = 0;
+ if (!StoreNtSecurity)
+ return S_OK;
+ #ifdef _USE_SECURITY_CODE
+ if (propID == kpidNtSecure)
+ {
+ if (StdInMode)
+ return S_OK;
+
+ if (ParentDirItem)
+ {
+ if (ParentDirItem->SecureIndex < 0)
+ return S_OK;
+ const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[ParentDirItem->SecureIndex];
+ *data = buf;
+ *dataSize = (UInt32)buf.Size();
+ *propType = NPropDataType::kRaw;
+ return S_OK;
+ }
+
+ if (Arc && Arc->GetRootProps)
+ return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType);
+ }
+ #endif
+ return S_OK;
+}
+
+// #ifdef _USE_SECURITY_CODE
+// #endif
+
+STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ *data = 0;
+ *dataSize = 0;
+ *propType = 0;
+
+ if (propID == kpidNtSecure ||
+ propID == kpidNtReparse)
+ {
+ if (StdInMode)
+ return S_OK;
+
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps)
+ return Arc->GetRawProps->GetRawProp(
+ ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex,
+ propID, data, dataSize, propType);
+ {
+ /*
+ if (!up.NewData)
+ return E_FAIL;
+ */
+ if (up.IsAnti)
+ return S_OK;
+
+ #ifndef UNDER_CE
+ const CDirItem &di = DirItems->Items[up.DirIndex];
+ #endif
+
+ #ifdef _USE_SECURITY_CODE
+ if (propID == kpidNtSecure)
+ {
+ if (!StoreNtSecurity)
+ return S_OK;
+ if (di.SecureIndex < 0)
+ return S_OK;
+ const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[di.SecureIndex];
+ *data = buf;
+ *dataSize = (UInt32)buf.Size();
+ *propType = NPropDataType::kRaw;
+ }
+ else
+ #endif
+ {
+ // propID == kpidNtReparse
+ if (!StoreSymLinks)
+ return S_OK;
+ #ifndef UNDER_CE
+ const CByteBuffer *buf = &di.ReparseData2;
+ if (buf->Size() == 0)
+ buf = &di.ReparseData;
+ if (buf->Size() != 0)
+ {
+ *data = *buf;
+ *dataSize = (UInt32)buf->Size();
+ *propType = NPropDataType::kRaw;
+ }
+ #endif
+ }
+
+ return S_OK;
+ }
+ }
+
+ return S_OK;
+}
+
+#ifndef UNDER_CE
+
+static UString GetRelativePath(const UString &to, const UString &from)
+{
+ UStringVector partsTo, partsFrom;
+ SplitPathToParts(to, partsTo);
+ SplitPathToParts(from, partsFrom);
+
+ unsigned i;
+ for (i = 0;; i++)
+ {
+ if (i + 1 >= partsFrom.Size() ||
+ i + 1 >= partsTo.Size())
+ break;
+ if (CompareFileNames(partsFrom[i], partsTo[i]) != 0)
+ break;
+ }
+
+ if (i == 0)
+ {
+ #ifdef _WIN32
+ if (NName::IsDrivePath(to) ||
+ NName::IsDrivePath(from))
+ return to;
+ #endif
+ }
+
+ UString s;
+ unsigned k;
+
+ for (k = i + 1; k < partsFrom.Size(); k++)
+ s += ".." STRING_PATH_SEPARATOR;
+
+ for (k = i; k < partsTo.Size(); k++)
+ {
+ if (k != i)
+ s.Add_PathSepar();
+ s += partsTo[k];
+ }
+
+ return s;
+}
+
+#endif
+
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ NCOM::CPropVariant prop;
+
+ if (up.NewData)
+ {
+ /*
+ if (propID == kpidIsHardLink)
+ {
+ prop = _isHardLink;
+ prop.Detach(value);
+ return S_OK;
+ }
+ */
+ if (propID == kpidSymLink)
+ {
+ if (index == _hardIndex_From)
+ {
+ prop.Detach(value);
+ return S_OK;
+ }
+ if (up.DirIndex >= 0)
+ {
+ #ifndef UNDER_CE
+ const CDirItem &di = DirItems->Items[up.DirIndex];
+ // if (di.IsDir())
+ {
+ CReparseAttr attr;
+ DWORD errorCode = 0;
+ if (attr.Parse(di.ReparseData, di.ReparseData.Size(), errorCode))
+ {
+ UString simpleName = attr.GetPath();
+ if (attr.IsRelative())
+ prop = simpleName;
+ else
+ {
+ const FString phyPath = DirItems->GetPhyPath(up.DirIndex);
+ FString fullPath;
+ if (NDir::MyGetFullPathName(phyPath, fullPath))
+ {
+ prop = GetRelativePath(simpleName, fs2us(fullPath));
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+ }
+ }
+ #endif
+ }
+ }
+ else if (propID == kpidHardLink)
+ {
+ if (index == _hardIndex_From)
+ {
+ const CKeyKeyValPair &pair = _map[_hardIndex_To];
+ const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value];
+ prop = DirItems->GetLogPath(up2.DirIndex);
+ prop.Detach(value);
+ return S_OK;
+ }
+ if (up.DirIndex >= 0)
+ {
+ prop.Detach(value);
+ return S_OK;
+ }
+ }
+ }
+
+ if (up.IsAnti
+ && propID != kpidIsDir
+ && propID != kpidPath
+ && propID != kpidIsAltStream)
+ {
+ switch (propID)
+ {
+ case kpidSize: prop = (UInt64)0; break;
+ case kpidIsAnti: prop = true; break;
+ }
+ }
+ else if (propID == kpidPath && up.NewNameIndex >= 0)
+ prop = (*NewNames)[up.NewNameIndex];
+ else if (propID == kpidComment
+ && CommentIndex >= 0
+ && (unsigned)CommentIndex == index
+ && Comment)
+ prop = *Comment;
+ else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem)
+ {
+ // we can generate new ShortName here;
+ }
+ 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())
+ {
+ const CDirItem &di = DirItems->Items[up.DirIndex];
+ switch (propID)
+ {
+ case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
+ case kpidIsDir: prop = di.IsDir(); break;
+ case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break;
+ case kpidAttrib: prop = di.Attrib; break;
+ case kpidCTime: prop = di.CTime; break;
+ case kpidATime: prop = di.ATime; break;
+ case kpidMTime: prop = di.MTime; break;
+ case kpidIsAltStream: prop = di.IsAltStream; break;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ // case kpidShortName: prop = di.ShortName; break;
+ #endif
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+#ifndef _7ZIP_ST
+static NSynchronization::CCriticalSection CS;
+#endif
+
+STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
+{
+ COM_TRY_BEGIN
+ *inStream = NULL;
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ if (!up.NewData)
+ return E_FAIL;
+
+ RINOK(Callback->CheckBreak());
+ // RINOK(Callback->Finalize());
+
+ bool isDir = IsDir(up);
+
+ if (up.IsAnti)
+ {
+ UString name;
+ if (up.ArcIndex >= 0)
+ name = (*ArcItems)[up.ArcIndex].Name;
+ else if (up.DirIndex >= 0)
+ name = DirItems->GetLogPath(up.DirIndex);
+ 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 */
+
+ if (!isDir)
+ {
+ CBufInStream *inStreamSpec = new CBufInStream();
+ CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec;
+ inStreamSpec->Init(NULL, 0);
+ *inStream = inStreamLoc.Detach();
+ }
+ return S_OK;
+ }
+
+ 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();
+ }
+ else
+ {
+ CInFileStream *inStreamSpec = new CInFileStream;
+ CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+
+ inStreamSpec->SupportHardLinks = StoreHardLinks;
+ inStreamSpec->Callback = this;
+ inStreamSpec->CallbackRef = index;
+
+ 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(path))
+ {
+ return Callback->OpenFileError(path, ::GetLastError());
+ }
+ }
+ else
+ #endif
+ if (!inStreamSpec->OpenShared(path, ShareForWrite))
+ {
+ DWORD error = ::GetLastError();
+ HRESULT hres = Callback->OpenFileError(path, error);
+ if (StopAfterOpenError)
+ if (hres == S_OK || hres == S_FALSE)
+ return HRESULT_FROM_WIN32(error);
+ return hres;
+ }
+
+ if (StoreHardLinks)
+ {
+ CStreamFileProps props;
+ if (inStreamSpec->GetProps2(&props) == S_OK)
+ {
+ if (props.NumLinks > 1)
+ {
+ CKeyKeyValPair pair;
+ pair.Key1 = props.VolID;
+ pair.Key2 = props.FileID_Low;
+ pair.Value = index;
+ unsigned numItems = _map.Size();
+ unsigned pairIndex = _map.AddToUniqueSorted2(pair);
+ if (numItems == _map.Size())
+ {
+ // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex];
+ _hardIndex_From = index;
+ _hardIndex_To = pairIndex;
+ // we could return NULL as stream, but it's better to return real stream
+ // return S_OK;
+ }
+ }
+ }
+ }
+
+ if (ProcessedItemsStatuses)
+ {
+ #ifndef _7ZIP_ST
+ NSynchronization::CCriticalSectionLock lock(CS);
+ #endif
+ ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1;
+ }
+ *inStream = inStreamLoc.Detach();
+ }
+
+ return S_OK;
+ COM_TRY_END
+}
+
+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 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
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
+{
+ if (VolumesSizes.Size() == 0)
+ return S_FALSE;
+ if (index >= (UInt32)VolumesSizes.Size())
+ index = VolumesSizes.Size() - 1;
+ *size = VolumesSizes[index];
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
+{
+ COM_TRY_BEGIN
+ char temp[16];
+ ConvertUInt32ToString(index + 1, temp);
+ FString res (temp);
+ while (res.Len() < 2)
+ res.InsertAtFront(FTEXT('0'));
+ FString fileName = VolName;
+ fileName += '.';
+ fileName += res;
+ fileName += VolExt;
+ COutFileStream *streamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
+ if (!streamSpec->Create(fileName, false))
+ return ::GetLastError();
+ *volumeStream = streamLoc.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+ COM_TRY_BEGIN
+ return Callback->CryptoGetTextPassword2(passwordIsDefined, password);
+ COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+ 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/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.h
new file mode 100644
index 0000000000..1b5d1eee8e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.h
@@ -0,0 +1,162 @@
+// UpdateCallback.h
+
+#ifndef __UPDATE_CALLBACK_H
+#define __UPDATE_CALLBACK_H
+
+#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"
+
+struct CArcToDoStat
+{
+ CDirItemsStat2 NewData;
+ CDirItemsStat2 OldData;
+ CDirItemsStat2 DeleteData;
+
+ UInt64 Get_NumDataItems_Total() const
+ {
+ return NewData.Get_NumDataItems2() + OldData.Get_NumDataItems2();
+ }
+};
+
+#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 Finalize() x; */ \
+ virtual HRESULT SetNumItems(const CArcToDoStat &stat) 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, bool isDir) x; \
+ /* virtual HRESULT CloseProgress() { return S_OK; } */
+
+struct IUpdateCallbackUI
+{
+ INTERFACE_IUpdateCallbackUI(=0)
+};
+
+struct CKeyKeyValPair
+{
+ UInt64 Key1;
+ UInt64 Key2;
+ unsigned Value;
+
+ int Compare(const CKeyKeyValPair &a) const
+ {
+ if (Key1 < a.Key1) return -1;
+ if (Key1 > a.Key1) return 1;
+ return MyCompare(Key2, a.Key2);
+ }
+};
+
+
+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)
+ bool _saclEnabled;
+ #endif
+ CRecordVector<CKeyKeyValPair> _map;
+
+ UInt32 _hardIndex_From;
+ UInt32 _hardIndex_To;
+
+public:
+ 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;
+
+ const CDirItems *DirItems;
+ const CDirItem *ParentDirItem;
+
+ const CArc *Arc;
+ CMyComPtr<IInArchive> Archive;
+ const CObjectVector<CArcItem> *ArcItems;
+ const CRecordVector<CUpdatePair2> *UpdatePairs;
+ const UStringVector *NewNames;
+ int CommentIndex;
+ const UString *Comment;
+
+ bool ShareForWrite;
+ bool StopAfterOpenError;
+ bool StdInMode;
+
+ bool KeepOriginalItemNames;
+ bool StoreNtSecurity;
+ bool StoreHardLinks;
+ bool StoreSymLinks;
+
+ Byte *ProcessedItemsStatuses;
+
+
+ CArchiveUpdateCallback();
+
+ bool IsDir(const CUpdatePair2 &up) const
+ {
+ if (up.DirIndex >= 0)
+ return DirItems->Items[up.DirIndex].IsDir();
+ else if (up.ArcIndex >= 0)
+ return (*ArcItems)[up.ArcIndex].IsDir;
+ return false;
+ }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.cpp
new file mode 100644
index 0000000000..5153671a7c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -0,0 +1,233 @@
+// UpdatePair.cpp
+
+#include "StdAfx.h"
+
+#include <time.h>
+
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/TimeUtils.h"
+
+#include "SortUtils.h"
+#include "UpdatePair.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)
+{
+ switch (fileTimeType)
+ {
+ case NFileTimeType::kWindows:
+ return ::CompareFileTime(&time1, &time2);
+ case NFileTimeType::kUnix:
+ {
+ UInt32 unixTime1, unixTime2;
+ FileTimeToUnixTime(time1, unixTime1);
+ FileTimeToUnixTime(time2, unixTime2);
+ return MyCompare(unixTime1, unixTime2);
+ }
+ case NFileTimeType::kDOS:
+ {
+ UInt32 dosTime1, dosTime2;
+ FileTimeToDosTime(time1, dosTime1);
+ FileTimeToDosTime(time2, dosTime2);
+ return MyCompare(dosTime1, dosTime2);
+ }
+ }
+ throw 4191618;
+}
+
+static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:";
+static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:";
+static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";
+
+static void ThrowError(const char *message, const UString &s1, const UString &s2)
+{
+ UString m (message);
+ m.Add_LF(); m += s1;
+ m.Add_LF(); m += s2;
+ throw m;
+}
+
+static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2)
+{
+ int res = CompareFileNames(ai1.Name, ai2.Name);
+ if (res != 0)
+ return res;
+ if (ai1.IsDir != ai2.IsDir)
+ return ai1.IsDir ? -1 : 1;
+ return 0;
+}
+
+static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param)
+{
+ unsigned i1 = *p1;
+ unsigned i2 = *p2;
+ const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param;
+ int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]);
+ if (res != 0)
+ return res;
+ return MyCompare(i1, i2);
+}
+
+void GetUpdatePairInfoList(
+ const CDirItems &dirItems,
+ const CObjectVector<CArcItem> &arcItems,
+ NFileTimeType::EEnum fileTimeType,
+ CRecordVector<CUpdatePair> &updatePairs)
+{
+ CUIntVector dirIndices, arcIndices;
+
+ unsigned numDirItems = dirItems.Items.Size();
+ unsigned numArcItems = arcItems.Size();
+
+ CIntArr duplicatedArcItem(numArcItems);
+ {
+ int *vals = &duplicatedArcItem[0];
+ for (unsigned i = 0; i < numArcItems; i++)
+ vals[i] = 0;
+ }
+
+ {
+ arcIndices.ClearAndSetSize(numArcItems);
+ if (numArcItems != 0)
+ {
+ unsigned *vals = &arcIndices[0];
+ for (unsigned i = 0; i < numArcItems; i++)
+ vals[i] = i;
+ }
+ arcIndices.Sort(CompareArcItems, (void *)&arcItems);
+ for (unsigned i = 0; i + 1 < numArcItems; i++)
+ if (CompareArcItemsBase(
+ arcItems[arcIndices[i]],
+ arcItems[arcIndices[i + 1]]) == 0)
+ {
+ duplicatedArcItem[i] = 1;
+ duplicatedArcItem[i + 1] = -1;
+ }
+ }
+
+ UStringVector dirNames;
+ {
+ dirNames.ClearAndReserve(numDirItems);
+ unsigned i;
+ for (i = 0; i < numDirItems; i++)
+ dirNames.AddInReserved(dirItems.GetLogPath(i));
+ SortFileNames(dirNames, dirIndices);
+ for (i = 0; i + 1 < numDirItems; i++)
+ {
+ const UString &s1 = dirNames[dirIndices[i]];
+ const UString &s2 = dirNames[dirIndices[i + 1]];
+ if (CompareFileNames(s1, s2) == 0)
+ ThrowError(k_Duplicate_inDir_Message, s1, s2);
+ }
+ }
+
+ unsigned dirIndex = 0;
+ unsigned arcIndex = 0;
+
+ int prevHostFile = -1;
+ const UString *prevHostName = NULL;
+
+ while (dirIndex < numDirItems || arcIndex < numArcItems)
+ {
+ CUpdatePair pair;
+
+ int dirIndex2 = -1;
+ int arcIndex2 = -1;
+ const CDirItem *di = NULL;
+ const CArcItem *ai = NULL;
+
+ int compareResult = -1;
+ const UString *name = NULL;
+
+ if (dirIndex < numDirItems)
+ {
+ dirIndex2 = dirIndices[dirIndex];
+ di = &dirItems.Items[dirIndex2];
+ }
+
+ if (arcIndex < numArcItems)
+ {
+ arcIndex2 = arcIndices[arcIndex];
+ ai = &arcItems[arcIndex2];
+ compareResult = 1;
+ if (dirIndex < numDirItems)
+ {
+ compareResult = CompareFileNames(dirNames[dirIndex2], ai->Name);
+ if (compareResult == 0)
+ {
+ if (di->IsDir() != ai->IsDir)
+ compareResult = (ai->IsDir ? 1 : -1);
+ }
+ }
+ }
+
+ if (compareResult < 0)
+ {
+ name = &dirNames[dirIndex2];
+ pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
+ pair.DirIndex = dirIndex2;
+ dirIndex++;
+ }
+ else if (compareResult > 0)
+ {
+ name = &ai->Name;
+ pair.State = ai->Censored ?
+ NUpdateArchive::NPairState::kOnlyInArchive:
+ NUpdateArchive::NPairState::kNotMasked;
+ pair.ArcIndex = arcIndex2;
+ arcIndex++;
+ }
+ else
+ {
+ int dupl = duplicatedArcItem[arcIndex];
+ if (dupl != 0)
+ ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[arcIndex + dupl]].Name);
+
+ name = &dirNames[dirIndex2];
+ if (!ai->Censored)
+ ThrowError(k_NotCensoredCollision_Message, *name, ai->Name);
+
+ pair.DirIndex = dirIndex2;
+ pair.ArcIndex = arcIndex2;
+
+ switch (ai->MTimeDefined ? MyCompareTime(
+ ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType,
+ di->MTime, ai->MTime): 0)
+ {
+ case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;
+ case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
+ default:
+ pair.State = (ai->SizeDefined && di->Size == ai->Size) ?
+ NUpdateArchive::NPairState::kSameFiles :
+ NUpdateArchive::NPairState::kUnknowNewerFiles;
+ }
+
+ dirIndex++;
+ arcIndex++;
+ }
+
+ if ((di && di->IsAltStream) ||
+ (ai && ai->IsAltStream))
+ {
+ if (prevHostName)
+ {
+ unsigned hostLen = prevHostName->Len();
+ if (name->Len() > hostLen)
+ if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0)
+ pair.HostIndex = prevHostFile;
+ }
+ }
+ else
+ {
+ prevHostFile = updatePairs.Size();
+ prevHostName = name;
+ }
+
+ updatePairs.Add(pair);
+ }
+
+ updatePairs.ReserveDown();
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.h
new file mode 100644
index 0000000000..36da243428
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.h
@@ -0,0 +1,27 @@
+// UpdatePair.h
+
+#ifndef __UPDATE_PAIR_H
+#define __UPDATE_PAIR_H
+
+#include "DirItem.h"
+#include "UpdateAction.h"
+
+#include "../../Archive/IArchive.h"
+
+struct CUpdatePair
+{
+ NUpdateArchive::NPairState::EEnum State;
+ int ArcIndex;
+ int DirIndex;
+ int HostIndex; // >= 0 for alt streams only, contains index of host pair
+
+ CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {}
+};
+
+void GetUpdatePairInfoList(
+ const CDirItems &dirItems,
+ const CObjectVector<CArcItem> &arcItems,
+ NFileTimeType::EEnum fileTimeType,
+ CRecordVector<CUpdatePair> &updatePairs);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.cpp
new file mode 100644
index 0000000000..c025ac4680
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -0,0 +1,70 @@
+// UpdateProduce.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateProduce.h"
+
+using namespace NUpdateArchive;
+
+static const char * const kUpdateActionSetCollision = "Internal collision in update action set";
+
+void UpdateProduce(
+ const CRecordVector<CUpdatePair> &updatePairs,
+ const CActionSet &actionSet,
+ CRecordVector<CUpdatePair2> &operationChain,
+ IUpdateProduceCallback *callback)
+{
+ FOR_VECTOR (i, updatePairs)
+ {
+ const CUpdatePair &pair = updatePairs[i];
+
+ CUpdatePair2 up2;
+ up2.DirIndex = pair.DirIndex;
+ up2.ArcIndex = pair.ArcIndex;
+ up2.NewData = up2.NewProps = true;
+ up2.UseArcProps = false;
+
+ switch (actionSet.StateActions[(unsigned)pair.State])
+ {
+ case NPairAction::kIgnore:
+ if (pair.ArcIndex >= 0 && callback)
+ callback->ShowDeleteFile(pair.ArcIndex);
+ continue;
+
+ case NPairAction::kCopy:
+ if (pair.State == NPairState::kOnlyOnDisk)
+ throw kUpdateActionSetCollision;
+ if (pair.State == NPairState::kOnlyInArchive)
+ {
+ if (pair.HostIndex >= 0)
+ {
+ /*
+ ignore alt stream if
+ 1) no such alt stream in Disk
+ 2) there is Host file in disk
+ */
+ if (updatePairs[pair.HostIndex].DirIndex >= 0)
+ continue;
+ }
+ }
+ up2.NewData = up2.NewProps = false;
+ up2.UseArcProps = true;
+ break;
+
+ case NPairAction::kCompress:
+ if (pair.State == NPairState::kOnlyInArchive ||
+ pair.State == NPairState::kNotMasked)
+ throw kUpdateActionSetCollision;
+ break;
+
+ case NPairAction::kCompressAsAnti:
+ up2.IsAnti = true;
+ up2.UseArcProps = (pair.ArcIndex >= 0);
+ break;
+ }
+
+ operationChain.Add(up2);
+ }
+
+ operationChain.ReserveDown();
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.h
new file mode 100644
index 0000000000..8467543839
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.h
@@ -0,0 +1,55 @@
+// UpdateProduce.h
+
+#ifndef __UPDATE_PRODUCE_H
+#define __UPDATE_PRODUCE_H
+
+#include "UpdatePair.h"
+
+struct CUpdatePair2
+{
+ bool NewData;
+ bool NewProps;
+ bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties.
+ bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status
+
+ int DirIndex;
+ int ArcIndex;
+ int NewNameIndex;
+
+ bool IsMainRenameItem;
+
+ void SetAs_NoChangeArcItem(int arcIndex)
+ {
+ NewData = NewProps = false;
+ UseArcProps = true;
+ IsAnti = false;
+ ArcIndex = arcIndex;
+ }
+
+ bool ExistOnDisk() const { return DirIndex != -1; }
+ bool ExistInArchive() const { return ArcIndex != -1; }
+
+ CUpdatePair2():
+ NewData(false),
+ NewProps(false),
+ UseArcProps(false),
+ IsAnti(false),
+ DirIndex(-1),
+ ArcIndex(-1),
+ NewNameIndex(-1),
+ IsMainRenameItem(false)
+ {}
+};
+
+struct IUpdateProduceCallback
+{
+ virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0;
+};
+
+void UpdateProduce(
+ const CRecordVector<CUpdatePair> &updatePairs,
+ const NUpdateArchive::CActionSet &actionSet,
+ CRecordVector<CUpdatePair2> &operationChain,
+ IUpdateProduceCallback *callback);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.cpp
new file mode 100644
index 0000000000..03d6eed107
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.cpp
@@ -0,0 +1,94 @@
+// WorkDir.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileName.h"
+
+#include "WorkDir.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName)
+{
+ NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (workDirInfo.ForRemovableOnly)
+ {
+ mode = NWorkDir::NMode::kCurrent;
+ FString prefix = path.Left(3);
+ if (prefix[1] == FTEXT(':') && prefix[2] == FTEXT('\\'))
+ {
+ UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP));
+ if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)
+ mode = workDirInfo.Mode;
+ }
+ /*
+ CParsedPath parsedPath;
+ parsedPath.ParsePath(archiveName);
+ UINT driveType = GetDriveType(parsedPath.Prefix);
+ if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE))
+ mode = NZipSettings::NWorkDir::NMode::kCurrent;
+ */
+ }
+ #endif
+
+ int pos = path.ReverseFind_PathSepar() + 1;
+ fileName = path.Ptr(pos);
+
+ switch (mode)
+ {
+ case NWorkDir::NMode::kCurrent:
+ {
+ return path.Left(pos);
+ }
+ case NWorkDir::NMode::kSpecified:
+ {
+ FString tempDir = workDirInfo.Path;
+ NName::NormalizeDirPathPrefix(tempDir);
+ return tempDir;
+ }
+ default:
+ {
+ FString tempDir;
+ if (!MyGetTempPath(tempDir))
+ throw 141717;
+ return tempDir;
+ }
+ }
+}
+
+HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath)
+{
+ NWorkDir::CInfo workDirInfo;
+ workDirInfo.Load();
+ FString namePart;
+ FString workDir = GetWorkDir(workDirInfo, originalPath, namePart);
+ CreateComplexDir(workDir);
+ CTempFile tempFile;
+ _outStreamSpec = new COutFileStream;
+ OutStream = _outStreamSpec;
+ if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File))
+ {
+ DWORD error = GetLastError();
+ return error ? error : E_FAIL;
+ }
+ _originalPath = originalPath;
+ return S_OK;
+}
+
+HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal)
+{
+ OutStream.Release();
+ if (!_tempFile.MoveTo(_originalPath, deleteOriginal))
+ {
+ DWORD error = GetLastError();
+ return error ? error : E_FAIL;
+ }
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.h
new file mode 100644
index 0000000000..13d4ed9fea
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.h
@@ -0,0 +1,26 @@
+// WorkDir.h
+
+#ifndef __WORK_DIR_H
+#define __WORK_DIR_H
+
+#include "../../../Windows/FileDir.h"
+
+#include "../../Common/FileStreams.h"
+
+#include "ZipRegistry.h"
+
+FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName);
+
+class CWorkDirTempFile
+{
+ FString _originalPath;
+ NWindows::NFile::NDir::CTempFile _tempFile;
+ COutFileStream *_outStreamSpec;
+public:
+ CMyComPtr<IOutStream> OutStream;
+
+ HRESULT CreateTempFile(const FString &originalPath);
+ HRESULT MoveToOriginal(bool deleteOriginal);
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Common/ZipRegistry.h b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ZipRegistry.h
new file mode 100644
index 0000000000..4c16b61c48
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Common/ZipRegistry.h
@@ -0,0 +1,130 @@
+// ZipRegistry.h
+
+#ifndef __ZIP_REGISTRY_H
+#define __ZIP_REGISTRY_H
+
+#include "../../../Common/MyTypes.h"
+#include "../../../Common/MyString.h"
+
+#include "ExtractMode.h"
+
+namespace NExtract
+{
+ struct CInfo
+ {
+ NPathMode::EEnum PathMode;
+ NOverwriteMode::EEnum OverwriteMode;
+ bool PathMode_Force;
+ bool OverwriteMode_Force;
+
+ CBoolPair SplitDest;
+ CBoolPair ElimDup;
+ // CBoolPair AltStreams;
+ CBoolPair NtSecurity;
+ CBoolPair ShowPassword;
+
+ UStringVector Paths;
+
+ void Save() const;
+ void Load();
+ };
+
+ void Save_ShowPassword(bool showPassword);
+ bool Read_ShowPassword();
+}
+
+namespace NCompression
+{
+ struct CFormatOptions
+ {
+ UInt32 Level;
+ UInt32 Dictionary;
+ UInt32 Order;
+ UInt32 BlockLogSize;
+ UInt32 NumThreads;
+
+ CSysString FormatID;
+ UString Method;
+ UString Options;
+ UString EncryptionMethod;
+
+ void Reset_BlockLogSize()
+ {
+ BlockLogSize = (UInt32)(Int32)-1;
+ }
+
+ void ResetForLevelChange()
+ {
+ BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1;
+ Method.Empty();
+ // Options.Empty();
+ // EncryptionMethod.Empty();
+ }
+ CFormatOptions() { ResetForLevelChange(); }
+ };
+
+ struct CInfo
+ {
+ UInt32 Level;
+ bool ShowPassword;
+ bool EncryptHeaders;
+ UString ArcType;
+ UStringVector ArcPaths;
+
+ CObjectVector<CFormatOptions> Formats;
+
+ CBoolPair NtSecurity;
+ CBoolPair AltStreams;
+ CBoolPair HardLinks;
+ CBoolPair SymLinks;
+
+ void Save() const;
+ void Load();
+ };
+}
+
+namespace NWorkDir
+{
+ namespace NMode
+ {
+ enum EEnum
+ {
+ kSystem,
+ kCurrent,
+ kSpecified
+ };
+ }
+ struct CInfo
+ {
+ NMode::EEnum Mode;
+ FString Path;
+ bool ForRemovableOnly;
+
+ void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }
+ void SetDefault()
+ {
+ Mode = NMode::kSystem;
+ Path.Empty();
+ SetForRemovableOnlyDefault();
+ }
+
+ void Save() const;
+ void Load();
+ };
+}
+
+
+struct CContextMenuInfo
+{
+ CBoolPair Cascaded;
+ CBoolPair MenuIcons;
+ CBoolPair ElimDup;
+
+ bool Flags_Def;
+ UInt32 Flags;
+
+ void Save() const;
+ void Load();
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.cpp
new file mode 100644
index 0000000000..9cf8dd6dc9
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.cpp
@@ -0,0 +1,41 @@
+// BenchCon.cpp
+
+#include "StdAfx.h"
+
+#include "../Common/Bench.h"
+
+#include "BenchCon.h"
+#include "ConsoleClose.h"
+
+struct CPrintBenchCallback: public IBenchPrintCallback
+{
+ FILE *_file;
+
+ void Print(const char *s);
+ void NewLine();
+ HRESULT CheckBreak();
+};
+
+void CPrintBenchCallback::Print(const char *s)
+{
+ fputs(s, _file);
+}
+
+void CPrintBenchCallback::NewLine()
+{
+ fputc('\n', _file);
+}
+
+HRESULT CPrintBenchCallback::CheckBreak()
+{
+ return NConsoleClose::TestBreakSignal() ? E_ABORT: S_OK;
+}
+
+HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS
+ const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f)
+{
+ CPrintBenchCallback callback;
+ callback._file = f;
+ return Bench(EXTERNAL_CODECS_LOC_VARS
+ &callback, NULL, props, numIterations, true);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.h
new file mode 100644
index 0000000000..ef235eea31
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.h
@@ -0,0 +1,14 @@
+// BenchCon.h
+
+#ifndef __BENCH_CON_H
+#define __BENCH_CON_H
+
+#include <stdio.h>
+
+#include "../../Common/CreateCoder.h"
+#include "../../UI/Common/Property.h"
+
+HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS
+ const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.mak b/other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.mak
new file mode 100644
index 0000000000..6757e6b442
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.mak
@@ -0,0 +1,36 @@
+CONSOLE_OBJS = \
+ $O\BenchCon.obj \
+ $O\ConsoleClose.obj \
+ $O\ExtractCallbackConsole.obj \
+ $O\HashCon.obj \
+ $O\List.obj \
+ $O\Main.obj \
+ $O\MainAr.obj \
+ $O\OpenCallbackConsole.obj \
+ $O\PercentPrinter.obj \
+ $O\UpdateCallbackConsole.obj \
+ $O\UserInputUtils.obj \
+
+UI_COMMON_OBJS = \
+ $O\ArchiveCommandLine.obj \
+ $O\ArchiveExtractCallback.obj \
+ $O\ArchiveOpenCallback.obj \
+ $O\Bench.obj \
+ $O\DefaultName.obj \
+ $O\EnumDirItems.obj \
+ $O\Extract.obj \
+ $O\ExtractingFilePath.obj \
+ $O\HashCalc.obj \
+ $O\LoadCodecs.obj \
+ $O\OpenArchive.obj \
+ $O\PropIDUtils.obj \
+ $O\SetProperties.obj \
+ $O\SortUtils.obj \
+ $O\TempFiles.obj \
+ $O\Update.obj \
+ $O\UpdateAction.obj \
+ $O\UpdateCallback.obj \
+ $O\UpdatePair.obj \
+ $O\UpdateProduce.obj \
+
+#
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.manifest b/other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.manifest
new file mode 100644
index 0000000000..77ecaad72d
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.manifest
@@ -0,0 +1,13 @@
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7z" type="win32"></assemblyIdentity>
+<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+<security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false">
+</requestedExecutionLevel></requestedPrivileges></security></trustInfo>
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
+<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+</application></compatibility>
+</assembly> \ No newline at end of file
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.cpp
new file mode 100644
index 0000000000..a6f17af930
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.cpp
@@ -0,0 +1,69 @@
+// ConsoleClose.cpp
+
+#include "StdAfx.h"
+
+#include "ConsoleClose.h"
+
+#if !defined(UNDER_CE) && defined(_WIN32)
+#include "../../../Common/MyWindows.h"
+#endif
+
+namespace NConsoleClose {
+
+unsigned g_BreakCounter = 0;
+static const unsigned kBreakAbortThreshold = 2;
+
+#if !defined(UNDER_CE) && defined(_WIN32)
+static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
+{
+ if (ctrlType == CTRL_LOGOFF_EVENT)
+ {
+ // printf("\nCTRL_LOGOFF_EVENT\n");
+ return TRUE;
+ }
+
+ g_BreakCounter++;
+ if (g_BreakCounter < kBreakAbortThreshold)
+ return TRUE;
+ return FALSE;
+ /*
+ switch (ctrlType)
+ {
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+ if (g_BreakCounter < kBreakAbortThreshold)
+ return TRUE;
+ }
+ return FALSE;
+ */
+}
+#endif
+
+/*
+void CheckCtrlBreak()
+{
+ if (TestBreakSignal())
+ throw CCtrlBreakException();
+}
+*/
+
+CCtrlHandlerSetter::CCtrlHandlerSetter()
+{
+ #if !defined(UNDER_CE) && defined(_WIN32)
+ if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE))
+ throw "SetConsoleCtrlHandler fails";
+ #endif
+}
+
+CCtrlHandlerSetter::~CCtrlHandlerSetter()
+{
+ #if !defined(UNDER_CE) && defined(_WIN32)
+ if (!SetConsoleCtrlHandler(HandlerRoutine, FALSE))
+ {
+ // warning for throw in destructor.
+ // throw "SetConsoleCtrlHandler fails";
+ }
+ #endif
+}
+
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.h
new file mode 100644
index 0000000000..0a0bbf0e0a
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.h
@@ -0,0 +1,33 @@
+// ConsoleClose.h
+
+#ifndef __CONSOLE_CLOSE_H
+#define __CONSOLE_CLOSE_H
+
+namespace NConsoleClose {
+
+extern unsigned g_BreakCounter;
+
+inline bool TestBreakSignal()
+{
+ #ifdef UNDER_CE
+ return false;
+ #else
+ return (g_BreakCounter != 0);
+ #endif
+}
+
+class CCtrlHandlerSetter
+{
+public:
+ CCtrlHandlerSetter();
+ virtual ~CCtrlHandlerSetter();
+};
+
+class CCtrlBreakException
+{};
+
+// void CheckCtrlBreak();
+
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
new file mode 100644
index 0000000000..bdf954998c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -0,0 +1,825 @@
+// ExtractCallbackConsole.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/TimeUtils.h"
+#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 HRESULT CheckBreak2()
+{
+ return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
+}
+
+static const char * const 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;
+ _se->NormalizePrint_UString(fs2us(path));
+ *_se << 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 PrintSize_bytes_Smart_comma(AString &s, UInt64 val)
+{
+ if (val == (UInt64)(Int64)-1)
+ return;
+ s += ", ";
+ PrintSize_bytes_Smart(s, val);
+}
+
+
+
+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");
+ PrintSize_bytes_Smart_comma(s, st.FilesSize);
+ if (st.NumAltStreams != 0)
+ {
+ s.Add_LF();
+ Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams");
+ PrintSize_bytes_Smart_comma(s, st.AltStreamsSize);
+ }
+}
+
+
+void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st)
+{
+ Print_DirItemsStat(s, (CDirItemsStat &)st);
+ bool needLF = true;
+ if (st.Anti_NumDirs != 0)
+ {
+ if (needLF)
+ s.Add_LF();
+ needLF = false;
+ Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? "anti-folder" : "anti-folders");
+ }
+ if (st.Anti_NumFiles != 0)
+ {
+ if (needLF)
+ s.Add_LF();
+ else
+ s += ", ";
+ needLF = false;
+ Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? "anti-file" : "anti-files");
+ }
+ if (st.Anti_NumAltStreams != 0)
+ {
+ if (needLF)
+ s.Add_LF();
+ else
+ s += ", ";
+ needLF = false;
+ Print_UInt64_and_String(s, st.Anti_NumAltStreams, "anti-alternate-streams");
+ }
+}
+
+
+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 * const kTestString = "T";
+static const char * const kExtractString = "-";
+static const char * const kSkipString = ".";
+
+// static const char * const kCantAutoRename = "can not create file with auto name\n";
+// static const char * const kCantRenameFile = "can not rename existing file\n";
+// static const char * const kCantDeleteOutputFile = "can not delete output file ";
+
+static const char * const kMemoryExceptionMessage = "Can't allocate required memory!";
+
+static const char * const kExtracting = "Extracting archive: ";
+static const char * const kTesting = "Testing archive: ";
+
+static const char * const kEverythingIsOk = "Everything is Ok";
+static const char * const kNoFiles = "No files to process";
+
+static const char * const kUnsupportedMethod = "Unsupported Method";
+static const char * const kCrcFailed = "CRC Failed";
+static const char * const kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
+static const char * const kDataError = "Data Error";
+static const char * const kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
+static const char * const kUnavailableData = "Unavailable data";
+static const char * const kUnexpectedEnd = "Unexpected end of data";
+static const char * const kDataAfterEnd = "There are some data after the end of the payload data";
+static const char * const kIsNotArc = "Is not archive";
+static const char * const kHeadersError = "Headers Error";
+static const char * const kWrongPassword = "Wrong password";
+
+static const char * const k_ErrorFlagsMessages[] =
+{
+ "Is not archive"
+ , "Headers Error"
+ , "Headers Error in encrypted archive. Wrong password?"
+ , "Unavailable start of archive"
+ , "Unconfirmed start of archive"
+ , "Unexpected end of archive"
+ , "There are data after the end of archive"
+ , "Unsupported method"
+ , "Unsupported feature"
+ , "Data Error"
+ , "CRC Error"
+};
+
+STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size)
+{
+ MT_LOCK
+
+ if (NeedPercents())
+ {
+ _percent.Total = size;
+ _percent.Print();
+ }
+ return CheckBreak2();
+}
+
+STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)
+{
+ MT_LOCK
+
+ if (NeedPercents())
+ {
+ if (completeValue)
+ _percent.Completed = *completeValue;
+ _percent.Print();
+ }
+ return CheckBreak2();
+}
+
+static const char * const kTab = " ";
+
+static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)
+{
+ *_so << kTab << "Path: ";
+ _so->NormalizePrint_wstr(path);
+ *_so << endl;
+ if (size && *size != (UInt64)(Int64)-1)
+ {
+ AString s;
+ PrintSize_bytes_Smart(s, *size);
+ *_so << kTab << "Size: " << s << endl;
+ }
+ if (ft)
+ {
+ char temp[64];
+ if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC))
+ *_so << kTab << "Modified: " << temp << endl;
+ }
+}
+
+STDMETHODIMP CExtractCallbackConsole::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
+
+ 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)
+ {
+ case NUserAnswerMode::kQuit: return E_ABORT;
+ case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break;
+ case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break;
+ case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;
+ case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break;
+ case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;
+ case NUserAnswerMode::kEof: return E_ABORT;
+ case NUserAnswerMode::kError: return E_FAIL;
+ default: return E_FAIL;
+ }
+
+ if (_so)
+ {
+ *_so << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
+
+ return CheckBreak2();
+}
+
+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; requiredLevel = 2; break;
+ default: s = "???"; requiredLevel = 2;
+ };
+
+ 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->Normalize_UString(_tempU);
+ }
+ _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)
+{
+ MT_LOCK
+
+ RINOK(CheckBreak2());
+
+ NumFileErrors_in_Current++;
+ NumFileErrors++;
+
+ ClosePercentsAndFlush();
+ if (_se)
+ {
+ *_se << kError << message << endl;
+ _se->Flush();
+ }
+
+ return CheckBreak2();
+}
+
+void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)
+{
+ 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
+ {
+ dest += "Error #";
+ dest.Add_UInt32(opRes);
+ }
+}
+
+STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted)
+{
+ MT_LOCK
+
+ if (opRes == NArchive::NExtract::NOperationResult::kOK)
+ {
+ if (NeedPercents())
+ {
+ _percent.Command.Empty();
+ _percent.FileName.Empty();
+ _percent.Files++;
+ }
+ }
+ else
+ {
+ NumFileErrors_in_Current++;
+ NumFileErrors++;
+
+ if (_se)
+ {
+ ClosePercentsAndFlush();
+
+ AString s;
+ SetExtractErrorMessage(opRes, encrypted, s);
+
+ *_se << s;
+ if (!_currentName.IsEmpty())
+ {
+ *_se << " : ";
+ _se->NormalizePrint_UString(_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)
+{
+ PasswordIsDefined = true;
+ Password = password;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+ MT_LOCK
+ return Open_CryptoGetTextPassword(password);
+ COM_TRY_END
+}
+
+#endif
+
+HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)
+{
+ RINOK(CheckBreak2());
+
+ NumTryArcs++;
+ ThereIsError_in_Current = false;
+ ThereIsWarning_in_Current = false;
+ NumFileErrors_in_Current = 0;
+
+ ClosePercents_for_so();
+ if (_so)
+ {
+ *_so << endl << (testMode ? kTesting : kExtracting);
+ _so->NormalizePrint_wstr(name);
+ *_so << endl;
+ }
+
+ if (NeedPercents())
+ _percent.Command = "Open";
+ return 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);
+
+static AString GetOpenArcErrorMessage(UInt32 errorFlags)
+{
+ AString s;
+
+ for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++)
+ {
+ UInt32 f = (1 << i);
+ if ((errorFlags & f) == 0)
+ continue;
+ const char *m = k_ErrorFlagsMessages[i];
+ if (!s.IsEmpty())
+ s.Add_LF();
+ s += m;
+ errorFlags &= ~f;
+ }
+
+ if (errorFlags != 0)
+ {
+ char sz[16];
+ sz[0] = '0';
+ sz[1] = 'x';
+ ConvertUInt32ToHex(errorFlags, sz + 2);
+ if (!s.IsEmpty())
+ 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 += pre;
+ s += " as [";
+ s += arcType;
+ s += "] archive";
+}
+
+void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc)
+{
+ const CArcErrorInfo &er = arc.ErrorInfo;
+
+ *_so << "WARNING:\n";
+ _so->NormalizePrint_UString(arc.Path);
+ UString s;
+ if (arc.FormatIndex == er.ErrorFormatIndex)
+ {
+ s.Add_LF();
+ s += "The archive is open with offset";
+ }
+ else
+ {
+ 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 (NeedPercents())
+ {
+ _percent.Files = 0;
+ _percent.Command.Empty();
+ _percent.FileName.Empty();
+ }
+
+
+ ClosePercentsAndFlush();
+
+ FOR_VECTOR (level, arcLink.Arcs)
+ {
+ 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->NormalizePrint_UString(arc.Path);
+ *_se << 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->NormalizePrint_UString(arc.Path);
+ *_so << 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 (er.ErrorFormatIndex >= 0)
+ {
+ if (_so)
+ {
+ Print_ErrorFormatIndex_Warning(_so, codecs, arc);
+ if (NeedFlush)
+ _so->Flush();
+ }
+ ThereIsWarning_in_Current = true;
+ }
+ }
+
+ if (result == S_OK)
+ {
+ if (_so)
+ {
+ RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
+ *_so << endl;
+ }
+ }
+ else
+ {
+ NumCantOpenArcs++;
+ if (_so)
+ _so->Flush();
+ if (_se)
+ {
+ *_se << kError;
+ _se->NormalizePrint_wstr(name);
+ *_se << 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()
+{
+ ClosePercents_for_so();
+
+ if (_so)
+ {
+ *_so << endl << kNoFiles << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
+ return CheckBreak2();
+}
+
+HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
+{
+ MT_LOCK
+
+ if (NeedPercents())
+ {
+ _percent.ClosePrint(true);
+ _percent.Command.Empty();
+ _percent.FileName.Empty();
+ }
+
+ if (_so)
+ _so->Flush();
+
+ if (result == S_OK)
+ {
+ if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current)
+ {
+ if (ThereIsWarning_in_Current)
+ NumArcsWithWarnings++;
+ else
+ NumOkArcs++;
+ if (_so)
+ *_so << kEverythingIsOk << endl;
+ }
+ else
+ {
+ NumArcsWithError++;
+ if (_so)
+ {
+ *_so << endl;
+ if (NumFileErrors_in_Current != 0)
+ *_so << "Sub items Errors: " << NumFileErrors_in_Current << endl;
+ }
+ }
+ if (_so && NeedFlush)
+ _so->Flush();
+ }
+ else
+ {
+ 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();
+ }
+ }
+
+ return CheckBreak2();
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.h
new file mode 100644
index 0000000000..5de6c5b2a2
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.h
@@ -0,0 +1,164 @@
+// ExtractCallbackConsole.h
+
+#ifndef __EXTRACT_CALLBACK_CONSOLE_H
+#define __EXTRACT_CALLBACK_CONSOLE_H
+
+#include "../../../Common/StdOutStream.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
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ STDMETHOD(SetTotal)(UInt64 total);
+ STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+ INTERFACE_IFolderArchiveExtractCallback(;)
+
+ INTERFACE_IExtractCallbackUI(;)
+ // INTERFACE_IArchiveExtractCallbackMessage(;)
+ INTERFACE_IFolderArchiveExtractCallback2(;)
+
+ #ifndef _NO_CRYPTO
+
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+ #endif
+
+ UInt64 NumTryArcs;
+
+ bool ThereIsError_in_Current;
+ bool ThereIsWarning_in_Current;
+
+ UInt64 NumOkArcs;
+ UInt64 NumCantOpenArcs;
+ UInt64 NumArcsWithError;
+ UInt64 NumArcsWithWarnings;
+
+ UInt64 NumOpenArcErrors;
+ UInt64 NumOpenArcWarnings;
+
+ UInt64 NumFileErrors;
+ UInt64 NumFileErrors_in_Current;
+
+ bool NeedFlush;
+ unsigned PercentsNameLevel;
+ unsigned LogLevel;
+
+ 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;
+ NumArcsWithWarnings = 0;
+
+ NumOpenArcErrors = 0;
+ NumOpenArcWarnings = 0;
+
+ NumFileErrors = 0;
+ NumFileErrors_in_Current = 0;
+ }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.cpp
new file mode 100644
index 0000000000..ec8e6dca94
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.cpp
@@ -0,0 +1,367 @@
+// HashCon.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+
+#include "ConsoleClose.h"
+#include "HashCon.h"
+
+static const char * const kEmptyFileAlias = "[Content]";
+
+static const char * const kScanningMessage = "Scanning";
+
+static HRESULT CheckBreak2()
+{
+ return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
+}
+
+HRESULT CHashCallbackConsole::CheckBreak()
+{
+ return CheckBreak2();
+}
+
+HRESULT CHashCallbackConsole::StartScanning()
+{
+ if (PrintHeaders && _so)
+ *_so << kScanningMessage << endl;
+ if (NeedPercents())
+ {
+ _percent.ClearCurState();
+ _percent.Command = "Scan";
+ }
+ return CheckBreak2();
+}
+
+HRESULT CHashCallbackConsole::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 CheckBreak2();
+}
+
+HRESULT CHashCallbackConsole::ScanError(const FString &path, DWORD systemError)
+{
+ return ScanError_Base(path, systemError);
+}
+
+void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
+
+HRESULT CHashCallbackConsole::FinishScanning(const CDirItemsStat &st)
+{
+ 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 CheckBreak2();
+}
+
+HRESULT CHashCallbackConsole::SetTotal(UInt64 size)
+{
+ if (NeedPercents())
+ {
+ _percent.Total = size;
+ _percent.Print();
+ }
+ return CheckBreak2();
+}
+
+HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue)
+{
+ if (completeValue && NeedPercents())
+ {
+ _percent.Completed = *completeValue;
+ _percent.Print();
+ }
+ return CheckBreak2();
+}
+
+static void AddMinuses(AString &s, unsigned num)
+{
+ for (unsigned i = 0; i < num; i++)
+ s += '-';
+}
+
+static void AddSpaces_if_Positive(AString &s, int num)
+{
+ for (int i = 0; i < num; i++)
+ s.Add_Space();
+}
+
+static void SetSpacesAndNul(char *s, unsigned num)
+{
+ for (unsigned i = 0; i < num; i++)
+ s[i] = ' ';
+ s[num] = 0;
+}
+
+static const unsigned kSizeField_Len = 13;
+static const unsigned kNameField_Len = 12;
+
+static const unsigned kHashColumnWidth_Min = 4 * 2;
+
+static unsigned GetColumnWidth(unsigned digestSize)
+{
+ unsigned width = digestSize * 2;
+ return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width;
+}
+
+void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers)
+{
+ _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));
+ }
+
+ if (PrintSize)
+ {
+ _s.Add_Space();
+ AddMinuses(_s, kSizeField_Len);
+ }
+
+ if (PrintName)
+ {
+ AddSpacesBeforeName();
+ AddMinuses(_s, kNameField_Len);
+ }
+
+ *_so << _s << endl;
+}
+
+HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb)
+{
+ if (PrintHeaders && _so)
+ {
+ _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);
+ }
+
+ return CheckBreak2();
+}
+
+HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
+{
+ return OpenFileError_Base(path, systemError);
+}
+
+HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */)
+{
+ _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));
+ if (i != 0)
+ _s.Add_Space();
+ _s += s;
+ }
+
+ if (PrintSize)
+ {
+ _s.Add_Space();
+
+ char s[kSizeField_Len + 32];
+ char *p = s;
+
+ if (showHash)
+ {
+ 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;
+ }
+
+ if (PrintName)
+ AddSpacesBeforeName();
+
+ *_so << _s;
+}
+
+HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash)
+{
+ if (_so)
+ {
+ PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash);
+ if (PrintName)
+ {
+ if (_fileName.IsEmpty())
+ *_so << kEmptyFileAlias;
+ else
+ _so->NormalizePrint_UString(_fileName);
+ }
+ *_so << endl;
+ }
+
+ if (NeedPercents())
+ {
+ _percent.Files++;
+ _percent.Print();
+ }
+
+ return CheckBreak2();
+}
+
+static const char * const k_DigestTitles[] =
+{
+ " : "
+ , " for data: "
+ , " for data and names: "
+ , " for streams and names: "
+};
+
+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];
+ s[0] = 0;
+ AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
+ so << s << endl;
+}
+
+void PrintHashStat(CStdOutStream &so, const CHashBundle &hb)
+{
+ FOR_VECTOR (i, hb.Hashers)
+ {
+ const CHasherState &h = hb.Hashers[i];
+ PrintSum(so, h, k_HashCalc_Index_DataSum);
+ if (hb.NumFiles != 1 || hb.NumDirs != 0)
+ PrintSum(so, h, k_HashCalc_Index_NamesSum);
+ if (hb.NumAltStreams != 0)
+ PrintSum(so, h, k_HashCalc_Index_StreamsSum);
+ so << endl;
+ }
+}
+
+void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value)
+{
+ char s[32];
+ s[0] = ':';
+ s[1] = ' ';
+ ConvertUInt64ToString(value, s + 2);
+ *_so << name << s << endl;
+}
+
+HRESULT CHashCallbackConsole::AfterLastFile(const CHashBundle &hb)
+{
+ ClosePercents2();
+
+ if (PrintHeaders && _so)
+ {
+ 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);
+ }
+
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.h
new file mode 100644
index 0000000000..9c12869eb6
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.h
@@ -0,0 +1,48 @@
+// HashCon.h
+
+#ifndef __HASH_CON_H
+#define __HASH_CON_H
+
+#include "../Common/HashCalc.h"
+
+#include "UpdateCallbackConsole.h"
+
+class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase
+{
+ 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 &so, const CHashBundle &hb);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/List.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/List.cpp
new file mode 100644
index 0000000000..ebcabb6853
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/List.cpp
@@ -0,0 +1,1349 @@
+// List.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/MyCom.h"
+#include "../../../Common/StdOutStream.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/UTFConvert.h"
+
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
+
+#include "../Common/OpenArchive.h"
+#include "../Common/PropIDUtils.h"
+
+#include "ConsoleClose.h"
+#include "List.h"
+#include "OpenCallbackConsole.h"
+
+using namespace NWindows;
+using namespace NCOM;
+
+extern CStdOutStream *g_StdStream;
+extern CStdOutStream *g_ErrStream;
+
+static const char * const kPropIdToName[] =
+{
+ "0"
+ , "1"
+ , "2"
+ , "Path"
+ , "Name"
+ , "Extension"
+ , "Folder"
+ , "Size"
+ , "Packed Size"
+ , "Attributes"
+ , "Created"
+ , "Accessed"
+ , "Modified"
+ , "Solid"
+ , "Commented"
+ , "Encrypted"
+ , "Split Before"
+ , "Split After"
+ , "Dictionary Size"
+ , "CRC"
+ , "Type"
+ , "Anti"
+ , "Method"
+ , "Host OS"
+ , "File System"
+ , "User"
+ , "Group"
+ , "Block"
+ , "Comment"
+ , "Position"
+ , "Path Prefix"
+ , "Folders"
+ , "Files"
+ , "Version"
+ , "Volume"
+ , "Multivolume"
+ , "Offset"
+ , "Links"
+ , "Blocks"
+ , "Volumes"
+ , "Time Type"
+ , "64-bit"
+ , "Big-endian"
+ , "CPU"
+ , "Physical Size"
+ , "Headers Size"
+ , "Checksum"
+ , "Characteristics"
+ , "Virtual Address"
+ , "ID"
+ , "Short Name"
+ , "Creator Application"
+ , "Sector Size"
+ , "Mode"
+ , "Symbolic Link"
+ , "Error"
+ , "Total Size"
+ , "Free Space"
+ , "Cluster Size"
+ , "Label"
+ , "Local Name"
+ , "Provider"
+ , "NT Security"
+ , "Alternate Stream"
+ , "Aux"
+ , "Deleted"
+ , "Tree"
+ , "SHA-1"
+ , "SHA-256"
+ , "Error Type"
+ , "Errors"
+ , "Errors"
+ , "Warnings"
+ , "Warning"
+ , "Streams"
+ , "Alternate Streams"
+ , "Alternate Streams Size"
+ , "Virtual Size"
+ , "Unpack Size"
+ , "Total Physical Size"
+ , "Volume Index"
+ , "SubType"
+ , "Short Comment"
+ , "Code Page"
+ , "Is not archive type"
+ , "Physical Size can't be detected"
+ , "Zeros Tail Is Allowed"
+ , "Tail Size"
+ , "Embedded Stub Size"
+ , "Link"
+ , "Hard Link"
+ , "iNode"
+ , "Stream ID"
+ , "Read-only"
+ , "Out Name"
+ , "Copy Link"
+};
+
+static const char kEmptyAttribChar = '.';
+
+static const char * const kListing = "Listing archive: ";
+
+static const char * const kString_Files = "files";
+static const char * const kString_Dirs = "folders";
+static const char * const kString_AltStreams = "alternate streams";
+static const char * const kString_Streams = "streams";
+
+static const char * const kError = "ERROR: ";
+
+static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s)
+{
+ if (isDir)
+ wa |= FILE_ATTRIBUTE_DIRECTORY;
+ if (allAttribs)
+ {
+ ConvertWinAttribToString(s, wa);
+ return;
+ }
+ s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0) ? 'D': kEmptyAttribChar;
+ s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar;
+ s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar;
+ s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar;
+ s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar;
+ s[5] = 0;
+}
+
+enum EAdjustment
+{
+ kLeft,
+ kCenter,
+ kRight
+};
+
+struct CFieldInfo
+{
+ PROPID PropID;
+ bool IsRawProp;
+ UString NameU;
+ AString NameA;
+ EAdjustment TitleAdjustment;
+ EAdjustment TextAdjustment;
+ unsigned PrefixSpacesWidth;
+ unsigned Width;
+};
+
+struct CFieldInfoInit
+{
+ PROPID PropID;
+ const char *Name;
+ EAdjustment TitleAdjustment;
+ EAdjustment TextAdjustment;
+ unsigned PrefixSpacesWidth;
+ unsigned Width;
+};
+
+static const CFieldInfoInit kStandardFieldTable[] =
+{
+ { kpidMTime, " Date Time", kLeft, kLeft, 0, 19 },
+ { kpidAttrib, "Attr", kRight, kCenter, 1, 5 },
+ { kpidSize, "Size", kRight, kRight, 1, 12 },
+ { kpidPackSize, "Compressed", kRight, kRight, 1, 12 },
+ { kpidPath, "Name", kLeft, kLeft, 2, 24 }
+};
+
+const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width
+static const char *g_Spaces =
+" " ;
+
+static void PrintSpaces(unsigned numSpaces)
+{
+ if (numSpaces > 0 && numSpaces <= kNumSpacesMax)
+ g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces);
+}
+
+static void PrintSpacesToString(char *dest, unsigned numSpaces)
+{
+ unsigned i;
+ for (i = 0; i < numSpaces; i++)
+ dest[i] = ' ';
+ dest[i] = 0;
+}
+
+// extern int g_CodePage;
+
+static void PrintUString(EAdjustment adj, unsigned width, const UString &s, AString &temp)
+{
+ /*
+ // 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())
+ {
+ 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;
+ }
+
+ g_StdOut.PrintUString(s, temp);
+ PrintSpaces(numSpaces);
+}
+
+static void PrintString(EAdjustment adj, unsigned width, const char *s)
+{
+ unsigned numSpaces = 0;
+ unsigned len = (unsigned)strlen(s);
+
+ if (width > len)
+ {
+ 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;
+ }
+
+ g_StdOut << s;
+ PrintSpaces(numSpaces);
+}
+
+static void PrintStringToString(char *dest, EAdjustment adj, unsigned width, const char *textString)
+{
+ unsigned numSpaces = 0;
+ unsigned len = (unsigned)strlen(textString);
+
+ if (width > len)
+ {
+ 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);
+}
+
+struct CListUInt64Def
+{
+ UInt64 Val;
+ bool Def;
+
+ CListUInt64Def(): Val(0), Def(false) {}
+ void Add(UInt64 v) { Val += v; Def = true; }
+ void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); }
+};
+
+struct CListFileTimeDef
+{
+ FILETIME Val;
+ bool Def;
+
+ CListFileTimeDef(): Def(false) { Val.dwLowDateTime = 0; Val.dwHighDateTime = 0; }
+ void Update(const CListFileTimeDef &t)
+ {
+ if (t.Def && (!Def || CompareFileTime(&Val, &t.Val) < 0))
+ {
+ Val = t.Val;
+ Def = true;
+ }
+ }
+};
+
+struct CListStat
+{
+ CListUInt64Def Size;
+ CListUInt64Def PackSize;
+ CListFileTimeDef MTime;
+ UInt64 NumFiles;
+
+ CListStat(): NumFiles(0) {}
+ void Update(const CListStat &st)
+ {
+ Size.Add(st.Size);
+ PackSize.Add(st.PackSize);
+ MTime.Update(st.MTime);
+ NumFiles += st.NumFiles;
+ }
+ void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; }
+};
+
+struct CListStat2
+{
+ CListStat MainFiles;
+ CListStat AltStreams;
+ UInt64 NumDirs;
+
+ CListStat2(): NumDirs(0) {}
+
+ void Update(const CListStat2 &st)
+ {
+ 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; }
+};
+
+class CFieldPrinter
+{
+ CObjectVector<CFieldInfo> _fields;
+
+ void AddProp(const wchar_t *name, PROPID propID, bool isRawProp);
+public:
+ const CArc *Arc;
+ bool TechMode;
+ UString FilePath;
+ AString TempAString;
+ UString TempWString;
+ bool IsDir;
+
+ AString LinesString;
+
+ void Clear() { _fields.Clear(); LinesString.Empty(); }
+ 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 &st);
+ void PrintSum(const CListStat &st, UInt64 numDirs, const char *str);
+ void PrintSum(const CListStat2 &stat2);
+};
+
+void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, unsigned numItems)
+{
+ Clear();
+ for (unsigned i = 0; i < numItems; i++)
+ {
+ CFieldInfo &f = _fields.AddNew();
+ const CFieldInfoInit &fii = standardFieldTable[i];
+ f.PropID = fii.PropID;
+ f.IsRawProp = false;
+ f.NameA = fii.Name;
+ f.TitleAdjustment = fii.TitleAdjustment;
+ f.TextAdjustment = fii.TextAdjustment;
+ f.PrefixSpacesWidth = fii.PrefixSpacesWidth;
+ f.Width = fii.Width;
+
+ unsigned k;
+ for (k = 0; k < fii.PrefixSpacesWidth; k++)
+ LinesString.Add_Space();
+ for (k = 0; k < fii.Width; k++)
+ LinesString += '-';
+ }
+}
+
+static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU)
+{
+ if (propID < ARRAY_SIZE(kPropIdToName))
+ {
+ nameA = kPropIdToName[propID];
+ return;
+ }
+ if (name)
+ nameU = name;
+ else
+ {
+ nameA.Empty();
+ nameA.Add_UInt32(propID);
+ }
+}
+
+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 += " = ";
+ if (!f.NameA.IsEmpty())
+ f.NameA += " = ";
+ else
+ {
+ const UString &s = f.NameU;
+ AString sA;
+ unsigned i;
+ for (i = 0; i < s.Len(); i++)
+ {
+ wchar_t c = s[i];
+ if (c >= 0x80)
+ break;
+ sA += (char)c;
+ }
+ if (i == s.Len())
+ f.NameA = sA;
+ }
+ _fields.Add(f);
+}
+
+HRESULT CFieldPrinter::AddMainProps(IInArchive *archive)
+{
+ UInt32 numProps;
+ RINOK(archive->GetNumberOfProperties(&numProps));
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ VARTYPE vt;
+ RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));
+ AddProp(name, propID, false);
+ }
+ return S_OK;
+}
+
+HRESULT CFieldPrinter::AddRawProps(IArchiveGetRawProps *getRawProps)
+{
+ UInt32 numProps;
+ RINOK(getRawProps->GetNumRawProps(&numProps));
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ RINOK(getRawProps->GetRawPropInfo(i, &name, &propID));
+ AddProp(name, propID, true);
+ }
+ return S_OK;
+}
+
+void CFieldPrinter::PrintTitle()
+{
+ FOR_VECTOR (i, _fields)
+ {
+ const CFieldInfo &f = _fields[i];
+ PrintSpaces(f.PrefixSpacesWidth);
+ PrintString(f.TitleAdjustment, ((f.PropID == kpidPath) ? 0: f.Width), f.NameA);
+ }
+}
+
+void CFieldPrinter::PrintTitleLines()
+{
+ g_StdOut << LinesString;
+}
+
+static void PrintTime(char *dest, const FILETIME *ft)
+{
+ *dest = 0;
+ if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0)
+ return;
+ ConvertUtcFileTimeToString(*ft, dest, kTimestampPrintLevel_SEC);
+}
+
+#ifndef _SFX
+
+static inline char GetHex(Byte value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+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));
+ dest += 2;
+ }
+ *dest = 0;
+}
+
+#endif
+
+#define MY_ENDL endl
+
+HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)
+{
+ char temp[128];
+ size_t tempPos = 0;
+
+ bool techMode = this->TechMode;
+ /*
+ if (techMode)
+ {
+ g_StdOut << "Index = ";
+ g_StdOut << (UInt64)index;
+ g_StdOut << endl;
+ }
+ */
+ FOR_VECTOR (i, _fields)
+ {
+ const CFieldInfo &f = _fields[i];
+
+ if (!techMode)
+ {
+ PrintSpacesToString(temp + tempPos, f.PrefixSpacesWidth);
+ tempPos += f.PrefixSpacesWidth;
+ }
+
+ if (techMode)
+ {
+ if (!f.NameA.IsEmpty())
+ g_StdOut << f.NameA;
+ else
+ g_StdOut << f.NameU;
+ }
+
+ if (f.PropID == kpidPath)
+ {
+ if (!techMode)
+ g_StdOut << temp;
+ g_StdOut.NormalizePrint_UString(FilePath, TempWString, TempAString);
+ if (techMode)
+ g_StdOut << MY_ENDL;
+ continue;
+ }
+
+ const unsigned width = f.Width;
+
+ if (f.IsRawProp)
+ {
+ #ifndef _SFX
+
+ const void *data;
+ UInt32 dataSize;
+ UInt32 propType;
+ RINOK(Arc->GetRawProps->GetRawProp(index, f.PropID, &data, &dataSize, &propType));
+
+ if (dataSize != 0)
+ {
+ bool needPrint = true;
+
+ if (f.PropID == kpidNtSecure)
+ {
+ if (propType != NPropDataType::kRaw)
+ return E_FAIL;
+ #ifndef _SFX
+ ConvertNtSecureToString((const Byte *)data, dataSize, TempAString);
+ g_StdOut << TempAString;
+ needPrint = false;
+ #endif
+ }
+ else if (f.PropID == kpidNtReparse)
+ {
+ UString s;
+ if (ConvertNtReparseToString((const Byte *)data, dataSize, s))
+ {
+ needPrint = false;
+ g_StdOut.PrintUString(s, TempAString);
+ }
+ }
+
+ if (needPrint)
+ {
+ if (propType != NPropDataType::kRaw)
+ return E_FAIL;
+
+ const UInt32 kMaxDataSize = 64;
+
+ if (dataSize > kMaxDataSize)
+ {
+ g_StdOut << "data:";
+ g_StdOut << dataSize;
+ }
+ else
+ {
+ char hexStr[kMaxDataSize * 2 + 4];
+ HexToString(hexStr, (const Byte *)data, dataSize);
+ g_StdOut << hexStr;
+ }
+ }
+ }
+
+ #endif
+ }
+ else
+ {
+ CPropVariant prop;
+ switch (f.PropID)
+ {
+ 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, IsDir, techMode, temp + tempPos);
+ if (techMode)
+ g_StdOut << temp + tempPos;
+ else
+ tempPos += strlen(temp + tempPos);
+ }
+ else if (prop.vt == VT_EMPTY)
+ {
+ if (!techMode)
+ {
+ PrintSpacesToString(temp + tempPos, width);
+ tempPos += width;
+ }
+ }
+ else if (prop.vt == VT_FILETIME)
+ {
+ PrintTime(temp + tempPos, &prop.filetime);
+ if (techMode)
+ g_StdOut << temp + tempPos;
+ else
+ {
+ size_t len = strlen(temp + tempPos);
+ tempPos += len;
+ if (len < (unsigned)f.Width)
+ {
+ len = f.Width - len;
+ PrintSpacesToString(temp + tempPos, (unsigned)len);
+ tempPos += len;
+ }
+ }
+ }
+ else if (prop.vt == VT_BSTR)
+ {
+ TempWString.SetFromBstr(prop.bstrVal);
+ // do we need multi-line support here ?
+ g_StdOut.Normalize_UString(TempWString);
+ if (techMode)
+ {
+ g_StdOut.PrintUString(TempWString, TempAString);
+ }
+ else
+ PrintUString(f.TextAdjustment, width, TempWString, TempAString);
+ }
+ else
+ {
+ char s[64];
+ ConvertPropertyToShortString2(s, prop, f.PropID);
+ if (techMode)
+ g_StdOut << s;
+ else
+ {
+ PrintStringToString(temp + tempPos, f.TextAdjustment, width, s);
+ tempPos += strlen(temp + tempPos);
+ }
+ }
+ }
+ if (techMode)
+ g_StdOut << MY_ENDL;
+ }
+ g_StdOut << MY_ENDL;
+ return S_OK;
+}
+
+static void PrintNumber(EAdjustment adj, unsigned width, const CListUInt64Def &value)
+{
+ char s[32];
+ s[0] = 0;
+ if (value.Def)
+ ConvertUInt64ToString(value.Val, s);
+ PrintString(adj, width, s);
+}
+
+void Print_UInt64_and_String(AString &s, UInt64 val, const char *name);
+
+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, st.Size);
+ else if (f.PropID == kpidPackSize)
+ PrintNumber(f.TextAdjustment, f.Width, st.PackSize);
+ else if (f.PropID == kpidMTime)
+ {
+ char s[64];
+ s[0] = 0;
+ if (st.MTime.Def)
+ PrintTime(s, &st.MTime.Val);
+ PrintString(f.TextAdjustment, f.Width, s);
+ }
+ else if (f.PropID == kpidPath)
+ {
+ AString s;
+ Print_UInt64_and_String(s, st.NumFiles, str);
+ if (numDirs != 0)
+ {
+ s += ", ";
+ Print_UInt64_and_String(s, numDirs, kString_Dirs);
+ }
+ PrintString(f.TextAdjustment, 0, s);
+ }
+ else
+ PrintString(f.TextAdjustment, f.Width, "");
+ }
+ g_StdOut << endl;
+}
+
+void CFieldPrinter::PrintSum(const CListStat2 &stat2)
+{
+ PrintSum(stat2.MainFiles, stat2.NumDirs, kString_Files);
+ if (stat2.AltStreams.NumFiles != 0)
+ {
+ PrintSum(stat2.AltStreams, 0, kString_AltStreams);;
+ CListStat st = stat2.MainFiles;
+ st.Update(stat2.AltStreams);
+ PrintSum(st, 0, kString_Streams);
+ }
+}
+
+static HRESULT GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, CListUInt64Def &value)
+{
+ value.Val = 0;
+ value.Def = false;
+ CPropVariant prop;
+ RINOK(archive->GetProperty(index, propID, &prop));
+ value.Def = ConvertPropVariantToUInt64(prop, value.Val);
+ return S_OK;
+}
+
+static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t)
+{
+ t.Val.dwLowDateTime = 0;
+ t.Val.dwHighDateTime = 0;
+ t.Def = false;
+ CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidMTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ t.Val = prop.filetime;
+ t.Def = true;
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+static void PrintPropNameAndNumber(CStdOutStream &so, const char *name, UInt64 val)
+{
+ so << name << ": " << val << endl;
+}
+
+static void PrintPropName_and_Eq(CStdOutStream &so, PROPID propID)
+{
+ const char *s;
+ char temp[16];
+ if (propID < ARRAY_SIZE(kPropIdToName))
+ s = kPropIdToName[propID];
+ else
+ {
+ ConvertUInt32ToString(propID, temp);
+ s = temp;
+ }
+ so << s << " = ";
+}
+
+static void PrintPropNameAndNumber(CStdOutStream &so, PROPID propID, UInt64 val)
+{
+ PrintPropName_and_Eq(so, propID);
+ so << val << endl;
+}
+
+static void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int64 val)
+{
+ PrintPropName_and_Eq(so, propID);
+ so << val << endl;
+}
+
+
+static void UString_Replace_CRLF_to_LF(UString &s)
+{
+ // s.Replace(L"\r\n", L"\n");
+ wchar_t *src = s.GetBuf();
+ wchar_t *dest = src;
+ for (;;)
+ {
+ wchar_t c = *src++;
+ if (c == 0)
+ break;
+ if (c == '\r' && *src == '\n')
+ {
+ src++;
+ c = '\n';
+ }
+ *dest++ = c;
+ }
+ s.ReleaseBuf_SetEnd((unsigned)(dest - s.GetBuf()));
+}
+
+
+static void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val)
+{
+ UString s = val;
+ if (s.Find(L'\n') >= 0)
+ {
+ so << endl;
+ so << "{";
+ so << endl;
+ UString_Replace_CRLF_to_LF(s);
+ so.Normalize_UString__LF_Allowed(s);
+ so << s;
+ so << endl;
+ so << "}";
+ }
+ else
+ {
+ so.Normalize_UString(s);
+ so << s;
+ }
+ so << endl;
+}
+
+
+static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val, bool multiLine)
+{
+ so << name << " = ";
+ if (multiLine)
+ {
+ PrintPropVal_MultiLine(so, val);
+ return;
+ }
+ UString s = val;
+ so.Normalize_UString(s);
+ so << s;
+ so << endl;
+}
+
+
+static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop)
+{
+ UString s;
+ ConvertPropertyToString2(s, prop, propID);
+ if (!s.IsEmpty())
+ {
+ AString nameA;
+ UString nameU;
+ GetPropName(propID, name, nameA, nameU);
+ if (!nameA.IsEmpty())
+ so << nameA;
+ else
+ so << nameU;
+ so << " = ";
+ PrintPropVal_MultiLine(so, s);
+ }
+}
+
+static HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propID, const wchar_t *name)
+{
+ CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(propID, &prop));
+ PrintPropertyPair2(so, propID, name, prop);
+ return S_OK;
+}
+
+static void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning)
+{
+ so << "Open " << (isWarning ? "WARNING" : "ERROR")
+ << ": Can not open the file as ["
+ << type
+ << "] archive"
+ << endl;
+}
+
+int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name);
+
+void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
+
+static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er)
+{
+ PrintErrorFlags(so, "ERRORS:", er.GetErrorFlags());
+ if (!er.ErrorMessage.IsEmpty())
+ PrintPropPair(so, "ERROR", er.ErrorMessage, true);
+
+ PrintErrorFlags(so, "WARNINGS:", er.GetWarningFlags());
+ if (!er.WarningMessage.IsEmpty())
+ PrintPropPair(so, "WARNING", er.WarningMessage, true);
+}
+
+HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)
+{
+ FOR_VECTOR (r, arcLink.Arcs)
+ {
+ const CArc &arc = arcLink.Arcs[r];
+ const CArcErrorInfo &er = arc.ErrorInfo;
+
+ so << "--\n";
+ PrintPropPair(so, "Path", arc.Path, false);
+ 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), false);
+
+ 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.NormalizePrint_UString(arcLink.NonOpen_ArcPath);
+ so << 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,
+ bool stdInMode,
+ UStringVector &arcPaths, UStringVector &arcPathsFull,
+ bool processAltStreams, bool showAltStreams,
+ const NWildcard::CCensorNode &wildcardCensor,
+ bool enableHeaders, bool techMode,
+ #ifndef _NO_CRYPTO
+ bool &passwordEnabled, UString &password,
+ #endif
+ #ifndef _SFX
+ const CObjectVector<CProperty> *props,
+ #endif
+ UInt64 &numErrors,
+ UInt64 &numWarnings)
+{
+ bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
+
+ numErrors = 0;
+ numWarnings = 0;
+
+ CFieldPrinter fp;
+ if (!techMode)
+ fp.Init(kStandardFieldTable, ARRAY_SIZE(kStandardFieldTable));
+
+ CListStat2 stat2total;
+
+ CBoolArr skipArcs(arcPaths.Size());
+ unsigned arcIndex;
+ for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)
+ skipArcs[arcIndex] = false;
+ UInt64 numVolumes = 0;
+ UInt64 numArcs = 0;
+ UInt64 totalArcSizes = 0;
+
+ HRESULT lastError = 0;
+
+ for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)
+ {
+ if (skipArcs[arcIndex])
+ continue;
+ const UString &arcPath = arcPaths[arcIndex];
+ UInt64 arcPackSize = 0;
+
+ if (!stdInMode)
+ {
+ NFile::NFind::CFileInfo fi;
+ if (!fi.Find(us2fs(arcPath)))
+ {
+ 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;
+ g_ErrStream->NormalizePrint_UString(arcPath);
+ *g_ErrStream << endl << endl;
+ numErrors++;
+ continue;
+ }
+ if (fi.IsDir())
+ {
+ g_StdOut.Flush();
+ *g_ErrStream << endl << kError;
+ g_ErrStream->NormalizePrint_UString(arcPath);
+ *g_ErrStream << " is not a file" << endl << endl;
+ numErrors++;
+ continue;
+ }
+ arcPackSize = fi.Size;
+ totalArcSizes += arcPackSize;
+ }
+
+ CArchiveLink arcLink;
+
+ COpenCallbackConsole openCallback;
+ openCallback.Init(&g_StdOut, g_ErrStream, NULL);
+
+ #ifndef _NO_CRYPTO
+
+ openCallback.PasswordIsDefined = passwordEnabled;
+ openCallback.Password = password;
+
+ #endif
+
+ /*
+ CObjectVector<COptionalOpenProperties> optPropsVector;
+ COptionalOpenProperties &optProps = optPropsVector.AddNew();
+ optProps.Props = *props;
+ */
+
+ COpenOptions options;
+ #ifndef _SFX
+ options.props = props;
+ #endif
+ options.codecs = codecs;
+ options.types = &types;
+ options.excludedFormats = &excludedFormats;
+ options.stdInMode = stdInMode;
+ options.stream = NULL;
+ options.filePath = arcPath;
+
+ if (enableHeaders)
+ {
+ g_StdOut << endl << kListing;
+ g_StdOut.NormalizePrint_UString(arcPath);
+ g_StdOut << endl << endl;
+ }
+
+ HRESULT result = arcLink.Open_Strict(options, &openCallback);
+
+ if (result != S_OK)
+ {
+ if (result == E_ABORT)
+ return result;
+ g_StdOut.Flush();
+ *g_ErrStream << endl << kError;
+ g_ErrStream->NormalizePrint_UString(arcPath);
+ *g_ErrStream << " : ";
+ if (result == S_FALSE)
+ {
+ Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink);
+ }
+ else
+ {
+ 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;
+ }
+
+ {
+ FOR_VECTOR (r, arcLink.Arcs)
+ {
+ const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo;
+ if (!arc.WarningMessage.IsEmpty())
+ numWarnings++;
+ if (arc.AreThereWarnings())
+ numWarnings++;
+ if (arc.ErrorFormatIndex >= 0)
+ numWarnings++;
+ if (arc.AreThereErrors())
+ {
+ numErrors++;
+ // break;
+ }
+ if (!arc.ErrorMessage.IsEmpty())
+ numErrors++;
+ }
+ }
+
+ numArcs++;
+ numVolumes++;
+
+ if (!stdInMode)
+ {
+ numVolumes += arcLink.VolumePaths.Size();
+ totalArcSizes += arcLink.VolumesSize;
+ FOR_VECTOR (v, arcLink.VolumePaths)
+ {
+ int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);
+ if (index >= 0 && (unsigned)index > arcIndex)
+ skipArcs[(unsigned)index] = true;
+ }
+ }
+
+
+ if (enableHeaders)
+ {
+ RINOK(Print_OpenArchive_Props(g_StdOut, codecs, arcLink));
+
+ g_StdOut << endl;
+ if (techMode)
+ g_StdOut << "----------\n";
+ }
+
+ if (enableHeaders && !techMode)
+ {
+ fp.PrintTitle();
+ g_StdOut << endl;
+ fp.PrintTitleLines();
+ g_StdOut << endl;
+ }
+
+ const CArc &arc = arcLink.Arcs.Back();
+ fp.Arc = &arc;
+ fp.TechMode = techMode;
+ IInArchive *archive = arc.Archive;
+ if (techMode)
+ {
+ fp.Clear();
+ RINOK(fp.AddMainProps(archive));
+ if (arc.GetRawProps)
+ {
+ RINOK(fp.AddRawProps(arc.GetRawProps));
+ }
+ }
+
+ CListStat2 stat2;
+
+ UInt32 numItems;
+ RINOK(archive->GetNumberOfItems(&numItems));
+
+ CReadArcItem item;
+ UStringVector pathParts;
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ if (NConsoleClose::TestBreakSignal())
+ return E_ABORT;
+
+ HRESULT res = arc.GetItemPath2(i, fp.FilePath);
+
+ if (stdInMode && res == E_INVALIDARG)
+ break;
+ RINOK(res);
+
+ if (arc.Ask_Aux)
+ {
+ bool isAux;
+ RINOK(Archive_IsItem_Aux(archive, i, isAux));
+ if (isAux)
+ continue;
+ }
+
+ bool isAltStream = false;
+ if (arc.Ask_AltStream)
+ {
+ RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));
+ if (isAltStream && !processAltStreams)
+ continue;
+ }
+
+ RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir));
+
+ if (!allFilesAreAllowed)
+ {
+ 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;
+
+ RINOK(GetUInt64Value(archive, i, kpidSize, st.Size));
+ RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize));
+ RINOK(GetItemMTime(archive, i, st.MTime));
+
+ if (fp.IsDir)
+ stat2.NumDirs++;
+ else
+ st.NumFiles = 1;
+ stat2.GetStat(isAltStream).Update(st);
+
+ if (isAltStream && !showAltStreams)
+ continue;
+ RINOK(fp.PrintItemInfo(i, st));
+ }
+
+ UInt64 numStreams = stat2.GetNumStreams();
+ if (!stdInMode
+ && !stat2.MainFiles.PackSize.Def
+ && !stat2.AltStreams.PackSize.Def)
+ {
+ if (arcLink.VolumePaths.Size() != 0)
+ arcPackSize += arcLink.VolumesSize;
+ stat2.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize);
+ }
+
+ stat2.MainFiles.SetSizeDefIfNoFiles();
+ stat2.AltStreams.SetSizeDefIfNoFiles();
+
+ if (enableHeaders && !techMode)
+ {
+ fp.PrintTitleLines();
+ g_StdOut << endl;
+ fp.PrintSum(stat2);
+ }
+
+ if (enableHeaders)
+ {
+ if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
+ {
+ g_StdOut << "----------\n";
+ PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath, false);
+ PrintArcTypeError(g_StdOut, codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);
+ }
+ }
+
+ stat2total.Update(stat2);
+
+ g_StdOut.Flush();
+ }
+
+ if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1))
+ {
+ g_StdOut << endl;
+ fp.PrintTitleLines();
+ g_StdOut << endl;
+ fp.PrintSum(stat2total);
+ g_StdOut << endl;
+ 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/other-licenses/7zstub/src/CPP/7zip/UI/Console/List.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/List.h
new file mode 100644
index 0000000000..dabbc2a604
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/List.h
@@ -0,0 +1,27 @@
+// List.h
+
+#ifndef __LIST_H
+#define __LIST_H
+
+#include "../../../Common/Wildcard.h"
+
+#include "../Common/LoadCodecs.h"
+
+HRESULT ListArchives(CCodecs *codecs,
+ const CObjectVector<COpenType> &types,
+ const CIntVector &excludedFormats,
+ bool stdInMode,
+ UStringVector &archivePaths, UStringVector &archivePathsFull,
+ bool processAltStreams, bool showAltStreams,
+ const NWildcard::CCensorNode &wildcardCensor,
+ bool enableHeaders, bool techMode,
+ #ifndef _NO_CRYPTO
+ bool &passwordEnabled, UString &password,
+ #endif
+ #ifndef _SFX
+ const CObjectVector<CProperty> *props,
+ #endif
+ UInt64 &errors,
+ UInt64 &numWarnings);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/Main.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/Main.cpp
new file mode 100644
index 0000000000..8f2825cad1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/Main.cpp
@@ -0,0 +1,1151 @@
+// Main.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyWindows.h"
+
+#ifdef _WIN32
+#include <Psapi.h>
+#endif
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/MyInitGuid.h"
+
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/MyException.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+#include "../../../Common/UTFConvert.h"
+
+#include "../../../Windows/ErrorMsg.h"
+
+#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"
+#include "List.h"
+#include "OpenCallbackConsole.h"
+#include "UpdateCallbackConsole.h"
+
+#include "HashCon.h"
+
+#ifdef PROG_VARIANT_R
+#include "../../../../C/7zVersion.h"
+#else
+#include "../../MyVersion.h"
+#endif
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NCommandLineParser;
+
+#ifdef _WIN32
+HINSTANCE g_hInstance = 0;
+#endif
+
+extern bool g_LargePagesMode;
+
+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 * const kCopyrightString = "\n7-Zip"
+ #ifndef EXTERNAL_CODECS
+ #ifdef PROG_VARIANT_R
+ " (r)"
+ #else
+ " (a)"
+ #endif
+ #endif
+
+ " " MY_VERSION_CPU
+ " : " MY_COPYRIGHT_DATE "\n\n";
+
+static const char * const kHelpString =
+ "Usage: 7z"
+#ifndef EXTERNAL_CODECS
+#ifdef PROG_VARIANT_R
+ "r"
+#else
+ "a"
+#endif
+#endif
+ " <command> [<switches>...] <archive_name> [<file_names>...]\n"
+ "\n"
+ "<Commands>\n"
+ " a : Add files to archive\n"
+ " b : Benchmark\n"
+ " 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"
+ " rn : Rename files in archive\n"
+ " t : Test integrity of archive\n"
+ " u : Update files to archive\n"
+ " x : eXtract files with full paths\n"
+ "\n"
+ "<Switches>\n"
+ " -- : Stop switches parsing\n"
+ " @listfile : set path to listfile that contains file names\n"
+ " -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n"
+ " -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n"
+ " -ao{a|s|t|u} : set Overwrite mode\n"
+ " -an : disable archive_name field\n"
+ " -bb[0-3] : set output log level\n"
+ " -bd : disable progress indicator\n"
+ " -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n"
+ " -bt : show execution time statistics\n"
+ " -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n"
+ " -m{Parameters} : set compression Method\n"
+ " -mmt[N] : set number of CPU threads\n"
+ " -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n"
+ " -o{Directory} : set Output directory\n"
+ #ifndef _NO_CRYPTO
+ " -p{Password} : set Password\n"
+ #endif
+ " -r[-|0] : Recurse subdirectories\n"
+ " -sa{a|e|s} : set Archive name mode\n"
+ " -scc{UTF-8|WIN|DOS} : set charset for for console input/output\n"
+ " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n"
+ " -scrc[CRC32|CRC64|SHA1|SHA256|*] : set hash function for x, e, h commands\n"
+ " -sdel : delete files after compression\n"
+ " -seml[.] : send archive by email\n"
+ " -sfx[{name}] : Create SFX archive\n"
+ " -si[{name}] : read data from stdin\n"
+ " -slp : set Large Pages mode\n"
+ " -slt : show technical information for l (List) command\n"
+ " -snh : store hard links as links\n"
+ " -snl : store symbolic links as links\n"
+ " -sni : store NT security information\n"
+ " -sns[-] : store NTFS alternate streams\n"
+ " -so : write data to stdout\n"
+ " -spd : disable wildcard matching for file names\n"
+ " -spe : eliminate duplication of root folder for extract command\n"
+ " -spf : use fully qualified file paths\n"
+ " -ssc[-] : set sensitive case mode\n"
+ " -sse : stop archive creating, if it can't open some input file\n"
+ " -ssw : compress shared files\n"
+ " -stl : set archive timestamp from the most recently modified file\n"
+ " -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n"
+ " -stx{Type} : exclude archive type\n"
+ " -t{Type} : Set type of archive\n"
+ " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n"
+ " -v{Size}[b|k|m|g] : Create volumes\n"
+ " -w[{path}] : assign Work directory. Empty path means a temporary directory\n"
+ " -x[r[-|0]]{@listfile|!wildcard} : eXclude filenames\n"
+ " -y : assume Yes on all queries\n";
+
+// ---------------------------
+// exception messages
+
+static const char * const kEverythingIsOk = "Everything is Ok";
+static const char * const kUserErrorMessage = "Incorrect command line";
+static const char * const kNoFormats = "7-Zip cannot find the code that works with archives.";
+static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type";
+// static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type";
+
+#define kDefaultSfxModule "7zCon.sfx"
+
+static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code)
+{
+ if (g_ErrStream)
+ *g_ErrStream << endl << "ERROR: " << message << endl;
+ throw code;
+}
+
+#ifndef _WIN32
+static void GetArguments(int numArgs, const char *args[], UStringVector &parts)
+{
+ parts.Clear();
+ for (int i = 0; i < numArgs; i++)
+ {
+ UString s = MultiByteToUnicodeString(args[i]);
+ parts.Add(s);
+ }
+}
+#endif
+
+static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp)
+{
+ if (!so)
+ return;
+ *so << kCopyrightString;
+ // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl;
+ if (needHelp)
+ *so << kHelpString;
+}
+
+
+static void PrintStringRight(CStdOutStream &so, const char *s, unsigned size)
+{
+ unsigned len = MyStringLen(s);
+ for (unsigned i = len; i < size; i++)
+ so << ' ';
+ so << s;
+}
+
+static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size)
+{
+ char s[16];
+ ConvertUInt32ToString(val, s);
+ PrintStringRight(so, s, size);
+}
+
+static void PrintLibIndex(CStdOutStream &so, int libIndex)
+{
+ if (libIndex >= 0)
+ PrintUInt32(so, libIndex, 2);
+ else
+ so << " ";
+ so << ' ';
+}
+
+static void PrintString(CStdOutStream &so, const UString &s, unsigned size)
+{
+ unsigned len = s.Len();
+ so << s;
+ for (unsigned i = len; i < size; i++)
+ so << ' ';
+}
+
+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.NormalizePrint_UString(pc.Paths[i]);
+ so << " : ";
+ so << NError::MyFormatMessage(pc.Codes[i]) << endl;
+ }
+ so << "----------------" << endl;
+}
+
+static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
+ const CUpdateErrorInfo &errorInfo,
+ CStdOutStream *so,
+ CStdOutStream *se,
+ bool showHeaders)
+{
+ int exitCode = NExitCode::kSuccess;
+
+ if (callback.ScanErrors.Paths.Size() != 0)
+ {
+ if (se)
+ {
+ *se << endl;
+ *se << "Scan WARNINGS for files and folders:" << endl << endl;
+ PrintWarningsPaths(callback.ScanErrors, *se);
+ *se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
+ *se << endl;
+ }
+ exitCode = NExitCode::kWarning;
+ }
+
+ if (result != S_OK || errorInfo.ThereIsError())
+ {
+ if (se)
+ {
+ UString message;
+ if (!errorInfo.Message.IsEmpty())
+ {
+ message += errorInfo.Message.Ptr();
+ message.Add_LF();
+ }
+ {
+ FOR_VECTOR(i, errorInfo.FileNames)
+ {
+ message += fs2us(errorInfo.FileNames[i]);
+ message.Add_LF();
+ }
+ }
+ if (errorInfo.SystemError != 0)
+ {
+ message += NError::MyFormatMessage(errorInfo.SystemError);
+ message.Add_LF();
+ }
+ if (!message.IsEmpty())
+ *se << L"\nError:\n" << message;
+ }
+
+ // we will work with (result) later
+ // throw CSystemException(result);
+ return NExitCode::kFatalError;
+ }
+
+ unsigned numErrors = callback.FailedFiles.Paths.Size();
+ if (numErrors == 0)
+ {
+ if (showHeaders)
+ if (callback.ScanErrors.Paths.Size() == 0)
+ if (so)
+ {
+ if (se)
+ se->Flush();
+ *so << kEverythingIsOk << endl;
+ }
+ }
+ else
+ {
+ if (se)
+ {
+ *se << endl;
+ *se << "WARNINGS for files:" << endl << endl;
+ PrintWarningsPaths(callback.FailedFiles, *se);
+ *se << "WARNING: Cannot open " << numErrors << " file";
+ if (numErrors > 1)
+ *se << 's';
+ *se << endl;
+ }
+ exitCode = NExitCode::kWarning;
+ }
+
+ return exitCode;
+}
+
+static void ThrowException_if_Error(HRESULT res)
+{
+ if (res != S_OK)
+ throw CSystemException(res);
+}
+
+
+static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ')
+{
+ char temp[64];
+ char *p = temp + 32;
+ ConvertUInt64ToString(val, p);
+ unsigned len = MyStringLen(p);
+ for (; len < numDigits; len++)
+ *--p = c;
+ *g_StdStream << p;
+}
+
+static void PrintTime(const char *s, UInt64 val, UInt64 total)
+{
+ *g_StdStream << endl << s << " Time =";
+ const UInt32 kFreq = 10000000;
+ UInt64 sec = val / kFreq;
+ PrintNum(sec, 6);
+ *g_StdStream << '.';
+ UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000);
+ PrintNum(ms, 3, '0');
+
+ while (val > ((UInt64)1 << 56))
+ {
+ val >>= 1;
+ total >>= 1;
+ }
+
+ UInt64 percent = 0;
+ if (total != 0)
+ percent = val * 100 / total;
+ *g_StdStream << " =";
+ PrintNum(percent, 5);
+ *g_StdStream << '%';
+}
+
+#ifndef UNDER_CE
+
+#define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num))
+
+static void PrintMemUsage(const char *s, UInt64 val)
+{
+ *g_StdStream << " " << s << " Memory =";
+ PrintNum(SHIFT_SIZE_VALUE(val, 20), 7);
+ *g_StdStream << " MB";
+ if (g_LargePagesMode)
+ *g_StdStream << " (LP)";
+}
+
+EXTERN_C_BEGIN
+typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process,
+ PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb);
+typedef BOOL (WINAPI *Func_QueryProcessCycleTime)(HANDLE Process, PULONG64 CycleTime);
+EXTERN_C_END
+
+#endif
+
+static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }
+
+static void PrintStat()
+{
+ FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT;
+ if (!
+ #ifdef UNDER_CE
+ ::GetThreadTimes(::GetCurrentThread()
+ #else
+ // NT 3.5
+ ::GetProcessTimes(::GetCurrentProcess()
+ #endif
+ , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT))
+ return;
+ FILETIME curTimeFT;
+ NTime::GetCurUtcFileTime(curTimeFT);
+
+ #ifndef UNDER_CE
+
+ PROCESS_MEMORY_COUNTERS m;
+ memset(&m, 0, sizeof(m));
+ BOOL memDefined = FALSE;
+ BOOL cycleDefined = FALSE;
+ ULONG64 cycleTime = 0;
+ {
+ /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll
+ Win7: new function K32GetProcessMemoryInfo() in kernel32.dll
+ It's faster to call kernel32.dll code than Psapi.dll code
+ GetProcessMemoryInfo() requires Psapi.lib
+ Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll
+ The program with K32GetProcessMemoryInfo will not work on systems before Win7
+ // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));
+ */
+
+ HMODULE kern = ::GetModuleHandleW(L"kernel32.dll");
+ Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)
+ ::GetProcAddress(kern, "K32GetProcessMemoryInfo");
+ if (!my_GetProcessMemoryInfo)
+ {
+ HMODULE lib = LoadLibraryW(L"Psapi.dll");
+ if (lib)
+ my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)::GetProcAddress(lib, "GetProcessMemoryInfo");
+ }
+ if (my_GetProcessMemoryInfo)
+ memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m));
+ // FreeLibrary(lib);
+
+ Func_QueryProcessCycleTime my_QueryProcessCycleTime = (Func_QueryProcessCycleTime)
+ ::GetProcAddress(kern, "QueryProcessCycleTime");
+ if (my_QueryProcessCycleTime)
+ cycleDefined = my_QueryProcessCycleTime(GetCurrentProcess(), &cycleTime);
+ }
+
+ #endif
+
+ UInt64 curTime = GetTime64(curTimeFT);
+ UInt64 creationTime = GetTime64(creationTimeFT);
+ UInt64 kernelTime = GetTime64(kernelTimeFT);
+ UInt64 userTime = GetTime64(userTimeFT);
+
+ UInt64 totalTime = curTime - creationTime;
+
+ PrintTime("Kernel ", kernelTime, totalTime);
+
+ #ifndef UNDER_CE
+ if (cycleDefined)
+ {
+ *g_StdStream << " ";
+ PrintNum(cycleTime / 1000000, 22);
+ *g_StdStream << " MCycles";
+ }
+ #endif
+
+ PrintTime("User ", userTime, totalTime);
+
+ PrintTime("Process", kernelTime + userTime, totalTime);
+ #ifndef UNDER_CE
+ if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage);
+ #endif
+
+ PrintTime("Global ", totalTime, totalTime);
+ #ifndef UNDER_CE
+ if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize);
+ #endif
+
+ *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, char *args[]
+ #endif
+)
+{
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ SetFileApisToOEM();
+ #endif
+
+ UStringVector commandStrings;
+
+ #ifdef _WIN32
+ NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
+ #else
+ GetArguments(numArgs, args, commandStrings);
+ #endif
+
+ #ifndef UNDER_CE
+ if (commandStrings.Size() > 0)
+ commandStrings.Delete(0);
+ #endif
+
+ if (commandStrings.Size() == 0)
+ {
+ ShowCopyrightAndHelp(g_StdStream, true);
+ return 0;
+ }
+
+ CArcCmdLineOptions options;
+
+ CArcCmdLineParser parser;
+
+ parser.Parse1(commandStrings, options);
+
+ g_StdOut.IsTerminalMode = options.IsStdOutTerminal;
+ g_StdErr.IsTerminalMode = options.IsStdErrTerminal;
+
+ 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;;
+
+ if (options.HelpMode)
+ {
+ ShowCopyrightAndHelp(g_StdStream, true);
+ return 0;
+ }
+
+ if (options.EnableHeaders)
+ ShowCopyrightAndHelp(g_StdStream, false);
+
+ parser.Parse2(options);
+
+ 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());
+
+ bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+
+ if (codecs->Formats.Size() == 0 &&
+ (isExtractGroupCommand
+ || options.Command.CommandType == NCommandType::kList
+ || options.Command.IsFromUpdateGroup()))
+ {
+ #ifdef EXTERNAL_CODECS
+ if (!codecs->MainDll_ErrorPath.IsEmpty())
+ {
+ UString s ("Can't load module: ");
+ s += fs2us(codecs->MainDll_ErrorPath);
+ throw s;
+ }
+ #endif
+
+ throw kNoFormats;
+ }
+
+ CObjectVector<COpenType> types;
+ if (!ParseOpenTypes(*codecs, options.ArcType, types))
+ throw kUnsupportedArcTypeMessage;
+
+ CIntVector excludedFormats;
+ FOR_VECTOR (k, options.ExcludedArcTypes)
+ {
+ CIntVector tempIndices;
+ if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices)
+ || tempIndices.Size() != 1)
+ throw kUnsupportedArcTypeMessage;
+ excludedFormats.AddToUniqueSorted(tempIndices[0]);
+ // excludedFormats.Sort();
+ }
+
+
+ #ifdef EXTERNAL_CODECS
+ if (isExtractGroupCommand
+ || options.Command.CommandType == NCommandType::kHash
+ || options.Command.CommandType == NCommandType::kBenchmark)
+ ThrowException_if_Error(__externalCodecs.Load());
+ #endif
+
+ int retCode = NExitCode::kSuccess;
+ HRESULT hresultMain = S_OK;
+
+ // bool showStat = options.ShowTime;
+
+ /*
+ if (!options.EnableHeaders ||
+ options.TechMode)
+ showStat = false;
+ */
+
+
+ if (options.Command.CommandType == NCommandType::kInfo)
+ {
+ CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
+ unsigned i;
+
+ #ifdef EXTERNAL_CODECS
+ so << endl << "Libs:" << endl;
+ for (i = 0; i < codecs->Libs.Size(); i++)
+ {
+ PrintLibIndex(so, i);
+ so << ' ' << codecs->Libs[i].Path << endl;
+ }
+ #endif
+
+ so << endl << "Formats:" << endl;
+
+ const char * const kArcFlags = "KSNFMGOPBELH";
+ const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags);
+
+ for (i = 0; i < codecs->Formats.Size(); i++)
+ {
+ const CArcInfoEx &arc = codecs->Formats[i];
+
+ #ifdef EXTERNAL_CODECS
+ PrintLibIndex(so, arc.LibIndex);
+ #else
+ so << " ";
+ #endif
+
+ so << (char)(arc.UpdateEnabled ? 'C' : ' ');
+
+ for (unsigned b = 0; b < kNumArcFlags; b++)
+ {
+ so << (char)
+ ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' ');
+ }
+
+ so << ' ';
+ PrintString(so, arc.Name, 8);
+ so << ' ';
+ UString s;
+
+ FOR_VECTOR (t, arc.Exts)
+ {
+ if (t != 0)
+ s.Add_Space();
+ const CArcExtInfo &ext = arc.Exts[t];
+ s += ext.Ext;
+ if (!ext.AddExt.IsEmpty())
+ {
+ s += " (";
+ s += ext.AddExt;
+ s += ')';
+ }
+ }
+
+ PrintString(so, s, 13);
+ so << ' ';
+
+ if (arc.SignatureOffset != 0)
+ so << "offset=" << arc.SignatureOffset << ' ';
+
+ FOR_VECTOR(si, arc.Signatures)
+ {
+ if (si != 0)
+ so << " || ";
+
+ const CByteBuffer &sig = arc.Signatures[si];
+
+ for (size_t j = 0; j < sig.Size(); j++)
+ {
+ if (j != 0)
+ so << ' ';
+ Byte b = sig[j];
+ if (b > 0x20 && b < 0x80)
+ {
+ so << (char)b;
+ }
+ else
+ {
+ so << GetHex((b >> 4) & 0xF);
+ so << GetHex(b & 0xF);
+ }
+ }
+ }
+ 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
+
+ UInt32 numMethods;
+ if (codecs->GetNumMethods(&numMethods) == S_OK)
+ for (UInt32 j = 0; j < numMethods; j++)
+ {
+ 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;
+ HRESULT res = codecs->GetCodec_Id(j, id);
+ if (res != S_OK)
+ id = (UInt64)(Int64)-1;
+ 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
+
+ numMethods = codecs->GetNumHashers();
+ for (UInt32 j = 0; j < numMethods; j++)
+ {
+ PrintLibIndex(so, codecs->GetHasherLibIndex(j));
+ PrintUInt32(so, codecs->GetHasherDigestSize(j), 4);
+ so << ' ';
+ PrintHexId(so, codecs->GetHasherId(j));
+ so << ' ' << codecs->GetHasherName(j) << endl;
+ }
+
+ #endif
+
+ }
+ else if (options.Command.CommandType == NCommandType::kBenchmark)
+ {
+ CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
+ hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
+ options.Properties, options.NumIterations, (FILE *)so);
+ if (hresultMain == S_FALSE)
+ {
+ 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;
+
+ #ifndef _NO_CRYPTO
+ ecs->PasswordIsDefined = options.PasswordEnabled;
+ ecs->Password = options.Password;
+ #endif
+
+ ecs->Init(g_StdStream, g_ErrStream, percentsStream);
+ ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1);
+
+ ecs->LogLevel = options.LogLevel;
+ ecs->PercentsNameLevel = percentsNameLevel;
+
+ if (percentsStream)
+ ecs->SetWindowWidth(consoleWidth);
+
+ /*
+ COpenCallbackConsole openCallback;
+ 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;
+ eo.TestMode = options.Command.IsTestCommand();
+
+ #ifndef _SFX
+ eo.Properties = options.Properties;
+ #endif
+
+ UString errorMessage;
+ CDecompressStat stat;
+ CHashBundle hb;
+ IHashCalc *hashCalc = NULL;
+
+ if (!options.HashMethods.IsEmpty())
+ {
+ hashCalc = &hb;
+ ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods));
+ hb.Init();
+ }
+
+ hresultMain = Extract(
+ codecs,
+ types,
+ excludedFormats,
+ ArchivePathsSorted,
+ ArchivePathsFullSorted,
+ options.Censor.Pairs.Front().Head,
+ eo, ecs, ecs, hashCalc, errorMessage, stat);
+
+ ecs->ClosePercents();
+
+ if (!errorMessage.IsEmpty())
+ {
+ if (g_ErrStream)
+ *g_ErrStream << endl << "ERROR:" << endl << errorMessage << endl;
+ if (hresultMain == S_OK)
+ hresultMain = E_FAIL;
+ }
+
+ CStdOutStream *so = g_StdStream;
+
+ bool isError = false;
+
+ if (so)
+ {
+ *so << endl;
+
+ if (ecs->NumTryArcs > 1)
+ {
+ *so << "Archives: " << ecs->NumTryArcs << endl;
+ *so << "OK archives: " << ecs->NumOkArcs << endl;
+ }
+ }
+
+ if (ecs->NumCantOpenArcs != 0)
+ {
+ isError = true;
+ if (so)
+ *so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
+ }
+
+ if (ecs->NumArcsWithError != 0)
+ {
+ isError = true;
+ if (so)
+ *so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
+ }
+
+ if (so)
+ {
+ if (ecs->NumArcsWithWarnings != 0)
+ *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
+
+ if (ecs->NumOpenArcWarnings != 0)
+ {
+ *so << endl;
+ if (ecs->NumOpenArcWarnings != 0)
+ *so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
+ }
+ }
+
+ if (ecs->NumOpenArcErrors != 0)
+ {
+ isError = true;
+ if (so)
+ {
+ *so << endl;
+ if (ecs->NumOpenArcErrors != 0)
+ *so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
+ }
+ }
+
+ if (isError)
+ retCode = NExitCode::kFatalError;
+
+ if (so)
+ if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
+ {
+ // if (ecs->NumArchives > 1)
+ {
+ *so << endl;
+ if (ecs->NumFileErrors != 0)
+ *so << "Sub items Errors: " << ecs->NumFileErrors << endl;
+ }
+ }
+ else if (hresultMain == S_OK)
+ {
+ 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
+ {
+ UInt64 numErrors = 0;
+ UInt64 numWarnings = 0;
+
+ // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed
+
+ hresultMain = ListArchives(
+ codecs,
+ types,
+ excludedFormats,
+ options.StdInMode,
+ ArchivePathsSorted,
+ ArchivePathsFullSorted,
+ options.ExtractOptions.NtOptions.AltStreams.Val,
+ options.AltStreams.Val, // we don't want to show AltStreams by default
+ options.Censor.Pairs.Front().Head,
+ options.EnableHeaders,
+ options.TechMode,
+ #ifndef _NO_CRYPTO
+ options.PasswordEnabled,
+ options.Password,
+ #endif
+ &options.Properties,
+ numErrors, numWarnings);
+
+ if (options.EnableHeaders)
+ if (numWarnings > 0)
+ g_StdOut << endl << "Warnings: " << numWarnings << endl;
+
+ if (numErrors > 0)
+ {
+ if (options.EnableHeaders)
+ g_StdOut << endl << "Errors: " << numErrors << endl;
+ retCode = NExitCode::kFatalError;
+ }
+ }
+ }
+ else if (options.Command.IsFromUpdateGroup())
+ {
+ CUpdateOptions &uo = options.UpdateOptions;
+ if (uo.SfxMode && uo.SfxModule.IsEmpty())
+ uo.SfxModule = kDefaultSfxModule;
+
+ COpenCallbackConsole openCallback;
+ openCallback.Init(g_StdStream, g_ErrStream, percentsStream);
+
+ #ifndef _NO_CRYPTO
+ bool passwordIsDefined =
+ (options.PasswordEnabled && !options.Password.IsEmpty());
+ openCallback.PasswordIsDefined = passwordIsDefined;
+ openCallback.Password = options.Password;
+ #endif
+
+ CUpdateCallbackConsole callback;
+ 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.Password = options.Password;
+ #endif
+
+ callback.StdOutMode = uo.StdOutMode;
+ callback.Init(
+ // NULL,
+ g_StdStream, g_ErrStream, percentsStream);
+
+ CUpdateErrorInfo errorInfo;
+
+ /*
+ if (!uo.Init(codecs, types, options.ArchiveName))
+ throw kUnsupportedUpdateArcType;
+ */
+ hresultMain = UpdateArchive(codecs,
+ types,
+ options.ArchiveName,
+ options.Censor,
+ uo,
+ errorInfo, &openCallback, &callback, true);
+
+ callback.ClosePercents2();
+
+ CStdOutStream *se = g_StdStream;
+ if (!se)
+ se = g_ErrStream;
+
+ retCode = WarningsCheck(hresultMain, callback, errorInfo,
+ g_StdStream, se,
+ true // options.EnableHeaders
+ );
+ }
+ else if (options.Command.CommandType == NCommandType::kHash)
+ {
+ const CHashOptions &uo = options.HashOptions;
+
+ CHashCallbackConsole callback;
+ if (percentsStream)
+ callback.SetWindowWidth(consoleWidth);
+
+ callback.Init(g_StdStream, g_ErrStream, percentsStream);
+ callback.PrintHeaders = options.EnableHeaders;
+
+ AString errorInfoString;
+ hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L
+ options.Censor, uo,
+ errorInfoString, &callback);
+ CUpdateErrorInfo errorInfo;
+ errorInfo.Message = errorInfoString;
+ CStdOutStream *se = g_StdStream;
+ if (!se)
+ se = g_ErrStream;
+ retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders);
+ }
+ else
+ ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
+
+ if (options.ShowTime && g_StdStream)
+ PrintStat();
+
+ ThrowException_if_Error(hresultMain);
+
+ return retCode;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/MainAr.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/MainAr.cpp
new file mode 100644
index 0000000000..fdac64340d
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/MainAr.cpp
@@ -0,0 +1,167 @@
+// MainAr.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyException.h"
+#include "../../../Common/StdOutStream.h"
+
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/NtCheck.h"
+
+#include "../Common/ArchiveCommandLine.h"
+#include "../Common/ExitCode.h"
+
+#include "ConsoleClose.h"
+
+using namespace NWindows;
+
+CStdOutStream *g_StdStream = NULL;
+CStdOutStream *g_ErrStream = NULL;
+
+extern int Main2(
+ #ifndef _WIN32
+ int numArgs, char *args[]
+ #endif
+);
+
+static const char * const kException_CmdLine_Error_Message = "Command Line Error:";
+static const char * const kExceptionErrorMessage = "ERROR:";
+static const char * const kUserBreakMessage = "Break signaled";
+static const char * const kMemoryExceptionMessage = "ERROR: Can't allocate required memory!";
+static const char * const kUnknownExceptionMessage = "Unknown Error";
+static const char * const kInternalExceptionMessage = "\n\nInternal Error #";
+
+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
+(
+ #ifndef _WIN32
+ int numArgs, char *args[]
+ #endif
+)
+{
+ g_ErrStream = &g_StdErr;
+ g_StdStream = &g_StdOut;
+
+ NT_CHECK
+
+ NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
+ int res = 0;
+
+ try
+ {
+ res = Main2(
+ #ifndef _WIN32
+ numArgs, args
+ #endif
+ );
+ }
+ catch(const CNewException &)
+ {
+ PrintError(kMemoryExceptionMessage);
+ return (NExitCode::kMemoryError);
+ }
+ catch(const NConsoleClose::CCtrlBreakException &)
+ {
+ PrintError(kUserBreakMessage);
+ return (NExitCode::kUserBreak);
+ }
+ catch(const CMessagePathException &e)
+ {
+ PrintError(kException_CmdLine_Error_Message);
+ if (g_ErrStream)
+ *g_ErrStream << e << endl;
+ return (NExitCode::kUserError);
+ }
+ catch(const CSystemException &systemError)
+ {
+ if (systemError.ErrorCode == E_OUTOFMEMORY)
+ {
+ PrintError(kMemoryExceptionMessage);
+ return (NExitCode::kMemoryError);
+ }
+ if (systemError.ErrorCode == E_ABORT)
+ {
+ PrintError(kUserBreakMessage);
+ return (NExitCode::kUserBreak);
+ }
+ if (g_ErrStream)
+ {
+ PrintError("System ERROR:");
+ *g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl;
+ }
+ return (NExitCode::kFatalError);
+ }
+ catch(NExitCode::EEnum &exitCode)
+ {
+ FlushStreams();
+ if (g_ErrStream)
+ *g_ErrStream << kInternalExceptionMessage << exitCode << endl;
+ return (exitCode);
+ }
+ catch(const UString &s)
+ {
+ if (g_ErrStream)
+ {
+ PrintError(kExceptionErrorMessage);
+ *g_ErrStream << s << endl;
+ }
+ return (NExitCode::kFatalError);
+ }
+ catch(const AString &s)
+ {
+ if (g_ErrStream)
+ {
+ PrintError(kExceptionErrorMessage);
+ *g_ErrStream << s << endl;
+ }
+ return (NExitCode::kFatalError);
+ }
+ catch(const char *s)
+ {
+ if (g_ErrStream)
+ {
+ PrintError(kExceptionErrorMessage);
+ *g_ErrStream << s << endl;
+ }
+ return (NExitCode::kFatalError);
+ }
+ catch(const wchar_t *s)
+ {
+ 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(...)
+ {
+ PrintError(kUnknownExceptionMessage);
+ return (NExitCode::kFatalError);
+ }
+
+ return res;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
new file mode 100644
index 0000000000..6e58c1f96c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
@@ -0,0 +1,115 @@
+// OpenCallbackConsole.cpp
+
+#include "StdAfx.h"
+
+#include "OpenCallbackConsole.h"
+
+#include "ConsoleClose.h"
+#include "UserInputUtils.h"
+
+static HRESULT CheckBreak2()
+{
+ return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
+}
+
+HRESULT COpenCallbackConsole::Open_CheckBreak()
+{
+ return CheckBreak2();
+}
+
+HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)
+{
+ if (!MultiArcMode && 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;
+ if (!files)
+ _percent.Total = _totalBytes;
+ }
+ }
+
+ return CheckBreak2();
+}
+
+HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)
+{
+ if (!MultiArcMode && 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)
+{
+ *password = NULL;
+ RINOK(CheckBreak2());
+
+ if (!PasswordIsDefined)
+ {
+ ClosePercents();
+ RINOK(GetPassword_HRESULT(_so, Password));
+ PasswordIsDefined = true;
+ }
+ return StringToBstr(Password, password);
+}
+
+/*
+HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
+{
+ passwordIsDefined = PasswordIsDefined;
+ password = Password;
+ return S_OK;
+}
+
+bool COpenCallbackConsole::Open_WasPasswordAsked()
+{
+ return PasswordWasAsked;
+}
+
+void COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag ()
+{
+ PasswordWasAsked = false;
+}
+*/
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.h
new file mode 100644
index 0000000000..b9270f8e2c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.h
@@ -0,0 +1,66 @@
+// OpenCallbackConsole.h
+
+#ifndef __OPEN_CALLBACK_CONSOLE_H
+#define __OPEN_CALLBACK_CONSOLE_H
+
+#include "../../../Common/StdOutStream.h"
+
+#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:
+
+ bool MultiArcMode;
+
+ void ClosePercents()
+ {
+ if (NeedPercents())
+ _percent.ClosePrint(true);
+ }
+
+ COpenCallbackConsole():
+ _totalFilesDefined(false),
+ // _totalBytesDefined(false),
+ _totalBytes(0),
+ MultiArcMode(false)
+
+ #ifndef _NO_CRYPTO
+ , PasswordIsDefined(false)
+ // , PasswordWasAsked(false)
+ #endif
+
+ {}
+
+ void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
+ {
+ _so = outStream;
+ _se = errorStream;
+ _percent._so = percentStream;
+ }
+
+ INTERFACE_IOpenCallbackUI(;)
+
+ #ifndef _NO_CRYPTO
+ bool PasswordIsDefined;
+ // bool PasswordWasAsked;
+ UString Password;
+ #endif
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.cpp
new file mode 100644
index 0000000000..20249ed031
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -0,0 +1,183 @@
+// PercentPrinter.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+
+#include "PercentPrinter.h"
+
+static const unsigned kPercentsSize = 4;
+
+CPercentPrinter::~CPercentPrinter()
+{
+ ClosePrint(false);
+}
+
+void CPercentPrinterState::ClearCurState()
+{
+ Completed = 0;
+ Total = ((UInt64)(Int64)-1);
+ Files = 0;
+ Command.Empty();
+ FileName.Empty();
+}
+
+void CPercentPrinter::ClosePrint(bool needFlush)
+{
+ unsigned num = _printedString.Len();
+ if (num != 0)
+ {
+
+ 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::GetPercents()
+{
+ char s[32];
+ unsigned size;
+ {
+ char c = '%';
+ UInt64 val = 0;
+ if (Total == (UInt64)(Int64)-1)
+ {
+ val = Completed >> 20;
+ c = 'M';
+ }
+ else if (Total != 0)
+ val = Completed * 100 / Total;
+ ConvertUInt64ToString(val, s);
+ size = (unsigned)strlen(s);
+ s[size++] = c;
+ s[size] = 0;
+ }
+
+ while (size < kPercentsSize)
+ {
+ _s += ' ';
+ size++;
+ }
+
+ _s += s;
+}
+
+void CPercentPrinter::Print()
+{
+ 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;
+
+ _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 += ' ';
+
+ _tempU = FileName;
+ _so->Normalize_UString(_tempU);
+ StdOut_Convert_UString_to_AString(_tempU, _temp);
+ 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, _tempU.Len() - len);
+ _tempU.Insert(len / 2, L" . ");
+ _so->Normalize_UString(_tempU);
+ 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/other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.h
new file mode 100644
index 0000000000..90b4083ed3
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.h
@@ -0,0 +1,62 @@
+// PercentPrinter.h
+
+#ifndef __PERCENT_PRINTER_H
+#define __PERCENT_PRINTER_H
+
+#include "../../../Common/StdOutStream.h"
+
+struct CPercentPrinterState
+{
+ 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 *_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/other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.cpp
new file mode 100644
index 0000000000..c6d3b1fa62
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.h
new file mode 100644
index 0000000000..59d9ac15b1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/Common.h"
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
new file mode 100644
index 0000000000..46ffaba021
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -0,0 +1,702 @@
+// UpdateCallbackConsole.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+
+#include "../../../Windows/ErrorMsg.h"
+
+#ifndef _7ZIP_ST
+#include "../../../Windows/Synchronization.h"
+#endif
+
+#include "ConsoleClose.h"
+#include "UserInputUtils.h"
+#include "UpdateCallbackConsole.h"
+
+using namespace NWindows;
+
+#ifndef _7ZIP_ST
+static NSynchronization::CCriticalSection g_CriticalSection;
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+#define MT_LOCK
+#endif
+
+static const wchar_t * const kEmptyFileAlias = L"[Content]";
+
+static const char * const kOpenArchiveMessage = "Open archive: ";
+static const char * const kCreatingArchiveMessage = "Creating archive: ";
+static const char * const kUpdatingArchiveMessage = "Updating archive: ";
+static const char * const kScanningMessage = "Scanning the drive:";
+
+static const char * const kError = "ERROR: ";
+static const char * const kWarning = "WARNING: ";
+
+static HRESULT CheckBreak2()
+{
+ 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)
+ {
+ 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;
+ _se->NormalizePrint_wstr(name);
+ *_se << endl;
+ HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
+ RINOK(res);
+ _se->Flush();
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::StartScanning()
+{
+ if (_so)
+ *_so << kScanningMessage << endl;
+ _percent.Command = "Scan ";
+ return S_OK;
+}
+
+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();
+}
+
+void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning)
+{
+ ClosePercents2();
+
+ if (_se)
+ {
+ if (_so)
+ _so->Flush();
+
+ *_se << endl << (isWarning ? kWarning : kError)
+ << NError::MyFormatMessage(systemError)
+ << endl;
+ _se->NormalizePrint_UString(fs2us(path));
+ *_se << endl << endl;
+ _se->Flush();
+ }
+}
+
+
+HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError)
+{
+ MT_LOCK
+
+ ScanErrors.AddError(path, systemError);
+ CommonError(path, systemError, true);
+
+ return S_OK;
+}
+
+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)
+{
+ char temp[32];
+ ConvertUInt64ToString(val, temp);
+ s += name;
+ s += ": ";
+ s += temp;
+}
+
+void PrintSize_bytes_Smart(AString &s, UInt64 val);
+void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
+void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
+
+HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
+{
+ 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 * const 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 (_so)
+ {
+ *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
+ if (name)
+ _so->NormalizePrint_wstr(name);
+ else
+ *_so << k_StdOut_ArcName;
+ *_so << endl << endl;
+ }
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)
+{
+ 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::WriteSfx(const wchar_t *name, UInt64 size)
+{
+ if (_so)
+ {
+ *_so << "Write SFX: ";
+ *_so << name;
+ AString s (" : ");
+ PrintSize_bytes_Smart(s, size);
+ *_so << s << endl;
+ }
+ return S_OK;
+}
+
+
+HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
+{
+ if (LogLevel > 0 && _so)
+ {
+ ClosePercents_for_so();
+
+ if (!DeleteMessageWasShown)
+ {
+ if (_so)
+ *_so << endl << ": Removing files after including to archive" << endl;
+ }
+
+ {
+ {
+ _tempA = "Removing";
+ _tempA.Add_Space();
+ *_so << _tempA;
+ _tempU = fs2us(path);
+ _so->Normalize_UString(_tempU);
+ _so->PrintUString(_tempU, _tempA);
+ *_so << endl;
+ if (NeedFlush)
+ _so->Flush();
+ }
+ }
+ }
+
+ if (!DeleteMessageWasShown)
+ {
+ if (NeedPercents())
+ {
+ _percent.ClearCurState();
+ }
+ 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;
+}
+*/
+
+
+void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
+{
+ AString s;
+ Print_DirItemsStat2(s, stat);
+ *_so << name << ": " << s << endl;
+}
+
+HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat)
+{
+ if (_so)
+ {
+ ClosePercents_for_so();
+ if (!stat.DeleteData.IsEmpty())
+ {
+ *_so << endl;
+ PrintToDoStat(_so, stat.DeleteData, "Delete data from archive");
+ }
+ if (!stat.OldData.IsEmpty())
+ PrintToDoStat(_so, stat.OldData, "Keep old data in archive");
+ // if (!stat.NewData.IsEmpty())
+ {
+ PrintToDoStat(_so, stat.NewData, "Add new data to archive");
+ }
+ *_so << endl;
+ }
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
+{
+ MT_LOCK
+ if (NeedPercents())
+ {
+ _percent.Total = size;
+ _percent.Print();
+ }
+ return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
+{
+ MT_LOCK
+ if (completeValue)
+ {
+ if (NeedPercents())
+ {
+ _percent.Completed = *completeValue;
+ _percent.Print();
+ }
+ }
+ return CheckBreak2();
+}
+
+HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
+{
+ return CheckBreak2();
+}
+
+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->Normalize_UString(_tempU);
+ }
+ _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 (!name || name[0] == 0)
+ name = kEmptyFileAlias;
+
+ 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::SetOperationResult(Int32)
+{
+ MT_LOCK
+ _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)
+ {
+ ClosePercents2();
+
+ if (_se)
+ {
+ if (_so)
+ _so->Flush();
+
+ AString s;
+ SetExtractErrorMessage(opRes, isEncrypted, s);
+ *_se << s << " : " << endl;
+ _se->NormalizePrint_wstr(name);
+ *_se << endl << endl;
+ _se->Flush();
+ }
+ return S_OK;
+ }
+ return S_OK;
+}
+
+
+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
+ )
+{
+ #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
+
+ *passwordIsDefined = false;
+ return S_OK;
+
+ #else
+
+ if (!PasswordIsDefined)
+ {
+ if (AskPassword)
+ {
+ RINOK(GetPassword_HRESULT(_so, Password));
+ PasswordIsDefined = true;
+ }
+ }
+ *passwordIsDefined = BoolToInt(PasswordIsDefined);
+ return StringToBstr(Password, password);
+
+ #endif
+
+ COM_TRY_END
+}
+
+HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+
+ *password = NULL;
+
+ #ifdef _NO_CRYPTO
+
+ return E_NOTIMPL;
+
+ #else
+
+ if (!PasswordIsDefined)
+ {
+ {
+ RINOK(GetPassword_HRESULT(_so, Password))
+ PasswordIsDefined = true;
+ }
+ }
+ return StringToBstr(Password, password);
+
+ #endif
+ COM_TRY_END
+}
+
+HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
+{
+ if (StdOutMode)
+ return S_OK;
+
+ if (LogLevel > 7)
+ {
+ if (!name || name[0] == 0)
+ name = kEmptyFileAlias;
+ return PrintProgress(name, "D", true);
+ }
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.h
new file mode 100644
index 0000000000..6765db6774
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.h
@@ -0,0 +1,124 @@
+// UpdateCallbackConsole.h
+
+#ifndef __UPDATE_CALLBACK_CONSOLE_H
+#define __UPDATE_CALLBACK_CONSOLE_H
+
+#include "../../../Common/StdOutStream.h"
+
+#include "../Common/Update.h"
+
+#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
+{
+protected:
+ 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);
+
+public:
+ bool NeedPercents() const { return _percent._so != NULL; };
+
+ bool StdOutMode;
+
+ bool NeedFlush;
+ unsigned PercentsNameLevel;
+ unsigned LogLevel;
+
+ AString _tempA;
+ UString _tempU;
+
+ CCallbackConsoleBase():
+ StdOutMode(false),
+ NeedFlush(false),
+ PercentsNameLevel(1),
+ LogLevel(0)
+ {}
+
+ void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
+
+ void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
+ {
+ FailedFiles.Clear();
+
+ _so = outStream;
+ _se = errorStream;
+ _percent._so = percentStream;
+ }
+
+ 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);
+
+};
+
+class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase
+{
+ // void PrintPropPair(const char *name, const wchar_t *val);
+
+public:
+ #ifndef _NO_CRYPTO
+ bool PasswordIsDefined;
+ UString Password;
+ bool AskPassword;
+ #endif
+
+ bool DeleteMessageWasShown;
+
+ CUpdateCallbackConsole()
+ : DeleteMessageWasShown(false)
+ #ifndef _NO_CRYPTO
+ , PasswordIsDefined(false)
+ , AskPassword(false)
+ #endif
+ {}
+
+ /*
+ void Init(CStdOutStream *outStream)
+ {
+ CCallbackConsoleBase::Init(outStream);
+ }
+ */
+ // ~CUpdateCallbackConsole() { if (NeedPercents()) _percent.ClosePrint(); }
+ INTERFACE_IUpdateCallbackUI2(;)
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.cpp
new file mode 100644
index 0000000000..7bdafdae55
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -0,0 +1,110 @@
+// UserInputUtils.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/StdInStream.h"
+#include "../../../Common/StringConvert.h"
+
+#include "UserInputUtils.h"
+
+static const char kYes = 'y';
+static const char kNo = 'n';
+static const char kYesAll = 'a';
+static const char kNoAll = 's';
+static const char kAutoRenameAll = 'u';
+static const char kQuit = 'q';
+
+static const char * const kFirstQuestionMessage = "? ";
+static const char * const kHelpQuestionMessage =
+ "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ";
+
+// return true if pressed Quite;
+
+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
+{
+ if (outStream)
+ *outStream << kFirstQuestionMessage;
+ for (;;)
+ {
+ if (outStream)
+ {
+ *outStream << kHelpQuestionMessage;
+ outStream->Flush();
+ }
+ AString scannedString;
+ if (!g_StdIn.ScanAStringUntilNewLine(scannedString))
+ return NUserAnswerMode::kError;
+ if (g_StdIn.Error())
+ return NUserAnswerMode::kError;
+ scannedString.Trim();
+ if (scannedString.IsEmpty() && g_StdIn.Eof())
+ return NUserAnswerMode::kEof;
+
+ if (scannedString.Len() == 1)
+ switch (::MyCharLower_Ascii(scannedString[0]))
+ {
+ case kYes: return NUserAnswerMode::kYes;
+ case kNo: return NUserAnswerMode::kNo;
+ case kYesAll: return NUserAnswerMode::kYesAll;
+ case kNoAll: return NUserAnswerMode::kNoAll;
+ case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll;
+ case kQuit: return NUserAnswerMode::kQuit;
+ }
+ }
+}
+
+#ifdef _WIN32
+#ifndef UNDER_CE
+#define MY_DISABLE_ECHO
+#endif
+#endif
+
+static bool GetPassword(CStdOutStream *outStream, UString &psw)
+{
+ if (outStream)
+ {
+ *outStream << "\nEnter password"
+ #ifdef MY_DISABLE_ECHO
+ " (will not be echoed)"
+ #endif
+ ":";
+ outStream->Flush();
+ }
+
+ #ifdef MY_DISABLE_ECHO
+
+ HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
+ bool wasChanged = false;
+ DWORD mode = 0;
+ if (console != INVALID_HANDLE_VALUE && console != 0)
+ if (GetConsoleMode(console, &mode))
+ wasChanged = (SetConsoleMode(console, mode & ~ENABLE_ECHO_INPUT) != 0);
+ bool res = g_StdIn.ScanUStringUntilNewLine(psw);
+ if (wasChanged)
+ SetConsoleMode(console, mode);
+
+ #else
+
+ bool res = g_StdIn.ScanUStringUntilNewLine(psw);
+
+ #endif
+
+ if (outStream)
+ {
+ *outStream << endl;
+ outStream->Flush();
+ }
+
+ return res;
+}
+
+HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw)
+{
+ if (!GetPassword(outStream, psw))
+ return E_INVALIDARG;
+ if (g_StdIn.Error())
+ return E_FAIL;
+ if (g_StdIn.Eof() && psw.IsEmpty())
+ return E_ABORT;
+ return S_OK;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.h b/other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.h
new file mode 100644
index 0000000000..ebe09c1eb9
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.h
@@ -0,0 +1,27 @@
+// UserInputUtils.h
+
+#ifndef __USER_INPUT_UTILS_H
+#define __USER_INPUT_UTILS_H
+
+#include "../../../Common/StdOutStream.h"
+
+namespace NUserAnswerMode {
+
+enum EEnum
+{
+ kYes,
+ kNo,
+ kYesAll,
+ kNoAll,
+ kAutoRenameAll,
+ kQuit,
+ kEof,
+ kError
+};
+}
+
+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);
+// bool GetPassword(CStdOutStream *outStream, UString &psw);
+HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/makefile b/other-licenses/7zstub/src/CPP/7zip/UI/Console/makefile
new file mode 100644
index 0000000000..31bc5c2829
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/makefile
@@ -0,0 +1,69 @@
+PROG = 7z.exe
+MY_CONSOLE = 1
+CFLAGS = $(CFLAGS) \
+ -DEXTERNAL_CODECS \
+
+!IFNDEF UNDER_CE
+CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE
+!ENDIF
+
+COMMON_OBJS = \
+ $O\CommandLineParser.obj \
+ $O\CRC.obj \
+ $O\IntToString.obj \
+ $O\ListFileUtils.obj \
+ $O\NewHandler.obj \
+ $O\StdInStream.obj \
+ $O\StdOutStream.obj \
+ $O\MyString.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\UTFConvert.obj \
+ $O\MyVector.obj \
+ $O\Wildcard.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\ErrorMsg.obj \
+ $O\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\FileLink.obj \
+ $O\FileName.obj \
+ $O\FileSystem.obj \
+ $O\MemoryLock.obj \
+ $O\PropVariant.obj \
+ $O\PropVariantConv.obj \
+ $O\Registry.obj \
+ $O\System.obj \
+ $O\TimeUtils.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\CreateCoder.obj \
+ $O\FilePathAutoRename.obj \
+ $O\FileStreams.obj \
+ $O\FilterCoder.obj \
+ $O\LimitedStreams.obj \
+ $O\MethodProps.obj \
+ $O\ProgressUtils.obj \
+ $O\PropId.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+ $O\UniqBlocks.obj \
+
+AR_COMMON_OBJS = \
+ $O\OutStreamWithCRC.obj \
+
+COMPRESS_OBJS = \
+ $O\CopyCoder.obj \
+
+C_OBJS = \
+ $O\Alloc.obj \
+ $O\CpuArch.obj \
+ $O\Sort.obj \
+ $O\Threads.obj \
+
+!include "../../Crc.mak"
+!include "Console.mak"
+
+!include "../../7zip.mak"
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Console/resource.rc b/other-licenses/7zstub/src/CPP/7zip/UI/Console/resource.rc
new file mode 100644
index 0000000000..8d721f5092
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Console/resource.rc
@@ -0,0 +1,7 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_APP("7-Zip Console" , "7z")
+
+#ifndef UNDER_CE
+1 24 MOVEABLE PURE "Console.manifest"
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.cpp
new file mode 100644
index 0000000000..1ef0d9c86f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.cpp
@@ -0,0 +1,37 @@
+// MyMessages.cpp
+
+#include "StdAfx.h"
+
+#include "MyMessages.h"
+
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/ResourceString.h"
+
+#include "../FileManager/LangUtils.h"
+
+using namespace NWindows;
+
+void ShowErrorMessage(HWND window, LPCWSTR message)
+{
+ ::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP);
+}
+
+void ShowErrorMessageHwndRes(HWND window, UINT resID)
+{
+ ShowErrorMessage(window, LangString(resID));
+}
+
+void ShowErrorMessageRes(UINT resID)
+{
+ ShowErrorMessageHwndRes(0, resID);
+}
+
+void ShowErrorMessageDWORD(HWND window, DWORD errorCode)
+{
+ ShowErrorMessage(window, NError::MyFormatMessage(errorCode));
+}
+
+void ShowLastErrorMessage(HWND window)
+{
+ ShowErrorMessageDWORD(window, ::GetLastError());
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.h b/other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.h
new file mode 100644
index 0000000000..c175e8a174
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.h
@@ -0,0 +1,16 @@
+// MyMessages.h
+
+#ifndef __MY_MESSAGES_H
+#define __MY_MESSAGES_H
+
+#include "../../../Common/MyString.h"
+
+void ShowErrorMessage(HWND window, LPCWSTR message);
+inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(0, message); }
+
+void ShowErrorMessageHwndRes(HWND window, UInt32 langID);
+void ShowErrorMessageRes(UInt32 langID);
+
+void ShowLastErrorMessage(HWND window = 0);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.cpp
new file mode 100644
index 0000000000..d5c981c54b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -0,0 +1,1025 @@
+// BrowseDialog.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyWindows.h"
+
+#include <commctrl.h>
+
+#ifndef UNDER_CE
+#include "../../../Windows/CommonDialog.h"
+#include "../../../Windows/Shell.h"
+#endif
+
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/FileFind.h"
+
+#ifdef UNDER_CE
+#include <commdlg.h>
+#endif
+
+#include "BrowseDialog.h"
+
+#define USE_MY_BROWSE_DIALOG
+
+#ifdef USE_MY_BROWSE_DIALOG
+
+#include "../../../Common/Defs.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/PropVariantConv.h"
+
+#include "../../../Windows/Control/ComboBox.h"
+#include "../../../Windows/Control/Dialog.h"
+#include "../../../Windows/Control/Edit.h"
+#include "../../../Windows/Control/ListView.h"
+
+#include "BrowseDialogRes.h"
+#include "PropertyNameRes.h"
+#include "SysIconUtils.h"
+
+#ifndef _SFX
+#include "RegistryUtils.h"
+#endif
+
+#endif
+
+#include "ComboDialog.h"
+#include "LangUtils.h"
+
+#include "resource.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+using namespace NFind;
+
+#ifdef USE_MY_BROWSE_DIALOG
+
+extern bool g_LVN_ITEMACTIVATE_Support;
+
+static const int kParentIndex = -1;
+static const UINT k_Message_RefreshPathEdit = WM_APP + 1;
+
+static HRESULT GetNormalizedError()
+{
+ DWORD errorCode = GetLastError();
+ return errorCode == 0 ? E_FAIL : errorCode;
+}
+
+extern UString HResultToMessage(HRESULT errorCode);
+
+static void MessageBox_Error_Global(HWND wnd, const wchar_t *message)
+{
+ ::MessageBoxW(wnd, message, L"7-Zip", MB_ICONERROR);
+}
+
+static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name)
+{
+ UString s = HResultToMessage(errorCode);
+ if (name)
+ {
+ s.Add_LF();
+ s += name;
+ }
+ MessageBox_Error_Global(wnd, s);
+}
+
+class CBrowseDialog: public NControl::CModalDialog
+{
+ NControl::CListView _list;
+ NControl::CEdit _pathEdit;
+ NControl::CComboBox _filterCombo;
+
+ CObjectVector<CFileInfo> _files;
+
+ CExtToIconMap _extToIconMap;
+ int _sortIndex;
+ bool _ascending;
+ bool _showDots;
+ UString _topDirPrefix; // we don't open parent of that folder
+ UString DirPrefix;
+
+ virtual bool OnInit();
+ virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
+ virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
+ virtual bool OnNotify(UINT controlID, LPNMHDR header);
+ virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo);
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ virtual void OnOK();
+
+ void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); }
+
+ bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);
+ // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
+ HRESULT Reload(const UString &pathPrefix, const UString &selectedName);
+ HRESULT Reload();
+
+ void OpenParentFolder();
+ void SetPathEditText();
+ void OnCreateDir();
+ void OnItemEnter();
+ void FinishOnOK();
+
+ int GetRealItemIndex(int indexInListView) const
+ {
+ LPARAM param;
+ if (!_list.GetItemParam(indexInListView, param))
+ return (int)-1;
+ return (int)param;
+ }
+
+public:
+ bool FolderMode;
+ UString Title;
+ UString FilePath; // input/ result path
+ bool ShowAllFiles;
+ UStringVector Filters;
+ UString FilterDescription;
+
+ CBrowseDialog(): FolderMode(false), _showDots(false), ShowAllFiles(true) {}
+ void SetFilter(const UString &s);
+ INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_BROWSE, parent); }
+ int CompareItems(LPARAM lParam1, LPARAM lParam2);
+};
+
+void CBrowseDialog::SetFilter(const UString &s)
+{
+ Filters.Clear();
+ UString mask;
+ unsigned i;
+ for (i = 0; i < s.Len(); i++)
+ {
+ wchar_t c = s[i];
+ if (c == ';')
+ {
+ if (!mask.IsEmpty())
+ Filters.Add(mask);
+ mask.Empty();
+ }
+ else
+ mask += c;
+ }
+ if (!mask.IsEmpty())
+ Filters.Add(mask);
+ ShowAllFiles = Filters.IsEmpty();
+ for (i = 0; i < Filters.Size(); i++)
+ {
+ const UString &f = Filters[i];
+ if (f == L"*.*" || f == L"*")
+ {
+ ShowAllFiles = true;
+ break;
+ }
+ }
+}
+
+bool CBrowseDialog::OnInit()
+{
+ #ifdef LANG
+ LangSetDlgItems(*this, NULL, 0);
+ #endif
+ if (!Title.IsEmpty())
+ SetText(Title);
+ _list.Attach(GetItem(IDL_BROWSE));
+ _filterCombo.Attach(GetItem(IDC_BROWSE_FILTER));
+ _pathEdit.Attach(GetItem(IDE_BROWSE_PATH));
+
+ if (FolderMode)
+ HideItem(IDC_BROWSE_FILTER);
+ else
+ EnableItem(IDC_BROWSE_FILTER, false);
+
+ #ifndef UNDER_CE
+ _list.SetUnicodeFormat();
+ #endif
+
+ #ifndef _SFX
+ CFmSettings st;
+ st.Load();
+ if (st.SingleClick)
+ _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT);
+ _showDots = st.ShowDots;
+ #endif
+
+ {
+ UString s;
+ if (!FilterDescription.IsEmpty())
+ s = FilterDescription;
+ else if (ShowAllFiles)
+ s = "*.*";
+ else
+ {
+ FOR_VECTOR (i, Filters)
+ {
+ if (i != 0)
+ s.Add_Space();
+ s += Filters[i];
+ }
+ }
+ _filterCombo.AddString(s);
+ _filterCombo.SetCurSel(0);
+ }
+
+ _list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
+ _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
+
+ _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100);
+ _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100);
+ {
+ LV_COLUMNW column;
+ column.iSubItem = 2;
+ column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ column.fmt = LVCFMT_RIGHT;
+ column.cx = 100;
+ const UString s = LangString(IDS_PROP_SIZE);
+ column.pszText = (wchar_t *)(const wchar_t *)s;
+ _list.InsertColumn(2, &column);
+ }
+
+ _list.InsertItem(0, L"12345678901234567"
+ #ifndef UNDER_CE
+ L"1234567890"
+ #endif
+ );
+ _list.SetSubItem(0, 1, L"2009-09-09"
+ #ifndef UNDER_CE
+ L" 09:09"
+ #endif
+ );
+ _list.SetSubItem(0, 2, L"9999 MB");
+ for (int i = 0; i < 3; i++)
+ _list.SetColumnWidthAuto(i);
+ _list.DeleteAllItems();
+
+ _ascending = true;
+ _sortIndex = 0;
+
+ NormalizeSize();
+
+ _topDirPrefix.Empty();
+ {
+ int rootSize = GetRootPrefixSize(FilePath);
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ // We can go up from root folder to drives list
+ if (IsDrivePath(FilePath))
+ rootSize = 0;
+ else if (IsSuperPath(FilePath))
+ {
+ if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize)))
+ rootSize = kSuperPathPrefixSize;
+ }
+ #endif
+ _topDirPrefix.SetFrom(FilePath, rootSize);
+ }
+
+ UString name;
+ if (!GetParentPath(FilePath, DirPrefix, name))
+ DirPrefix = _topDirPrefix;
+
+ for (;;)
+ {
+ UString baseFolder = DirPrefix;
+ if (Reload(baseFolder, name) == S_OK)
+ break;
+ name.Empty();
+ if (DirPrefix.IsEmpty())
+ break;
+ UString parent, name2;
+ GetParentPath(DirPrefix, parent, name2);
+ DirPrefix = parent;
+ }
+
+ if (name.IsEmpty())
+ name = FilePath;
+ if (FolderMode)
+ NormalizeDirPathPrefix(name);
+ _pathEdit.SetText(name);
+
+ #ifndef UNDER_CE
+ /* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible,
+ even if we use mouse for pressing the button to open this dialog. */
+ PostMsg(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS));
+ #endif
+
+ return CModalDialog::OnInit();
+}
+
+bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
+{
+ int mx, my;
+ {
+ RECT r;
+ GetClientRectOfItem(IDB_BROWSE_PARENT, r);
+ mx = r.left;
+ my = r.top;
+ }
+ InvalidateRect(NULL);
+
+ int xLim = xSize - mx;
+ {
+ RECT r;
+ GetClientRectOfItem(IDT_BROWSE_FOLDER, r);
+ MoveItem(IDT_BROWSE_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r));
+ }
+
+ int bx1, bx2, by;
+ GetItemSizes(IDCANCEL, bx1, by);
+ GetItemSizes(IDOK, bx2, by);
+ int y = ySize - my - by;
+ int x = xLim - bx1;
+ MoveItem(IDCANCEL, x, y, bx1, by);
+ MoveItem(IDOK, x - mx - bx2, y, bx2, by);
+
+ // Y_Size of ComboBox is tricky. So we use Y_Size of _pathEdit instead
+
+ int yPathSize;
+ {
+ RECT r;
+ GetClientRectOfItem(IDE_BROWSE_PATH, r);
+ yPathSize = RECT_SIZE_Y(r);
+ _pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize);
+ }
+
+ {
+ RECT r;
+ GetClientRectOfItem(IDC_BROWSE_FILTER, r);
+ _filterCombo.Move(r.left, y - my - yPathSize, xLim - r.left, RECT_SIZE_Y(r));
+ }
+
+ {
+ RECT r;
+ GetClientRectOfItem(IDL_BROWSE, r);
+ _list.Move(r.left, r.top, xLim - r.left, y - my - yPathSize - my - yPathSize - my - r.top);
+ }
+
+ return false;
+}
+
+bool CBrowseDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (message == k_Message_RefreshPathEdit)
+ {
+ SetPathEditText();
+ return true;
+ }
+ return CModalDialog::OnMessage(message, wParam, lParam);
+}
+
+bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
+{
+ if (header->hwndFrom != _list)
+ return false;
+ switch (header->code)
+ {
+ case LVN_ITEMACTIVATE:
+ if (g_LVN_ITEMACTIVATE_Support)
+ OnItemEnter();
+ break;
+ case NM_DBLCLK:
+ case NM_RETURN: // probabably it's unused
+ if (!g_LVN_ITEMACTIVATE_Support)
+ OnItemEnter();
+ break;
+ case LVN_COLUMNCLICK:
+ {
+ int index = LPNMLISTVIEW(header)->iSubItem;
+ if (index == _sortIndex)
+ _ascending = !_ascending;
+ else
+ {
+ _ascending = (index == 0);
+ _sortIndex = index;
+ }
+ Reload();
+ return false;
+ }
+ case LVN_KEYDOWN:
+ {
+ bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header));
+ Post_RefreshPathEdit();
+ return boolResult;
+ }
+ case NM_RCLICK:
+ case NM_CLICK:
+ case LVN_BEGINDRAG:
+ Post_RefreshPathEdit();
+ break;
+ }
+ return false;
+}
+
+bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo)
+{
+ bool ctrl = IsKeyDown(VK_CONTROL);
+
+ switch (keyDownInfo->wVKey)
+ {
+ case VK_BACK:
+ OpenParentFolder();
+ return true;
+ case 'R':
+ if (ctrl)
+ {
+ Reload();
+ return true;
+ }
+ return false;
+ case VK_F7:
+ OnCreateDir();
+ return true;
+ }
+ return false;
+}
+
+bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ switch (buttonID)
+ {
+ case IDB_BROWSE_PARENT: OpenParentFolder(); break;
+ case IDB_BROWSE_CREATE_DIR: OnCreateDir(); break;
+ default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
+ }
+ _list.SetFocus();
+ return true;
+}
+
+void CBrowseDialog::OnOK()
+{
+ /* When we press "Enter" in listview, Windows sends message to first Button.
+ We check that message was from ListView; */
+ if (GetFocus() == _list)
+ {
+ OnItemEnter();
+ return;
+ }
+ FinishOnOK();
+}
+
+
+bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name)
+{
+ parentPrefix.Empty();
+ name.Empty();
+ if (path.IsEmpty())
+ return false;
+ if (_topDirPrefix == path)
+ return false;
+ UString s = path;
+ if (IS_PATH_SEPAR(s.Back()))
+ s.DeleteBack();
+ if (s.IsEmpty())
+ return false;
+ if (IS_PATH_SEPAR(s.Back()))
+ return false;
+ int pos = s.ReverseFind_PathSepar();
+ parentPrefix.SetFrom(s, pos + 1);
+ name = s.Ptr(pos + 1);
+ return true;
+}
+
+int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2)
+{
+ if (lParam1 == kParentIndex) return -1;
+ if (lParam2 == kParentIndex) return 1;
+ const CFileInfo &f1 = _files[(int)lParam1];
+ const CFileInfo &f2 = _files[(int)lParam2];
+
+ bool isDir1 = f1.IsDir();
+ bool isDir2 = f2.IsDir();
+ if (isDir1 && !isDir2) return -1;
+ if (isDir2 && !isDir1) return 1;
+
+ int res = 0;
+ switch (_sortIndex)
+ {
+ case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break;
+ case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break;
+ case 2: res = MyCompare(f1.Size, f2.Size); break;
+ }
+ return _ascending ? res: -res;
+}
+
+static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
+{
+ return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2);
+}
+
+static void ConvertSizeToString(UInt64 v, wchar_t *s)
+{
+ Byte c = 0;
+ if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; }
+ else if (v >= ((UInt64)10000 << 10)) { v >>= 20; c = 'M'; }
+ else if (v >= ((UInt64)10000 << 0)) { v >>= 10; c = 'K'; }
+ ConvertUInt64ToString(v, s);
+ if (c != 0)
+ {
+ s += MyStringLen(s);
+ *s++ = ' ';
+ *s++ = c;
+ *s++ = 0;
+ }
+}
+
+// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
+
+HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName)
+{
+ CObjectVector<CFileInfo> files;
+
+ #ifndef UNDER_CE
+ bool isDrive = false;
+ if (pathPrefix.IsEmpty() || pathPrefix.IsEqualTo(kSuperPathPrefix))
+ {
+ isDrive = true;
+ FStringVector drives;
+ if (!MyGetLogicalDriveStrings(drives))
+ return GetNormalizedError();
+ FOR_VECTOR (i, drives)
+ {
+ FString d = drives[i];
+ if (d.Len() < 3 || d.Back() != '\\')
+ return E_FAIL;
+ d.DeleteBack();
+ CFileInfo &fi = files.AddNew();
+ fi.SetAsDir();
+ fi.Name = d;
+ }
+ }
+ else
+ #endif
+ {
+ CEnumerator enumerator;
+ enumerator.SetDirPrefix(us2fs(pathPrefix));
+ for (;;)
+ {
+ bool found;
+ CFileInfo fi;
+ if (!enumerator.Next(fi, found))
+ return GetNormalizedError();
+ if (!found)
+ break;
+ if (!fi.IsDir())
+ {
+ if (FolderMode)
+ continue;
+ if (!ShowAllFiles)
+ {
+ unsigned i;
+ for (i = 0; i < Filters.Size(); i++)
+ if (DoesWildcardMatchName(Filters[i], fs2us(fi.Name)))
+ break;
+ if (i == Filters.Size())
+ continue;
+ }
+ }
+ files.Add(fi);
+ }
+ }
+
+ DirPrefix = pathPrefix;
+
+ _files = files;
+
+ SetItemText(IDT_BROWSE_FOLDER, DirPrefix);
+
+ _list.SetRedraw(false);
+ _list.DeleteAllItems();
+
+ LVITEMW item;
+
+ int index = 0;
+ int cursorIndex = -1;
+
+ #ifndef _SFX
+ if (_showDots && _topDirPrefix != DirPrefix)
+ {
+ item.iItem = index;
+ const UString itemName ("..");
+ if (selectedName.IsEmpty())
+ cursorIndex = index;
+ item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
+ int subItem = 0;
+ item.iSubItem = subItem++;
+ item.lParam = kParentIndex;
+ item.pszText = (wchar_t *)(const wchar_t *)itemName;
+ item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix);
+ if (item.iImage < 0)
+ item.iImage = 0;
+ _list.InsertItem(&item);
+ _list.SetSubItem(index, subItem++, L"");
+ _list.SetSubItem(index, subItem++, L"");
+ index++;
+ }
+ #endif
+
+ for (unsigned i = 0; i < _files.Size(); i++, index++)
+ {
+ item.iItem = index;
+ const CFileInfo &fi = _files[i];
+ const UString name = fs2us(fi.Name);
+ if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0)
+ cursorIndex = index;
+ item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
+ int subItem = 0;
+ item.iSubItem = subItem++;
+ item.lParam = i;
+ item.pszText = (wchar_t *)(const wchar_t *)name;
+
+ const UString fullPath = DirPrefix + name;
+ #ifndef UNDER_CE
+ if (isDrive)
+ {
+ if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
+ item.iImage = 0;
+ }
+ else
+ #endif
+ item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
+ if (item.iImage < 0)
+ item.iImage = 0;
+ _list.InsertItem(&item);
+ wchar_t s[32];
+ {
+ s[0] = 0;
+ ConvertUtcFileTimeToString(fi.MTime, s,
+ #ifndef UNDER_CE
+ kTimestampPrintLevel_MIN
+ #else
+ kTimestampPrintLevel_DAY
+ #endif
+ );
+ _list.SetSubItem(index, subItem++, s);
+ }
+ {
+ s[0] = 0;
+ if (!fi.IsDir())
+ ConvertSizeToString(fi.Size, s);
+ _list.SetSubItem(index, subItem++, s);
+ }
+ }
+
+ if (_list.GetItemCount() > 0 && cursorIndex >= 0)
+ _list.SetItemState_FocusedSelected(cursorIndex);
+ _list.SortItems(CompareItems2, (LPARAM)this);
+ if (_list.GetItemCount() > 0 && cursorIndex < 0)
+ _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
+ _list.EnsureVisible(_list.GetFocusedItem(), false);
+ _list.SetRedraw(true);
+ _list.InvalidateRect(NULL, true);
+ return S_OK;
+}
+
+HRESULT CBrowseDialog::Reload()
+{
+ UString selected;
+ int index = _list.GetNextSelectedItem(-1);
+ if (index >= 0)
+ {
+ int fileIndex = GetRealItemIndex(index);
+ if (fileIndex != kParentIndex)
+ selected = fs2us(_files[fileIndex].Name);
+ }
+ UString dirPathTemp = DirPrefix;
+ return Reload(dirPathTemp, selected);
+}
+
+void CBrowseDialog::OpenParentFolder()
+{
+ UString parent, selected;
+ if (GetParentPath(DirPrefix, parent, selected))
+ {
+ Reload(parent, selected);
+ SetPathEditText();
+ }
+}
+
+void CBrowseDialog::SetPathEditText()
+{
+ int index = _list.GetNextSelectedItem(-1);
+ if (index < 0)
+ {
+ if (FolderMode)
+ _pathEdit.SetText(DirPrefix);
+ return;
+ }
+ int fileIndex = GetRealItemIndex(index);
+ if (fileIndex == kParentIndex)
+ {
+ if (FolderMode)
+ _pathEdit.SetText(L".." WSTRING_PATH_SEPARATOR);
+ return;
+ }
+ const CFileInfo &file = _files[fileIndex];
+ if (file.IsDir())
+ {
+ if (!FolderMode)
+ return;
+ _pathEdit.SetText(fs2us(file.Name) + WCHAR_PATH_SEPARATOR);
+ }
+ else
+ _pathEdit.SetText(fs2us(file.Name));
+}
+
+void CBrowseDialog::OnCreateDir()
+{
+ UString name;
+ {
+ UString enteredName;
+ Dlg_CreateFolder((HWND)*this, enteredName);
+ if (enteredName.IsEmpty())
+ return;
+ if (!CorrectFsPath(DirPrefix, enteredName, name))
+ {
+ MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, name);
+ return;
+ }
+ }
+ if (name.IsEmpty())
+ return;
+
+ FString destPath;
+ if (GetFullPath(us2fs(DirPrefix), us2fs(name), destPath))
+ {
+ if (!NDir::CreateComplexDir(destPath))
+ {
+ MessageBox_HResError((HWND)*this, GetNormalizedError(), fs2us(destPath));
+ }
+ else
+ {
+ UString tempPath = DirPrefix;
+ Reload(tempPath, name);
+ SetPathEditText();
+ }
+ _list.SetFocus();
+ }
+}
+
+void CBrowseDialog::OnItemEnter()
+{
+ int index = _list.GetNextSelectedItem(-1);
+ if (index < 0)
+ return;
+ int fileIndex = GetRealItemIndex(index);
+ if (fileIndex == kParentIndex)
+ OpenParentFolder();
+ else
+ {
+ const CFileInfo &file = _files[fileIndex];
+ if (!file.IsDir())
+ {
+ if (!FolderMode)
+ FinishOnOK();
+ /*
+ MessageBox_Error_Global(*this, FolderMode ?
+ L"You must select some folder":
+ L"You must select some file");
+ */
+ return;
+ }
+ UString s = DirPrefix;
+ s += fs2us(file.Name);
+ s.Add_PathSepar();
+ HRESULT res = Reload(s, UString());
+ if (res != S_OK)
+ MessageBox_HResError(*this, res, s);
+ SetPathEditText();
+ }
+}
+
+void CBrowseDialog::FinishOnOK()
+{
+ UString s;
+ _pathEdit.GetText(s);
+ FString destPath;
+ if (!GetFullPath(us2fs(DirPrefix), us2fs(s), destPath))
+ {
+ MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, s);
+ return;
+ }
+ FilePath = fs2us(destPath);
+ if (FolderMode)
+ NormalizeDirPathPrefix(FilePath);
+ End(IDOK);
+}
+
+#endif
+
+bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath)
+{
+ resultPath.Empty();
+
+ #ifndef UNDER_CE
+
+ #ifdef USE_MY_BROWSE_DIALOG
+ if (!IsSuperOrDevicePath(path))
+ #endif
+ return NShell::BrowseForFolder(owner, title, path, resultPath);
+
+ #endif
+
+ #ifdef USE_MY_BROWSE_DIALOG
+
+ CBrowseDialog dialog;
+ dialog.FolderMode = true;
+ if (title)
+ dialog.Title = title;
+ if (path)
+ dialog.FilePath = path;
+ if (dialog.Create(owner) != IDOK)
+ return false;
+ resultPath = dialog.FilePath;
+ #endif
+
+ return true;
+}
+
+bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path,
+ LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath)
+{
+ resultPath.Empty();
+
+ #ifndef UNDER_CE
+
+ #ifdef USE_MY_BROWSE_DIALOG
+ if (!IsSuperOrDevicePath(path))
+ #endif
+ {
+ if (MyGetOpenFileName(owner, title, NULL, path, filterDescription, filter, resultPath))
+ return true;
+ #ifdef UNDER_CE
+ return false;
+ #else
+ // maybe we must use GetLastError in WinCE.
+ DWORD errorCode = CommDlgExtendedError();
+ const char *errorMessage = NULL;
+ switch (errorCode)
+ {
+ case 0: return false; // cancel or close obn dialog
+ case FNERR_INVALIDFILENAME: errorMessage = "Invalid File Name"; break;
+ default: errorMessage = "Open Dialog Error";
+ }
+ if (!errorMessage)
+ return false;
+ {
+ UString s (errorMessage);
+ s.Add_LF();
+ s += path;
+ MessageBox_Error_Global(owner, s);
+ }
+ #endif
+ }
+
+ #endif
+
+ #ifdef USE_MY_BROWSE_DIALOG
+ CBrowseDialog dialog;
+ if (title)
+ dialog.Title = title;
+ if (path)
+ dialog.FilePath = path;
+ dialog.FolderMode = false;
+ if (filter)
+ dialog.SetFilter(filter);
+ if (filterDescription)
+ dialog.FilterDescription = filterDescription;
+ if (dialog.Create(owner) != IDOK)
+ return false;
+ resultPath = dialog.FilePath;
+ #endif
+
+ return true;
+}
+
+
+#ifdef _WIN32
+
+static void RemoveDotsAndSpaces(UString &path)
+{
+ while (!path.IsEmpty())
+ {
+ wchar_t c = path.Back();
+ if (c != ' ' && c != '.')
+ return;
+ path.DeleteBack();
+ }
+}
+
+
+bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result)
+{
+ result.Empty();
+
+ UString path = path2;
+ path.Replace(L'/', WCHAR_PATH_SEPARATOR);
+ unsigned start = 0;
+ UString base;
+
+ 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;
+ }
+
+ /* We can't use backward, since we must change only disk paths */
+ /*
+ for (;;)
+ {
+ if (path.Len() <= start)
+ break;
+ if (DoesFileOrDirExist(us2fs(path)))
+ break;
+ if (path.Back() == WCHAR_PATH_SEPARATOR)
+ {
+ path.DeleteBack();
+ result.Insert(0, WCHAR_PATH_SEPARATOR);;
+ }
+ int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1;
+ UString cur = path.Ptr(pos);
+ RemoveDotsAndSpaces(cur);
+ result.Insert(0, cur);
+ path.DeleteFrom(pos);
+ }
+ result.Insert(0, path);
+ return true;
+ */
+
+ result += path.Left(start);
+ bool checkExist = true;
+ UString cur;
+
+ for (;;)
+ {
+ if (start == path.Len())
+ break;
+ int slashPos = path.Find(WCHAR_PATH_SEPARATOR, start);
+ cur.SetFrom(path.Ptr(start), (slashPos < 0 ? path.Len() : slashPos) - start);
+ if (checkExist)
+ {
+ CFileInfo fi;
+ if (fi.Find(us2fs(base + result + cur)))
+ {
+ if (!fi.IsDir())
+ {
+ result = path;
+ break;
+ }
+ }
+ else
+ checkExist = false;
+ }
+ if (!checkExist)
+ RemoveDotsAndSpaces(cur);
+ result += cur;
+ if (slashPos < 0)
+ break;
+ result.Add_PathSepar();
+ start = slashPos + 1;
+ }
+
+ return true;
+}
+
+#else
+
+bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result)
+{
+ result = path;
+ return true;
+}
+
+#endif
+
+bool Dlg_CreateFolder(HWND wnd, UString &destName)
+{
+ destName.Empty();
+ CComboDialog dlg;
+ LangString(IDS_CREATE_FOLDER, dlg.Title);
+ LangString(IDS_CREATE_FOLDER_NAME, dlg.Static);
+ LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, dlg.Value);
+ if (dlg.Create(wnd) != IDOK)
+ return false;
+ destName = dlg.Value;
+ return true;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.h
new file mode 100644
index 0000000000..be51085bfa
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.h
@@ -0,0 +1,21 @@
+// BrowseDialog.h
+
+#ifndef __BROWSE_DIALOG_H
+#define __BROWSE_DIALOG_H
+
+#include "../../../Common/MyString.h"
+
+bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath);
+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 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 */
+
+bool CorrectFsPath(const UString &relBase, const UString &path, UString &result);
+
+bool Dlg_CreateFolder(HWND wnd, UString &destName);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialogRes.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialogRes.h
new file mode 100644
index 0000000000..f211b7374b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialogRes.h
@@ -0,0 +1,9 @@
+#define IDD_BROWSE 95
+
+#define IDL_BROWSE 100
+#define IDT_BROWSE_FOLDER 101
+#define IDE_BROWSE_PATH 102
+#define IDC_BROWSE_FILTER 103
+
+#define IDB_BROWSE_PARENT 110
+#define IDB_BROWSE_CREATE_DIR 112
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.cpp
new file mode 100644
index 0000000000..e846c56134
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.cpp
@@ -0,0 +1,64 @@
+// ComboDialog.cpp
+
+#include "StdAfx.h"
+#include "ComboDialog.h"
+
+#include "../../../Windows/Control/Static.h"
+
+#ifdef LANG
+#include "LangUtils.h"
+#endif
+
+using namespace NWindows;
+
+bool CComboDialog::OnInit()
+{
+ #ifdef LANG
+ LangSetDlgItems(*this, NULL, 0);
+ #endif
+ _comboBox.Attach(GetItem(IDC_COMBO));
+
+ /*
+ // why it doesn't work ?
+ DWORD style = _comboBox.GetStyle();
+ if (Sorted)
+ style |= CBS_SORT;
+ else
+ style &= ~CBS_SORT;
+ _comboBox.SetStyle(style);
+ */
+ SetText(Title);
+
+ NControl::CStatic staticContol;
+ staticContol.Attach(GetItem(IDT_COMBO));
+ staticContol.SetText(Static);
+ _comboBox.SetText(Value);
+ FOR_VECTOR (i, Strings)
+ _comboBox.AddString(Strings[i]);
+ NormalizeSize();
+ return CModalDialog::OnInit();
+}
+
+bool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
+{
+ int mx, my;
+ GetMargins(8, mx, my);
+ int bx1, bx2, by;
+ GetItemSizes(IDCANCEL, bx1, by);
+ GetItemSizes(IDOK, bx2, by);
+ int y = ySize - my - by;
+ int x = xSize - mx - bx1;
+
+ InvalidateRect(NULL);
+
+ MoveItem(IDCANCEL, x, y, bx1, by);
+ MoveItem(IDOK, x - mx - bx2, y, bx2, by);
+ ChangeSubWindowSizeX(_comboBox, xSize - mx * 2);
+ return false;
+}
+
+void CComboDialog::OnOK()
+{
+ _comboBox.GetText(Value);
+ CModalDialog::OnOK();
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.h
new file mode 100644
index 0000000000..6869cff703
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.h
@@ -0,0 +1,28 @@
+// ComboDialog.h
+
+#ifndef __COMBO_DIALOG_H
+#define __COMBO_DIALOG_H
+
+#include "../../../Windows/Control/ComboBox.h"
+#include "../../../Windows/Control/Dialog.h"
+
+#include "ComboDialogRes.h"
+
+class CComboDialog: public NWindows::NControl::CModalDialog
+{
+ NWindows::NControl::CComboBox _comboBox;
+ virtual void OnOK();
+ virtual bool OnInit();
+ virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
+public:
+ // bool Sorted;
+ UString Title;
+ UString Static;
+ UString Value;
+ UStringVector Strings;
+
+ // CComboDialog(): Sorted(false) {};
+ INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COMBO, parentWindow); }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialogRes.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialogRes.h
new file mode 100644
index 0000000000..98938b63bc
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialogRes.h
@@ -0,0 +1,4 @@
+#define IDD_COMBO 98
+
+#define IDT_COMBO 100
+#define IDC_COMBO 101
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/DialogSize.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/DialogSize.h
new file mode 100644
index 0000000000..bbce15982b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/DialogSize.h
@@ -0,0 +1,16 @@
+// DialogSize.h
+
+#ifndef __DIALOG_SIZE_H
+#define __DIALOG_SIZE_H
+
+#include "../../../Windows/Control/Dialog.h"
+
+#ifdef UNDER_CE
+#define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y);
+#define SIZED_DIALOG(big) (isBig ? big : big ## _2)
+#else
+#define BIG_DIALOG_SIZE(x, y)
+#define SIZED_DIALOG(big) big
+#endif
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.cpp
new file mode 100644
index 0000000000..6433e917dc
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -0,0 +1,1033 @@
+// ExtractCallback.cpp
+
+#include "StdAfx.h"
+
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/Lang.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/PropVariantConv.h"
+
+#include "../../Common/FilePathAutoRename.h"
+#include "../../Common/StreamUtils.h"
+#include "../Common/ExtractingFilePath.h"
+
+#ifndef _SFX
+#include "../Common/ZipRegistry.h"
+#endif
+
+#include "../GUI/ExtractRes.h"
+#include "resourceGui.h"
+
+#include "ExtractCallback.h"
+#include "FormatUtils.h"
+#include "LangUtils.h"
+#include "OverwriteDialog.h"
+#ifndef _NO_CRYPTO
+#include "PasswordDialog.h"
+#endif
+#include "PropertyName.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NFind;
+
+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
+ NumFolders = NumFiles = 0;
+ NeedAddFile = false;
+ #endif
+}
+
+void CExtractCallbackImp::AddError_Message(LPCWSTR s)
+{
+ ThereAreMessageErrors = true;
+ ProgressDialog->Sync.AddError_Message(s);
+}
+
+#ifndef _SFX
+
+STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64
+ #ifndef _SFX
+ numFiles
+ #endif
+ )
+{
+ #ifndef _SFX
+ ProgressDialog->Sync.Set_NumFilesTotal(numFiles);
+ #endif
+ return S_OK;
+}
+
+#endif
+
+STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 total)
+{
+ ProgressDialog->Sync.Set_NumBytesTotal(total);
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *value)
+{
+ return ProgressDialog->Sync.Set_NumBytesCur(value);
+}
+
+HRESULT CExtractCallbackImp::Open_CheckBreak()
+{
+ return ProgressDialog->Sync.CheckStop();
+}
+
+HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)
+{
+ HRESULT res = S_OK;
+ if (!MultiArcMode)
+ {
+ if (files)
+ {
+ _totalFilesDefined = true;
+ // res = ProgressDialog->Sync.Set_NumFilesTotal(*files);
+ }
+ else
+ _totalFilesDefined = false;
+
+ if (bytes)
+ {
+ _totalBytesDefined = true;
+ ProgressDialog->Sync.Set_NumBytesTotal(*bytes);
+ }
+ else
+ _totalBytesDefined = false;
+ }
+
+ return res;
+}
+
+HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)
+{
+ if (!MultiArcMode)
+ {
+ if (files)
+ {
+ ProgressDialog->Sync.Set_NumFilesCur(*files);
+ }
+
+ if (bytes)
+ {
+ }
+ }
+
+ return ProgressDialog->Sync.CheckStop();
+}
+
+HRESULT CExtractCallbackImp::Open_Finished()
+{
+ return ProgressDialog->Sync.CheckStop();
+}
+
+#ifndef _NO_CRYPTO
+
+HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)
+{
+ return CryptoGetTextPassword(password);
+}
+
+/*
+HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
+{
+ passwordIsDefined = PasswordIsDefined;
+ password = Password;
+ return S_OK;
+}
+
+bool CExtractCallbackImp::Open_WasPasswordAsked()
+{
+ return PasswordWasAsked;
+}
+
+void CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag()
+{
+ PasswordWasAsked = false;
+}
+*/
+
+#endif
+
+
+#ifndef _SFX
+STDMETHODIMP CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ ProgressDialog->Sync.Set_Ratio(inSize, outSize);
+ return S_OK;
+}
+#endif
+
+/*
+STDMETHODIMP CExtractCallbackImp::SetTotalFiles(UInt64 total)
+{
+ ProgressDialog->Sync.SetNumFilesTotal(total);
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackImp::SetCompletedFiles(const UInt64 *value)
+{
+ if (value != NULL)
+ ProgressDialog->Sync.SetNumFilesCur(*value);
+ return S_OK;
+}
+*/
+
+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)
+{
+ COverwriteDialog dialog;
+
+ dialog.OldFileInfo.SetTime(existTime);
+ dialog.OldFileInfo.SetSize(existSize);
+ dialog.OldFileInfo.Name = existName;
+
+ dialog.NewFileInfo.SetTime(newTime);
+ dialog.NewFileInfo.SetSize(newSize);
+ dialog.NewFileInfo.Name = newName;
+
+ ProgressDialog->WaitCreating();
+ INT_PTR writeAnswer = dialog.Create(*ProgressDialog);
+
+ switch (writeAnswer)
+ {
+ case IDCANCEL: *answer = NOverwriteAnswer::kCancel; return E_ABORT;
+ case IDYES: *answer = NOverwriteAnswer::kYes; break;
+ case IDNO: *answer = NOverwriteAnswer::kNo; break;
+ case IDB_YES_TO_ALL: *answer = NOverwriteAnswer::kYesToAll; break;
+ case IDB_NO_TO_ALL: *answer = NOverwriteAnswer::kNoToAll; break;
+ case IDB_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break;
+ default: return E_FAIL;
+ }
+ return S_OK;
+}
+
+
+STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */)
+{
+ _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)
+{
+ AddError_Message(s);
+ return S_OK;
+}
+
+HRESULT CExtractCallbackImp::MessageError(const char *message, const FString &path)
+{
+ ThereAreMessageErrors = true;
+ ProgressDialog->Sync.AddError_Message_Name(GetUnicodeString(message), fs2us(path));
+ return S_OK;
+}
+
+#ifndef _SFX
+
+STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s)
+{
+ AddError_Message(s);
+ return S_OK;
+}
+
+#endif
+
+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::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:
+ messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;
+ break;
+ */
+ }
+
+ UString msg;
+ UString msgOld;
+
+ #ifndef _SFX
+ if (id != 0)
+ LangString_OnlyFromLangFile(id, msg);
+ if (messageID != 0 && msg.IsEmpty())
+ LangString_OnlyFromLangFile(messageID, msgOld);
+ #endif
+
+ if (msg.IsEmpty() && !msgOld.IsEmpty())
+ s = MyFormatNew(msgOld, fileName);
+ else
+ {
+ if (msg.IsEmpty() && id != 0)
+ LangString(id, msg);
+ if (!msg.IsEmpty())
+ s += msg;
+ else
+ {
+ s += "Error #";
+ s.Add_UInt32(opRes);
+ }
+
+ if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword)
+ {
+ // s += " : ";
+ // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED);
+ s += " : ";
+ AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
+ }
+ s += " : ";
+ 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);
+ }
+ }
+
+ #ifndef _SFX
+ if (_isFolder)
+ NumFolders++;
+ else
+ NumFiles++;
+ ProgressDialog->Sync.Set_NumFilesCur(NumFiles);
+ #endif
+
+ 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, bool /* testMode */)
+{
+ #ifndef _SFX
+ RINOK(ProgressDialog->Sync.CheckStop());
+ ProgressDialog->Sync.Set_TitleFileName(name);
+ #endif
+ _currentArchivePath = name;
+ return S_OK;
+}
+
+HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path)
+{
+ _currentFilePath = path;
+ #ifndef _SFX
+ ProgressDialog->Sync.Set_FilePath(path);
+ #endif
+ return S_OK;
+}
+
+#ifndef _SFX
+
+HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path)
+{
+ #ifndef _SFX
+ if (NeedAddFile)
+ NumFiles++;
+ NeedAddFile = true;
+ ProgressDialog->Sync.Set_NumFilesCur(NumFiles);
+ #endif
+ return SetCurrentFilePath2(path);
+}
+
+#endif
+
+UString HResultToMessage(HRESULT errorCode);
+
+static const UInt32 k_ErrorFlagsIds[] =
+{
+ IDS_EXTRACT_MSG_IS_NOT_ARC,
+ IDS_EXTRACT_MSG_HEADERS_ERROR,
+ IDS_EXTRACT_MSG_HEADERS_ERROR,
+ IDS_OPEN_MSG_UNAVAILABLE_START,
+ IDS_OPEN_MSG_UNCONFIRMED_START,
+ IDS_EXTRACT_MSG_UEXPECTED_END,
+ IDS_EXTRACT_MSG_DATA_AFTER_END,
+ IDS_EXTRACT_MSG_UNSUPPORTED_METHOD,
+ IDS_OPEN_MSG_UNSUPPORTED_FEATURE,
+ IDS_EXTRACT_MSG_DATA_ERROR,
+ 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);
+ if ((errorFlags & f) == 0)
+ continue;
+ UInt32 id = k_ErrorFlagsIds[i];
+ UString m = LangString(id);
+ if (m.IsEmpty())
+ continue;
+ if (f == kpv_ErrorFlags_EncryptedHeadersError)
+ {
+ m += " : ";
+ AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
+ }
+ if (!s.IsEmpty())
+ s.Add_LF();
+ s += m;
+ errorFlags &= ~f;
+ }
+
+ if (errorFlags != 0)
+ {
+ char sz[16];
+ sz[0] = '0';
+ sz[1] = 'x';
+ ConvertUInt32ToHex(errorFlags, sz + 2);
+ if (!s.IsEmpty())
+ s.Add_LF();
+ s += sz;
+ }
+
+ return s;
+}
+
+static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)
+{
+ UInt32 errorFlags = er.GetErrorFlags();
+ UInt32 warningFlags = er.GetWarningFlags();
+
+ if (errorFlags != 0)
+ AddNewLineString(s, GetOpenArcErrorMessage(errorFlags));
+
+ if (!er.ErrorMessage.IsEmpty())
+ AddNewLineString(s, er.ErrorMessage);
+
+ if (warningFlags != 0)
+ {
+ s += GetNameOfProperty(kpidWarningFlags, L"Warnings");
+ s += ":";
+ s.Add_LF();
+ AddNewLineString(s, GetOpenArcErrorMessage(warningFlags));
+ }
+
+ if (!er.WarningMessage.IsEmpty())
+ {
+ s += GetNameOfProperty(kpidWarning, L"Warning");
+ s += ": ";
+ s += er.WarningMessage;
+ s.Add_LF();
+ }
+}
+
+static UString GetBracedType(const wchar_t *type)
+{
+ UString s ('[');
+ s += type;
+ s += ']';
+ return s;
+}
+
+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 (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0)
+ continue;
+
+ if (s.IsEmpty())
+ {
+ s += name;
+ s.Add_LF();
+ }
+
+ if (level != 0)
+ {
+ AddNewLineString(s, arc.Path);
+ }
+
+ ErrorInfo_Print(s, er);
+
+ 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))));
+ }
+ }
+ }
+
+ if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK)
+ {
+ 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);
+ }
+
+ 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())
+ {
+ NumArchiveErrors++;
+ AddError_Message(s);
+ _needWriteArchivePath = false;
+ }
+
+ 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)
+ return result;
+ NumArchiveErrors++;
+ if (result == E_ABORT || result == ERROR_DISK_FULL)
+ return result;
+
+ Add_ArchiveName_Error();
+ if (!_currentFilePath.IsEmpty())
+ MessageError(_currentFilePath);
+ MessageError(NError::MyFormatMessage(result));
+ return S_OK;
+}
+
+#ifndef _NO_CRYPTO
+
+HRESULT CExtractCallbackImp::SetPassword(const UString &password)
+{
+ PasswordIsDefined = true;
+ Password = password;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)
+{
+ PasswordWasAsked = true;
+ if (!PasswordIsDefined)
+ {
+ CPasswordDialog dialog;
+ #ifndef _SFX
+ bool showPassword = NExtract::Read_ShowPassword();
+ dialog.ShowPassword = showPassword;
+ #endif
+ ProgressDialog->WaitCreating();
+ if (dialog.Create(*ProgressDialog) != IDOK)
+ return E_ABORT;
+ Password = dialog.Password;
+ PasswordIsDefined = true;
+ #ifndef _SFX
+ if (dialog.ShowPassword != showPassword)
+ NExtract::Save_ShowPassword(dialog.ShowPassword);
+ #endif
+ }
+ return StringToBstr(Password, password);
+}
+
+#endif
+
+#ifndef _SFX
+
+STDMETHODIMP CExtractCallbackImp::AskWrite(
+ const wchar_t *srcPath, Int32 srcIsFolder,
+ const FILETIME *srcTime, const UInt64 *srcSize,
+ const wchar_t *destPath,
+ BSTR *destPathResult,
+ Int32 *writeAnswer)
+{
+ UString destPathResultTemp = destPath;
+
+ // RINOK(StringToBstr(destPath, destPathResult));
+
+ *destPathResult = 0;
+ *writeAnswer = BoolToInt(false);
+
+ FString destPathSys = us2fs(destPath);
+ bool srcIsFolderSpec = IntToBool(srcIsFolder);
+ CFileInfo destFileInfo;
+
+ if (destFileInfo.Find(destPathSys))
+ {
+ if (srcIsFolderSpec)
+ {
+ if (!destFileInfo.IsDir())
+ {
+ RINOK(MessageError("can not replace file with folder with same name", destPathSys));
+ return E_ABORT;
+ }
+ *writeAnswer = BoolToInt(false);
+ return S_OK;
+ }
+
+ if (destFileInfo.IsDir())
+ {
+ RINOK(MessageError("can not replace folder with file with same name", destPathSys));
+ *writeAnswer = BoolToInt(false);
+ return S_OK;
+ }
+
+ switch (OverwriteMode)
+ {
+ case NExtract::NOverwriteMode::kSkip:
+ return S_OK;
+ case NExtract::NOverwriteMode::kAsk:
+ {
+ Int32 overwriteResult;
+ UString destPathSpec = destPath;
+ int slashPos = destPathSpec.ReverseFind_PathSepar();
+ destPathSpec.DeleteFrom(slashPos + 1);
+ destPathSpec += fs2us(destFileInfo.Name);
+
+ RINOK(AskOverwrite(
+ destPathSpec,
+ &destFileInfo.MTime, &destFileInfo.Size,
+ srcPath,
+ srcTime, srcSize,
+ &overwriteResult));
+
+ switch (overwriteResult)
+ {
+ case NOverwriteAnswer::kCancel: return E_ABORT;
+ case NOverwriteAnswer::kNo: return S_OK;
+ case NOverwriteAnswer::kNoToAll: OverwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK;
+ case NOverwriteAnswer::kYes: break;
+ case NOverwriteAnswer::kYesToAll: OverwriteMode = NExtract::NOverwriteMode::kOverwrite; break;
+ case NOverwriteAnswer::kAutoRename: OverwriteMode = NExtract::NOverwriteMode::kRename; break;
+ default:
+ return E_FAIL;
+ }
+ }
+ }
+
+ if (OverwriteMode == NExtract::NOverwriteMode::kRename)
+ {
+ if (!AutoRenamePath(destPathSys))
+ {
+ RINOK(MessageError("can not create name for file", destPathSys));
+ return E_ABORT;
+ }
+ destPathResultTemp = fs2us(destPathSys);
+ }
+ else
+ if (!NDir::DeleteFileAlways(destPathSys))
+ {
+ RINOK(MessageError("can not delete output file", destPathSys));
+ return E_ABORT;
+ }
+ }
+ *writeAnswer = BoolToInt(true);
+ return StringToBstr(destPathResultTemp, destPathResult);
+}
+
+
+STDMETHODIMP CExtractCallbackImp::UseExtractToStream(Int32 *res)
+{
+ *res = BoolToInt(StreamMode);
+ return S_OK;
+}
+
+static HRESULT GetTime(IGetProp *getProp, PROPID propID, FILETIME &ft, bool &ftDefined)
+{
+ ftDefined = false;
+ NCOM::CPropVariant prop;
+ RINOK(getProp->GetProp(propID, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ ft = prop.filetime;
+ ftDefined = (ft.dwHighDateTime != 0 || ft.dwLowDateTime != 0);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+
+static HRESULT GetItemBoolProp(IGetProp *getProp, PROPID propID, bool &result)
+{
+ NCOM::CPropVariant prop;
+ result = false;
+ RINOK(getProp->GetProp(propID, &prop));
+ if (prop.vt == VT_BOOL)
+ result = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+
+STDMETHODIMP CExtractCallbackImp::GetStream7(const wchar_t *name,
+ Int32 isDir,
+ ISequentialOutStream **outStream, Int32 askExtractMode,
+ IGetProp *getProp)
+{
+ COM_TRY_BEGIN
+ *outStream = 0;
+ _newVirtFileWasAdded = false;
+ _hashStreamWasUsed = false;
+ _needUpdateStat = false;
+
+ if (_hashStream)
+ _hashStreamSpec->ReleaseStream();
+
+ GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream);
+
+ if (!ProcessAltStreams && _isAltStream)
+ return S_OK;
+
+ _filePath = name;
+ _isFolder = IntToBool(isDir);
+ _curSize = 0;
+ _curSizeDefined = false;
+
+ UInt64 size = 0;
+ bool sizeDefined;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(getProp->GetProp(kpidSize, &prop));
+ sizeDefined = ConvertPropVariantToUInt64(prop, size);
+ }
+
+ if (sizeDefined)
+ {
+ _curSize = size;
+ _curSizeDefined = true;
+ }
+
+ if (askExtractMode != NArchive::NExtract::NAskMode::kExtract &&
+ askExtractMode != NArchive::NExtract::NAskMode::kTest)
+ return S_OK;
+
+ _needUpdateStat = true;
+
+ CMyComPtr<ISequentialOutStream> outStreamLoc;
+
+ if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract)
+ {
+ CVirtFile &file = VirtFileSystemSpec->AddNewFile();
+ _newVirtFileWasAdded = true;
+ file.Name = name;
+ file.IsDir = IntToBool(isDir);
+ file.IsAltStream = _isAltStream;
+ file.Size = 0;
+
+ RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTimeDefined));
+ RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATimeDefined));
+ RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTimeDefined));
+
+ NCOM::CPropVariant prop;
+ RINOK(getProp->GetProp(kpidAttrib, &prop));
+ if (prop.vt == VT_UI4)
+ {
+ file.Attrib = prop.ulVal;
+ file.AttribDefined = true;
+ }
+ // else if (isDir) file.Attrib = FILE_ATTRIBUTE_DIRECTORY;
+
+ file.ExpectedSize = 0;
+ if (sizeDefined)
+ file.ExpectedSize = size;
+ outStreamLoc = VirtFileSystem;
+ }
+
+ if (_hashStream)
+ {
+ {
+ _hashStreamSpec->SetStream(outStreamLoc);
+ outStreamLoc = _hashStream;
+ _hashStreamSpec->Init(true);
+ _hashStreamWasUsed = true;
+ }
+ }
+
+ if (outStreamLoc)
+ *outStream = outStreamLoc.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)
+{
+ COM_TRY_BEGIN
+ _needUpdateStat = (
+ askExtractMode == NArchive::NExtract::NAskMode::kExtract ||
+ askExtractMode == NArchive::NExtract::NAskMode::kTest);
+
+ /*
+ _extractMode = false;
+ switch (askExtractMode)
+ {
+ case NArchive::NExtract::NAskMode::kExtract:
+ if (_testMode)
+ askExtractMode = NArchive::NExtract::NAskMode::kTest;
+ else
+ _extractMode = true;
+ break;
+ };
+ */
+ return SetCurrentFilePath2(_filePath);
+ COM_TRY_END
+}
+
+STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypted)
+{
+ COM_TRY_BEGIN
+ if (VirtFileSystem && _newVirtFileWasAdded)
+ {
+ // FIXME: probably we must request file size from VirtFileSystem
+ // _curSize = VirtFileSystem->GetLastFileSize()
+ // _curSizeDefined = true;
+ RINOK(VirtFileSystemSpec->CloseMemFile());
+ }
+ if (_hashStream && _hashStreamWasUsed)
+ {
+ _hashStreamSpec->_hash->Final(_isFolder, _isAltStream, _filePath);
+ _curSize = _hashStreamSpec->GetSize();
+ _curSizeDefined = true;
+ _hashStreamSpec->ReleaseStream();
+ _hashStreamWasUsed = false;
+ }
+ else if (_hashCalc && _needUpdateStat)
+ {
+ _hashCalc->SetSize(_curSize);
+ _hashCalc->Final(_isFolder, _isAltStream, _filePath);
+ }
+ return SetOperationResult(opRes, encrypted);
+ COM_TRY_END
+}
+
+
+static const size_t k_SizeT_MAX = (size_t)((size_t)0 - 1);
+
+static const UInt32 kBlockSize = ((UInt32)1 << 31);
+
+STDMETHODIMP CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ if (!_fileMode)
+ {
+ CVirtFile &file = Files.Back();
+ size_t rem = file.Data.Size() - (size_t)file.Size;
+ bool useMem = true;
+ if (rem < size)
+ {
+ UInt64 b = 0;
+ if (file.Data.Size() == 0)
+ b = file.ExpectedSize;
+ UInt64 a = file.Size + size;
+ if (b < a)
+ b = a;
+ a = (UInt64)file.Data.Size() * 2;
+ if (b < a)
+ b = a;
+ useMem = false;
+ if (b <= k_SizeT_MAX && b <= MaxTotalAllocSize)
+ useMem = file.Data.ReAlloc_KeepData((size_t)b, (size_t)file.Size);
+ }
+ if (useMem)
+ {
+ memcpy(file.Data + file.Size, data, size);
+ file.Size += size;
+ if (processedSize)
+ *processedSize = (UInt32)size;
+ return S_OK;
+ }
+ _fileMode = true;
+ }
+ RINOK(FlushToDisk(false));
+ return _outFileStream->Write(data, size, processedSize);
+}
+
+HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
+{
+ if (!_outFileStream)
+ {
+ _outFileStreamSpec = new COutFileStream;
+ _outFileStream = _outFileStreamSpec;
+ }
+ while (_numFlushed < Files.Size())
+ {
+ const CVirtFile &file = Files[_numFlushed];
+ const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name));
+ if (!_fileIsOpen)
+ {
+ if (!_outFileStreamSpec->Create(path, false))
+ {
+ _outFileStream.Release();
+ return E_FAIL;
+ // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath));
+ }
+ _fileIsOpen = true;
+ RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size));
+ }
+ if (_numFlushed == Files.Size() - 1 && !closeLast)
+ break;
+ if (file.CTimeDefined ||
+ file.ATimeDefined ||
+ file.MTimeDefined)
+ _outFileStreamSpec->SetTime(
+ file.CTimeDefined ? &file.CTime : NULL,
+ file.ATimeDefined ? &file.ATime : NULL,
+ file.MTimeDefined ? &file.MTime : NULL);
+ _outFileStreamSpec->Close();
+ _numFlushed++;
+ _fileIsOpen = false;
+ if (file.AttribDefined)
+ NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib);
+ }
+ return S_OK;
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.h
new file mode 100644
index 0000000000..a6d5ae3a43
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.h
@@ -0,0 +1,328 @@
+// ExtractCallback.h
+
+#ifndef __EXTRACT_CALLBACK_H
+#define __EXTRACT_CALLBACK_H
+
+#include "../../../../C/Alloc.h"
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/StringConvert.h"
+
+#ifndef _SFX
+#include "../Agent/IFolderArchive.h"
+#endif
+
+#include "../Common/ArchiveExtractCallback.h"
+#include "../Common/ArchiveOpenCallback.h"
+
+#ifndef _NO_CRYPTO
+#include "../../IPassword.h"
+#endif
+
+#ifndef _SFX
+#include "IFolder.h"
+#endif
+
+#include "ProgressDialog2.h"
+
+#ifdef LANG
+#include "LangUtils.h"
+#endif
+
+#ifndef _SFX
+
+class CGrowBuf
+{
+ Byte *_items;
+ size_t _size;
+
+ CLASS_NO_COPY(CGrowBuf);
+
+public:
+ bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
+ {
+ void *buf = MyAlloc(newSize);
+ if (!buf)
+ return false;
+ if (keepSize != 0)
+ memcpy(buf, _items, keepSize);
+ MyFree(_items);
+ _items = (Byte *)buf;
+ _size = newSize;
+ return true;
+ }
+
+ CGrowBuf(): _items(0), _size(0) {}
+ ~CGrowBuf() { MyFree(_items); }
+
+ operator Byte *() { return _items; }
+ operator const Byte *() const { return _items; }
+ size_t Size() const { return _size; }
+};
+
+struct CVirtFile
+{
+ CGrowBuf Data;
+
+ UInt64 Size; // real size
+ UInt64 ExpectedSize; // the size from props request. 0 if unknown
+
+ UString Name;
+
+ bool CTimeDefined;
+ bool ATimeDefined;
+ bool MTimeDefined;
+ bool AttribDefined;
+
+ bool IsDir;
+ bool IsAltStream;
+
+ DWORD Attrib;
+
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+
+ CVirtFile():
+ CTimeDefined(false),
+ ATimeDefined(false),
+ MTimeDefined(false),
+ AttribDefined(false),
+ IsDir(false),
+ IsAltStream(false) {}
+};
+
+class CVirtFileSystem:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ UInt64 _totalAllocSize;
+
+ size_t _pos;
+ unsigned _numFlushed;
+ bool _fileIsOpen;
+ bool _fileMode;
+ COutFileStream *_outFileStreamSpec;
+ CMyComPtr<ISequentialOutStream> _outFileStream;
+public:
+ CObjectVector<CVirtFile> Files;
+ UInt64 MaxTotalAllocSize;
+ FString DirPrefix;
+
+ CVirtFile &AddNewFile()
+ {
+ if (!Files.IsEmpty())
+ {
+ MaxTotalAllocSize -= Files.Back().Data.Size();
+ }
+ return Files.AddNew();
+ }
+ HRESULT CloseMemFile()
+ {
+ if (_fileMode)
+ {
+ return FlushToDisk(true);
+ }
+ CVirtFile &file = Files.Back();
+ if (file.Data.Size() != file.Size)
+ {
+ file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size);
+ }
+ return S_OK;
+ }
+
+ bool IsStreamInMem() const
+ {
+ if (_fileMode)
+ return false;
+ 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) {}
+
+ void Init()
+ {
+ _totalAllocSize = 0;
+ _fileMode = false;
+ _pos = 0;
+ _numFlushed = 0;
+ _fileIsOpen = false;
+ }
+
+ HRESULT CloseFile(const FString &path);
+ HRESULT FlushToDisk(bool closeLast);
+ size_t GetPos() const { return _pos; }
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+#endif
+
+class CExtractCallbackImp:
+ public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback
+ public IOpenCallbackUI,
+ public IFolderArchiveExtractCallback2,
+ #ifndef _SFX
+ public IFolderOperationsExtractCallback,
+ public IFolderExtractToStreamCallback,
+ public ICompressProgressInfo,
+ #endif
+ #ifndef _NO_CRYPTO
+ public ICryptoGetTextPassword,
+ #endif
+ 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)
+ MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
+ #endif
+ #ifndef _NO_CRYPTO
+ MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ INTERFACE_IProgress(;)
+ INTERFACE_IOpenCallbackUI(;)
+ INTERFACE_IFolderArchiveExtractCallback(;)
+ INTERFACE_IFolderArchiveExtractCallback2(;)
+ // STDMETHOD(SetTotalFiles)(UInt64 total);
+ // STDMETHOD(SetCompletedFiles)(const UInt64 *value);
+
+ INTERFACE_IExtractCallbackUI(;)
+
+ #ifndef _SFX
+ // IFolderOperationsExtractCallback
+ STDMETHOD(AskWrite)(
+ const wchar_t *srcPath,
+ Int32 srcIsFolder,
+ const FILETIME *srcTime,
+ const UInt64 *srcSize,
+ const wchar_t *destPathRequest,
+ BSTR *destPathResult,
+ Int32 *writeAnswer);
+ STDMETHOD(ShowMessage)(const wchar_t *message);
+ STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath);
+ STDMETHOD(SetNumFiles)(UInt64 numFiles);
+ INTERFACE_IFolderExtractToStreamCallback(;)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+ #endif
+
+ // ICryptoGetTextPassword
+ #ifndef _NO_CRYPTO
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+ #endif
+
+private:
+ UString _currentArchivePath;
+ bool _needWriteArchivePath;
+
+ UString _currentFilePath;
+ bool _isFolder;
+
+ bool _isAltStream;
+ UInt64 _curSize;
+ bool _curSizeDefined;
+ UString _filePath;
+ // bool _extractMode;
+ // bool _testMode;
+ bool _newVirtFileWasAdded;
+ bool _needUpdateStat;
+
+
+ HRESULT SetCurrentFilePath2(const wchar_t *filePath);
+ void AddError_Message(LPCWSTR message);
+
+ #ifndef _SFX
+ bool _hashStreamWasUsed;
+ COutStreamWithHash *_hashStreamSpec;
+ CMyComPtr<ISequentialOutStream> _hashStream;
+ IHashCalc *_hashCalc; // it's for stat in Test operation
+ #endif
+
+public:
+
+ #ifndef _SFX
+ CVirtFileSystem *VirtFileSystemSpec;
+ CMyComPtr<ISequentialOutStream> VirtFileSystem;
+ #endif
+
+ bool ProcessAltStreams;
+
+ bool StreamMode;
+
+ CProgressDialog *ProgressDialog;
+ #ifndef _SFX
+ UInt64 NumFolders;
+ UInt64 NumFiles;
+ bool NeedAddFile;
+ #endif
+ UInt32 NumArchiveErrors;
+ bool ThereAreMessageErrors;
+ NExtract::NOverwriteMode::EEnum OverwriteMode;
+
+ #ifndef _NO_CRYPTO
+ bool PasswordIsDefined;
+ bool PasswordWasAsked;
+ UString Password;
+ #endif
+
+
+ UString _lang_Extracting;
+ UString _lang_Testing;
+ UString _lang_Skipping;
+ UString _lang_Empty;
+
+ bool _totalFilesDefined;
+ bool _totalBytesDefined;
+ bool MultiArcMode;
+
+ CExtractCallbackImp():
+ #ifndef _NO_CRYPTO
+ PasswordIsDefined(false),
+ PasswordWasAsked(false),
+ #endif
+ OverwriteMode(NExtract::NOverwriteMode::kAsk),
+ StreamMode(false),
+ ProcessAltStreams(true),
+
+ _totalFilesDefined(false),
+ _totalBytesDefined(false),
+ MultiArcMode(false)
+
+ #ifndef _SFX
+ , _hashCalc(NULL)
+ #endif
+ {}
+
+ ~CExtractCallbackImp();
+ void Init();
+
+ #ifndef _SFX
+ void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
+
+ void SetHashMethods(IHashCalc *hash)
+ {
+ if (!hash)
+ return;
+ _hashStreamSpec = new COutStreamWithHash;
+ _hashStream = _hashStreamSpec;
+ _hashStreamSpec->_hash = hash;
+ }
+ #endif
+
+ bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.cpp
new file mode 100644
index 0000000000..4f7ef74e55
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.cpp
@@ -0,0 +1,28 @@
+// FormatUtils.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+
+#include "FormatUtils.h"
+
+#include "LangUtils.h"
+
+UString NumberToString(UInt64 number)
+{
+ wchar_t numberString[32];
+ ConvertUInt64ToString(number, numberString);
+ return numberString;
+}
+
+UString MyFormatNew(const UString &format, const UString &argument)
+{
+ UString result = format;
+ result.Replace(L"{0}", argument);
+ return result;
+}
+
+UString MyFormatNew(UINT resourceID, const UString &argument)
+{
+ return MyFormatNew(LangString(resourceID), argument);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.h
new file mode 100644
index 0000000000..f221cd2334
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.h
@@ -0,0 +1,14 @@
+// FormatUtils.h
+
+#ifndef __FORMAT_UTILS_H
+#define __FORMAT_UTILS_H
+
+#include "../../../Common/MyTypes.h"
+#include "../../../Common/MyString.h"
+
+UString NumberToString(UInt64 number);
+
+UString MyFormatNew(const UString &format, const UString &argument);
+UString MyFormatNew(UINT resourceID, const UString &argument);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/LangUtils.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/LangUtils.h
new file mode 100644
index 0000000000..c694423902
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/LangUtils.h
@@ -0,0 +1,40 @@
+// LangUtils.h
+
+#ifndef __LANG_UTILS_H
+#define __LANG_UTILS_H
+
+#include "../../../Windows/ResourceString.h"
+
+#ifdef LANG
+
+extern UString g_LangID;
+
+struct CIDLangPair
+{
+ UInt32 ControlID;
+ UInt32 LangID;
+};
+
+void ReloadLang();
+void LoadLangOneTime();
+FString GetLangDirPrefix();
+
+void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID);
+void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems);
+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
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/MyWindowsNew.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/MyWindowsNew.h
new file mode 100644
index 0000000000..c0fe8439b9
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/MyWindowsNew.h
@@ -0,0 +1,76 @@
+// MyWindowsNew.h
+
+#ifndef __MY_WINDOWS_NEW_H
+#define __MY_WINDOWS_NEW_H
+
+#ifdef _MSC_VER
+
+#include <ShObjIdl.h>
+
+#ifndef __ITaskbarList3_INTERFACE_DEFINED__
+#define __ITaskbarList3_INTERFACE_DEFINED__
+
+typedef enum THUMBBUTTONFLAGS
+{
+ THBF_ENABLED = 0,
+ THBF_DISABLED = 0x1,
+ THBF_DISMISSONCLICK = 0x2,
+ THBF_NOBACKGROUND = 0x4,
+ THBF_HIDDEN = 0x8,
+ THBF_NONINTERACTIVE = 0x10
+} THUMBBUTTONFLAGS;
+
+typedef enum THUMBBUTTONMASK
+{
+ THB_BITMAP = 0x1,
+ THB_ICON = 0x2,
+ THB_TOOLTIP = 0x4,
+ THB_FLAGS = 0x8
+} THUMBBUTTONMASK;
+
+// #include <pshpack8.h>
+
+typedef struct THUMBBUTTON
+{
+ THUMBBUTTONMASK dwMask;
+ UINT iId;
+ UINT iBitmap;
+ HICON hIcon;
+ WCHAR szTip[260];
+ THUMBBUTTONFLAGS dwFlags;
+} THUMBBUTTON;
+
+typedef struct THUMBBUTTON *LPTHUMBBUTTON;
+
+typedef enum TBPFLAG
+{
+ TBPF_NOPROGRESS = 0,
+ TBPF_INDETERMINATE = 0x1,
+ TBPF_NORMAL = 0x2,
+ TBPF_ERROR = 0x4,
+ TBPF_PAUSED = 0x8
+} TBPFLAG;
+
+DEFINE_GUID(IID_ITaskbarList3, 0xEA1AFB91, 0x9E28, 0x4B86, 0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF);
+
+struct ITaskbarList3: public ITaskbarList2
+{
+ STDMETHOD(SetProgressValue)(HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) = 0;
+ STDMETHOD(SetProgressState)(HWND hwnd, TBPFLAG tbpFlags) = 0;
+ STDMETHOD(RegisterTab)(HWND hwndTab, HWND hwndMDI) = 0;
+ STDMETHOD(UnregisterTab)(HWND hwndTab) = 0;
+ STDMETHOD(SetTabOrder)(HWND hwndTab, HWND hwndInsertBefore) = 0;
+ STDMETHOD(SetTabActive)(HWND hwndTab, HWND hwndMDI, DWORD dwReserved) = 0;
+ STDMETHOD(ThumbBarAddButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0;
+ STDMETHOD(ThumbBarUpdateButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0;
+ STDMETHOD(ThumbBarSetImageList)(HWND hwnd, HIMAGELIST himl) = 0;
+ STDMETHOD(SetOverlayIcon)(HWND hwnd, HICON hIcon, LPCWSTR pszDescription) = 0;
+ STDMETHOD(SetThumbnailTooltip)(HWND hwnd, LPCWSTR pszTip) = 0;
+ STDMETHOD(SetThumbnailClip)(HWND hwnd, RECT *prcClip) = 0;
+};
+
+#endif
+
+#endif
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
new file mode 100644
index 0000000000..3f0180decc
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
@@ -0,0 +1,122 @@
+// OverwriteDialog.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/PropVariantConv.h"
+#include "../../../Windows/ResourceString.h"
+
+#include "../../../Windows/Control/Static.h"
+
+#include "FormatUtils.h"
+#include "LangUtils.h"
+#include "OverwriteDialog.h"
+
+#include "PropertyNameRes.h"
+
+using namespace NWindows;
+
+#ifdef LANG
+static const UInt32 kLangIDs[] =
+{
+ IDT_OVERWRITE_HEADER,
+ IDT_OVERWRITE_QUESTION_BEGIN,
+ IDT_OVERWRITE_QUESTION_END,
+ IDB_YES_TO_ALL,
+ IDB_NO_TO_ALL,
+ IDB_AUTO_RENAME
+};
+#endif
+
+static const unsigned kCurrentFileNameSizeLimit = 82;
+static const unsigned kCurrentFileNameSizeLimit2 = 30;
+
+void COverwriteDialog::ReduceString(UString &s)
+{
+ unsigned size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2;
+ if (s.Len() > size)
+ {
+ s.Delete(size / 2, s.Len() - size);
+ s.Insert(size / 2, L" ... ");
+ }
+ if (!s.IsEmpty() && s.Back() == ' ')
+ {
+ // s += (wchar_t)(0x2423);
+ s.InsertAtFront(L'\"');
+ s += L'\"';
+ }
+}
+
+void COverwriteDialog::SetFileInfoControl(int textID, int iconID,
+ const NOverwriteDialog::CFileInfo &fileInfo)
+{
+ UString sizeString;
+ if (fileInfo.SizeIsDefined)
+ sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));
+
+ const UString &fileName = fileInfo.Name;
+ int slashPos = fileName.ReverseFind_PathSepar();
+ UString s1 = fileName.Left(slashPos + 1);
+ UString s2 = fileName.Ptr(slashPos + 1);
+
+ ReduceString(s1);
+ ReduceString(s2);
+
+ UString s = s1;
+ s.Add_LF();
+ s += s2;
+ s.Add_LF();
+ s += sizeString;
+ s.Add_LF();
+
+ if (fileInfo.TimeIsDefined)
+ {
+ AddLangString(s, IDS_PROP_MTIME);
+ s += ": ";
+ char t[32];
+ ConvertUtcFileTimeToString(fileInfo.Time, t);
+ s += t;
+ }
+
+ NControl::CDialogChildControl control;
+ control.Init(*this, textID);
+ control.SetText(s);
+
+ SHFILEINFO shellFileInfo;
+ if (::SHGetFileInfo(
+ GetSystemString(fileInfo.Name), FILE_ATTRIBUTE_NORMAL, &shellFileInfo,
+ sizeof(shellFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_LARGEICON))
+ {
+ NControl::CStatic staticContol;
+ staticContol.Attach(GetItem(iconID));
+ staticContol.SetIcon(shellFileInfo.hIcon);
+ }
+}
+
+bool COverwriteDialog::OnInit()
+{
+ #ifdef LANG
+ LangSetWindowText(*this, IDD_OVERWRITE);
+ LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
+ #endif
+ SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo);
+ SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo);
+ NormalizePosition();
+ return CModalDialog::OnInit();
+}
+
+bool COverwriteDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ switch (buttonID)
+ {
+ case IDYES:
+ case IDNO:
+ case IDB_YES_TO_ALL:
+ case IDB_NO_TO_ALL:
+ case IDB_AUTO_RENAME:
+ End(buttonID);
+ return true;
+ }
+ return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.h
new file mode 100644
index 0000000000..4564a472d8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.h
@@ -0,0 +1,69 @@
+// OverwriteDialog.h
+
+#ifndef __OVERWRITE_DIALOG_H
+#define __OVERWRITE_DIALOG_H
+
+#include "../../../Windows/Control/Dialog.h"
+
+#include "DialogSize.h"
+#include "OverwriteDialogRes.h"
+
+namespace NOverwriteDialog
+{
+ struct CFileInfo
+ {
+ bool SizeIsDefined;
+ bool TimeIsDefined;
+ UInt64 Size;
+ FILETIME Time;
+ UString Name;
+
+ void SetTime(const FILETIME *t)
+ {
+ if (t == 0)
+ TimeIsDefined = false;
+ else
+ {
+ TimeIsDefined = true;
+ Time = *t;
+ }
+ }
+ void SetSize(const UInt64 *size)
+ {
+ if (size == 0)
+ SizeIsDefined = false;
+ else
+ {
+ SizeIsDefined = true;
+ Size = *size;
+ }
+ }
+ };
+}
+
+class COverwriteDialog: public NWindows::NControl::CModalDialog
+{
+ bool _isBig;
+
+ void SetFileInfoControl(int textID, int iconID, const NOverwriteDialog::CFileInfo &fileInfo);
+ virtual bool OnInit();
+ bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ void ReduceString(UString &s);
+
+public:
+ INT_PTR Create(HWND parent = 0)
+ {
+ BIG_DIALOG_SIZE(280, 200);
+ #ifdef UNDER_CE
+ _isBig = isBig;
+ #else
+ _isBig = true;
+ #endif
+ return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent);
+ }
+
+ NOverwriteDialog::CFileInfo OldFileInfo;
+ NOverwriteDialog::CFileInfo NewFileInfo;
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.rc b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.rc
new file mode 100644
index 0000000000..80f48b007a
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.rc
@@ -0,0 +1,91 @@
+#include "OverwriteDialogRes.h"
+#include "../../GuiCommon.rc"
+
+#define xc 280
+#define yc 200
+
+#undef iconSize
+#define iconSize 24
+
+#undef x
+#undef fx
+#undef fy
+#define x (m + iconSize + m)
+#define fx (xc - iconSize - m)
+#define fy 50
+
+#define bSizeBig 104
+#undef bx1
+#define bx1 (xs - m - bSizeBig)
+
+IDD_OVERWRITE DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+CAPTION "Confirm File Replace"
+BEGIN
+ LTEXT "Destination folder already contains processed file.", IDT_OVERWRITE_HEADER, m, 7, xc, 8
+ LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8
+
+ ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize
+ LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX
+
+ LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 98, xc, 8
+
+ ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize
+ LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX
+
+ PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys
+ PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys
+ PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bSizeBig, bys
+ PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys
+ PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys
+ PUSHBUTTON "&Cancel", IDCANCEL, xs - m - bxs, by1, bxs, bys
+END
+
+
+#ifdef UNDER_CE
+
+#undef m
+#undef xc
+#undef yc
+
+#define m 4
+#define xc 152
+#define yc 144
+
+#undef fy
+#define fy 40
+
+#undef bxs
+#define bxs 48
+
+#undef bx1
+
+#define bx1 (xs - m - bxs)
+
+IDD_OVERWRITE_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+CAPTION "Confirm File Replace"
+BEGIN
+ LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, m, xc, 8
+
+ ICON "", IDI_OVERWRITE_OLD_FILE, m, 20, iconSize, iconSize
+ LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 20, fx, fy, SS_NOPREFIX
+
+ LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 60, xc, 8
+
+ ICON "", IDI_OVERWRITE_NEW_FILE, m, 72, iconSize, iconSize
+ LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 72, fx, fy, SS_NOPREFIX
+
+ PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys
+ PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys
+ PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bxs, bys
+ PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys
+ PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys
+ PUSHBUTTON "&Cancel", IDCANCEL, bx1, by1, bxs, bys
+END
+
+#endif
+
+
+STRINGTABLE
+BEGIN
+ IDS_FILE_SIZE "{0} bytes"
+END
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialogRes.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
new file mode 100644
index 0000000000..28bc0d0aa9
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
@@ -0,0 +1,17 @@
+#define IDD_OVERWRITE 3500
+#define IDD_OVERWRITE_2 13500
+
+#define IDT_OVERWRITE_HEADER 3501
+#define IDT_OVERWRITE_QUESTION_BEGIN 3502
+#define IDT_OVERWRITE_QUESTION_END 3503
+#define IDS_FILE_SIZE 3504
+
+#define IDB_AUTO_RENAME 3505
+#define IDB_YES_TO_ALL 440
+#define IDB_NO_TO_ALL 441
+
+#define IDI_OVERWRITE_OLD_FILE 100
+#define IDI_OVERWRITE_NEW_FILE 101
+
+#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102
+#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 103
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.cpp
new file mode 100644
index 0000000000..95e83fe452
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.cpp
@@ -0,0 +1,58 @@
+// PasswordDialog.cpp
+
+#include "StdAfx.h"
+
+#include "PasswordDialog.h"
+
+#ifdef LANG
+#include "LangUtils.h"
+#endif
+
+#ifdef LANG
+static const UInt32 kLangIDs[] =
+{
+ IDT_PASSWORD_ENTER,
+ IDX_PASSWORD_SHOW
+};
+#endif
+
+void CPasswordDialog::ReadControls()
+{
+ _passwordEdit.GetText(Password);
+ ShowPassword = IsButtonCheckedBool(IDX_PASSWORD_SHOW);
+}
+
+void CPasswordDialog::SetTextSpec()
+{
+ _passwordEdit.SetPasswordChar(ShowPassword ? 0: TEXT('*'));
+ _passwordEdit.SetText(Password);
+}
+
+bool CPasswordDialog::OnInit()
+{
+ #ifdef LANG
+ LangSetWindowText(*this, IDD_PASSWORD);
+ LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
+ #endif
+ _passwordEdit.Attach(GetItem(IDE_PASSWORD_PASSWORD));
+ CheckButton(IDX_PASSWORD_SHOW, ShowPassword);
+ SetTextSpec();
+ return CModalDialog::OnInit();
+}
+
+bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ if (buttonID == IDX_PASSWORD_SHOW)
+ {
+ ReadControls();
+ SetTextSpec();
+ return true;
+ }
+ return CDialog::OnButtonClicked(buttonID, buttonHWND);
+}
+
+void CPasswordDialog::OnOK()
+{
+ ReadControls();
+ CModalDialog::OnOK();
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.h
new file mode 100644
index 0000000000..b756a1c4d4
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.h
@@ -0,0 +1,28 @@
+// PasswordDialog.h
+
+#ifndef __PASSWORD_DIALOG_H
+#define __PASSWORD_DIALOG_H
+
+#include "../../../Windows/Control/Dialog.h"
+#include "../../../Windows/Control/Edit.h"
+
+#include "PasswordDialogRes.h"
+
+class CPasswordDialog: public NWindows::NControl::CModalDialog
+{
+ NWindows::NControl::CEdit _passwordEdit;
+
+ virtual void OnOK();
+ virtual bool OnInit();
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ void SetTextSpec();
+ void ReadControls();
+public:
+ UString Password;
+ bool ShowPassword;
+
+ CPasswordDialog(): ShowPassword(false) {}
+ INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_PASSWORD, parentWindow); }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.rc b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.rc
new file mode 100644
index 0000000000..51dd5bc473
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.rc
@@ -0,0 +1,14 @@
+#include "PasswordDialogRes.h"
+#include "../../GuiCommon.rc"
+
+#define xc 140
+#define yc 72
+
+IDD_PASSWORD DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+CAPTION "Enter password"
+BEGIN
+ LTEXT "&Enter password:", IDT_PASSWORD_ENTER, m, m, xc, 8
+ EDITTEXT IDE_PASSWORD_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "&Show password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10
+ OK_CANCEL
+END
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialogRes.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialogRes.h
new file mode 100644
index 0000000000..f9300d6bc2
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialogRes.h
@@ -0,0 +1,5 @@
+#define IDD_PASSWORD 3800
+#define IDT_PASSWORD_ENTER 3801
+#define IDX_PASSWORD_SHOW 3803
+
+#define IDE_PASSWORD_PASSWORD 120
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.cpp
new file mode 100644
index 0000000000..9b61369372
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.cpp
@@ -0,0 +1,197 @@
+// ProgressDialog.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+
+#include "resource.h"
+
+#include "ProgressDialog.h"
+
+using namespace NWindows;
+
+extern HINSTANCE g_hInstance;
+
+static const UINT_PTR kTimerID = 3;
+static const UINT kTimerElapse = 100;
+
+#ifdef LANG
+#include "LangUtils.h"
+#endif
+
+HRESULT CProgressSync::ProcessStopAndPause()
+{
+ for (;;)
+ {
+ if (GetStopped())
+ return E_ABORT;
+ if (!GetPaused())
+ break;
+ ::Sleep(100);
+ }
+ return S_OK;
+}
+
+#ifndef _SFX
+CProgressDialog::~CProgressDialog()
+{
+ AddToTitle(L"");
+}
+void CProgressDialog::AddToTitle(LPCWSTR s)
+{
+ if (MainWindow != 0)
+ MySetWindowText(MainWindow, UString(s) + MainTitle);
+}
+#endif
+
+
+bool CProgressDialog::OnInit()
+{
+ _range = (UInt64)(Int64)-1;
+ _prevPercentValue = -1;
+
+ _wasCreated = true;
+ _dialogCreatedEvent.Set();
+
+ #ifdef LANG
+ LangSetDlgItems(*this, NULL, 0);
+ #endif
+
+ m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));
+
+ if (IconID >= 0)
+ {
+ HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));
+ SetIcon(ICON_BIG, icon);
+ }
+
+ _timer = SetTimer(kTimerID, kTimerElapse);
+ SetText(_title);
+ CheckNeedClose();
+ return CModalDialog::OnInit();
+}
+
+void CProgressDialog::OnCancel() { Sync.SetStopped(true); }
+void CProgressDialog::OnOK() { }
+
+void CProgressDialog::SetRange(UInt64 range)
+{
+ _range = range;
+ _peviousPos = (UInt64)(Int64)-1;
+ _converter.Init(range);
+ m_ProgressBar.SetRange32(0 , _converter.Count(range)); // Test it for 100%
+}
+
+void CProgressDialog::SetPos(UInt64 pos)
+{
+ bool redraw = true;
+ if (pos < _range && pos > _peviousPos)
+ {
+ UInt64 posDelta = pos - _peviousPos;
+ if (posDelta < (_range >> 10))
+ redraw = false;
+ }
+ if (redraw)
+ {
+ m_ProgressBar.SetPos(_converter.Count(pos)); // Test it for 100%
+ _peviousPos = pos;
+ }
+}
+
+bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
+{
+ if (Sync.GetPaused())
+ return true;
+
+ CheckNeedClose();
+
+ UInt64 total, completed;
+ Sync.GetProgress(total, completed);
+ if (total != _range)
+ SetRange(total);
+ SetPos(completed);
+
+ if (total == 0)
+ total = 1;
+
+ int percentValue = (int)(completed * 100 / total);
+ if (percentValue != _prevPercentValue)
+ {
+ wchar_t s[64];
+ ConvertUInt64ToString(percentValue, s);
+ UString title = s;
+ title += "% ";
+ SetText(title + _title);
+ #ifndef _SFX
+ AddToTitle(title + MainAddTitle);
+ #endif
+ _prevPercentValue = percentValue;
+ }
+ return true;
+}
+
+bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case kCloseMessage:
+ {
+ KillTimer(_timer);
+ _timer = 0;
+ if (_inCancelMessageBox)
+ {
+ _externalCloseMessageWasReceived = true;
+ break;
+ }
+ return OnExternalCloseMessage();
+ }
+ /*
+ case WM_SETTEXT:
+ {
+ if (_timer == 0)
+ return true;
+ }
+ */
+ }
+ return CModalDialog::OnMessage(message, wParam, lParam);
+}
+
+bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ switch (buttonID)
+ {
+ case IDCANCEL:
+ {
+ bool paused = Sync.GetPaused();
+ Sync.SetPaused(true);
+ _inCancelMessageBox = true;
+ // Mozilla Customization - Removed redundant cancel button from dialog.
+ int res = ::MessageBoxW(*this, L"Are you sure you want to cancel?", _title, MB_YESNO);
+ _inCancelMessageBox = false;
+ Sync.SetPaused(paused);
+ if (res == IDCANCEL || res == IDNO)
+ {
+ if (_externalCloseMessageWasReceived)
+ OnExternalCloseMessage();
+ return true;
+ }
+ break;
+ }
+ }
+ return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
+}
+
+void CProgressDialog::CheckNeedClose()
+{
+ if (_needClose)
+ {
+ PostMsg(kCloseMessage);
+ _needClose = false;
+ }
+}
+
+bool CProgressDialog::OnExternalCloseMessage()
+{
+ End(0);
+ return true;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.h
new file mode 100644
index 0000000000..2a9d26d117
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.h
@@ -0,0 +1,170 @@
+// ProgressDialog.h
+
+#ifndef __PROGRESS_DIALOG_H
+#define __PROGRESS_DIALOG_H
+
+#include "../../../Windows/Synchronization.h"
+#include "../../../Windows/Thread.h"
+
+#include "../../../Windows/Control/Dialog.h"
+#include "../../../Windows/Control/ProgressBar.h"
+
+#include "ProgressDialogRes.h"
+
+class CProgressSync
+{
+ NWindows::NSynchronization::CCriticalSection _cs;
+ bool _stopped;
+ bool _paused;
+ UInt64 _total;
+ UInt64 _completed;
+public:
+ CProgressSync(): _stopped(false), _paused(false), _total(1), _completed(0) {}
+
+ HRESULT ProcessStopAndPause();
+ bool GetStopped()
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ return _stopped;
+ }
+ void SetStopped(bool value)
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ _stopped = value;
+ }
+ bool GetPaused()
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ return _paused;
+ }
+ void SetPaused(bool value)
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ _paused = value;
+ }
+ void SetProgress(UInt64 total, UInt64 completed)
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ _total = total;
+ _completed = completed;
+ }
+ void SetPos(UInt64 completed)
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ _completed = completed;
+ }
+ void GetProgress(UInt64 &total, UInt64 &completed)
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ total = _total;
+ completed = _completed;
+ }
+};
+
+class CU64ToI32Converter
+{
+ UInt64 _numShiftBits;
+public:
+ void Init(UInt64 range)
+ {
+ // Windows CE doesn't like big number here.
+ for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++)
+ range >>= 1;
+ }
+ int Count(UInt64 value) { return int(value >> _numShiftBits); }
+};
+
+class CProgressDialog: public NWindows::NControl::CModalDialog
+{
+private:
+ UINT_PTR _timer;
+
+ UString _title;
+ CU64ToI32Converter _converter;
+ UInt64 _peviousPos;
+ UInt64 _range;
+ NWindows::NControl::CProgressBar m_ProgressBar;
+
+ int _prevPercentValue;
+
+ bool _wasCreated;
+ bool _needClose;
+ bool _inCancelMessageBox;
+ bool _externalCloseMessageWasReceived;
+
+ bool OnTimer(WPARAM timerID, LPARAM callback);
+ void SetRange(UInt64 range);
+ void SetPos(UInt64 pos);
+ virtual bool OnInit();
+ virtual void OnCancel();
+ virtual void OnOK();
+ NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;
+ #ifndef _SFX
+ void AddToTitle(LPCWSTR string);
+ #endif
+ bool OnButtonClicked(int buttonID, HWND buttonHWND);
+
+ void WaitCreating() { _dialogCreatedEvent.Lock(); }
+ void CheckNeedClose();
+ bool OnExternalCloseMessage();
+public:
+ CProgressSync Sync;
+ int IconID;
+
+ #ifndef _SFX
+ HWND MainWindow;
+ UString MainTitle;
+ UString MainAddTitle;
+ ~CProgressDialog();
+ #endif
+
+ CProgressDialog(): _timer(0)
+ #ifndef _SFX
+ ,MainWindow(0)
+ #endif
+ {
+ IconID = -1;
+ _wasCreated = false;
+ _needClose = false;
+ _inCancelMessageBox = false;
+ _externalCloseMessageWasReceived = false;
+
+ if (_dialogCreatedEvent.Create() != S_OK)
+ throw 1334987;
+ }
+
+ INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0)
+ {
+ _title = title;
+ INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent);
+ thread.Wait();
+ return res;
+ }
+
+ enum
+ {
+ kCloseMessage = WM_APP + 1
+ };
+
+ virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
+
+ void ProcessWasFinished()
+ {
+ WaitCreating();
+ if (_wasCreated)
+ PostMsg(kCloseMessage);
+ else
+ _needClose = true;
+ };
+};
+
+
+class CProgressCloser
+{
+ CProgressDialog *_p;
+public:
+ CProgressCloser(CProgressDialog &p) : _p(&p) {}
+ ~CProgressCloser() { _p->ProcessWasFinished(); }
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.rc b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.rc
new file mode 100644
index 0000000000..5af370f74e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.rc
@@ -0,0 +1,12 @@
+#include "ProgressDialogRes.h"
+#include "../../GuiCommon.rc"
+
+#define xc 172
+#define yc 44
+
+IDD_PROGRESS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+CAPTION "Progress"
+BEGIN
+ PUSHBUTTON "Cancel", IDCANCEL, bx, by, bxs, bys
+ CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, m, xc, 14
+END
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
new file mode 100644
index 0000000000..bdb2be3f17
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -0,0 +1,1337 @@
+// ProgressDialog2.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/Control/Static.h"
+#include "../../../Windows/ErrorMsg.h"
+
+#include "../GUI/ExtractRes.h"
+
+#include "LangUtils.h"
+
+#include "DialogSize.h"
+#include "ProgressDialog2.h"
+#include "ProgressDialog2Res.h"
+
+using namespace NWindows;
+
+extern HINSTANCE g_hInstance;
+
+static const UINT_PTR kTimerID = 3;
+
+static const UINT kCloseMessage = WM_APP + 1;
+// we can't use WM_USER, since WM_USER can be used by standard Windows procedure for Dialog
+
+static const UINT kTimerElapse =
+ #ifdef UNDER_CE
+ 500
+ #else
+ 200
+ #endif
+ ;
+
+static const UINT kCreateDelay =
+ #ifdef UNDER_CE
+ 2500
+ #else
+ 500
+ #endif
+ ;
+
+static const DWORD kPauseSleepTime = 100;
+
+#ifdef LANG
+
+static const UInt32 kLangIDs[] =
+{
+ IDT_PROGRESS_ELAPSED,
+ IDT_PROGRESS_REMAINING,
+ IDT_PROGRESS_TOTAL,
+ IDT_PROGRESS_SPEED,
+ IDT_PROGRESS_PROCESSED,
+ IDT_PROGRESS_RATIO,
+ IDT_PROGRESS_ERRORS,
+ IDB_PROGRESS_BACKGROUND,
+ IDB_PAUSE
+};
+
+static const UInt32 kLangIDs_Colon[] =
+{
+ IDT_PROGRESS_PACKED,
+ IDT_PROGRESS_FILES
+};
+
+#endif
+
+
+#define UNDEFINED_VAL ((UInt64)(Int64)-1)
+#define INIT_AS_UNDEFINED(v) v = UNDEFINED_VAL;
+#define IS_UNDEFINED_VAL(v) ((v) == UNDEFINED_VAL)
+#define IS_DEFINED_VAL(v) ((v) != UNDEFINED_VAL)
+
+CProgressSync::CProgressSync():
+ _stopped(false), _paused(false),
+ _bytesProgressMode(true),
+ _totalBytes(UNDEFINED_VAL), _completedBytes(0),
+ _totalFiles(UNDEFINED_VAL), _curFiles(0),
+ _inSize(UNDEFINED_VAL),
+ _outSize(UNDEFINED_VAL),
+ _isDir(false)
+ {}
+
+#define CHECK_STOP if (_stopped) return E_ABORT; if (!_paused) return S_OK;
+#define CRITICAL_LOCK NSynchronization::CCriticalSectionLock lock(_cs);
+
+bool CProgressSync::Get_Paused()
+{
+ CRITICAL_LOCK
+ return _paused;
+}
+
+HRESULT CProgressSync::CheckStop()
+{
+ for (;;)
+ {
+ {
+ CRITICAL_LOCK
+ CHECK_STOP
+ }
+ ::Sleep(kPauseSleepTime);
+ }
+}
+
+HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir)
+{
+ {
+ CRITICAL_LOCK
+ _totalFiles = numFiles;
+ _totalBytes = totalSize;
+ _filePath = fs2us(fileName);
+ _isDir = isDir;
+ // _completedBytes = 0;
+ CHECK_STOP
+ }
+ return CheckStop();
+}
+
+HRESULT CProgressSync::Set_NumFilesTotal(UInt64 val)
+{
+ {
+ CRITICAL_LOCK
+ _totalFiles = val;
+ CHECK_STOP
+ }
+ return CheckStop();
+}
+
+void CProgressSync::Set_NumBytesTotal(UInt64 val)
+{
+ CRITICAL_LOCK
+ _totalBytes = val;
+}
+
+void CProgressSync::Set_NumFilesCur(UInt64 val)
+{
+ CRITICAL_LOCK
+ _curFiles = val;
+}
+
+HRESULT CProgressSync::Set_NumBytesCur(const UInt64 *val)
+{
+ {
+ CRITICAL_LOCK
+ if (val)
+ _completedBytes = *val;
+ CHECK_STOP
+ }
+ return CheckStop();
+}
+
+HRESULT CProgressSync::Set_NumBytesCur(UInt64 val)
+{
+ {
+ CRITICAL_LOCK
+ _completedBytes = val;
+ CHECK_STOP
+ }
+ return CheckStop();
+}
+
+void CProgressSync::Set_Ratio(const UInt64 *inSize, const UInt64 *outSize)
+{
+ CRITICAL_LOCK
+ if (inSize)
+ _inSize = *inSize;
+ if (outSize)
+ _outSize = *outSize;
+}
+
+void CProgressSync::Set_TitleFileName(const UString &fileName)
+{
+ CRITICAL_LOCK
+ _titleFileName = fileName;
+}
+
+void CProgressSync::Set_Status(const UString &s)
+{
+ CRITICAL_LOCK
+ _status = s;
+}
+
+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
+ if (path)
+ _filePath = path;
+ else
+ _filePath.Empty();
+ _isDir = isDir;
+}
+
+
+void CProgressSync::AddError_Message(const wchar_t *message)
+{
+ CRITICAL_LOCK
+ Messages.Add(message);
+}
+
+void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t *name)
+{
+ UString s;
+ if (name && *name != 0)
+ s += name;
+ if (message && *message != 0)
+ {
+ if (!s.IsEmpty())
+ s.Add_LF();
+ s += message;
+ if (!s.IsEmpty() && s.Back() == L'\n')
+ s.DeleteBack();
+ }
+ AddError_Message(s);
+}
+
+void CProgressSync::AddError_Code_Name(DWORD systemError, const wchar_t *name)
+{
+ UString s = NError::MyFormatMessage(systemError);
+ if (systemError == 0)
+ s = "Error";
+ AddError_Message_Name(s, name);
+}
+
+CProgressDialog::CProgressDialog():
+ _timer(0),
+ CompressingMode(true),
+ MainWindow(0)
+{
+ _isDir = false;
+
+ _numMessages = 0;
+ IconID = -1;
+ MessagesDisplayed = false;
+ _wasCreated = false;
+ _needClose = false;
+ _inCancelMessageBox = false;
+ _externalCloseMessageWasReceived = false;
+
+ _numPostedMessages = 0;
+ _numAutoSizeMessages = 0;
+ _errorsWereDisplayed = false;
+ _waitCloseByCancelButton = false;
+ _cancelWasPressed = false;
+ ShowCompressionInfo = true;
+ WaitMode = false;
+ if (_dialogCreatedEvent.Create() != S_OK)
+ throw 1334987;
+ if (_createDialogEvent.Create() != S_OK)
+ throw 1334987;
+ #ifdef __ITaskbarList3_INTERFACE_DEFINED__
+ CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&_taskbarList);
+ if (_taskbarList)
+ _taskbarList->HrInit();
+ #endif
+}
+
+#ifndef _SFX
+
+CProgressDialog::~CProgressDialog()
+{
+ #ifdef __ITaskbarList3_INTERFACE_DEFINED__
+ SetTaskbarProgressState(TBPF_NOPROGRESS);
+ #endif
+ AddToTitle(L"");
+}
+void CProgressDialog::AddToTitle(LPCWSTR s)
+{
+ if (MainWindow != 0)
+ {
+ CWindow window(MainWindow);
+ window.SetText((UString)s + MainTitle);
+ }
+}
+
+#endif
+
+
+void CProgressDialog::SetTaskbarProgressState()
+{
+ #ifdef __ITaskbarList3_INTERFACE_DEFINED__
+ if (_taskbarList && _hwndForTaskbar)
+ {
+ TBPFLAG tbpFlags;
+ if (Sync.Get_Paused())
+ tbpFlags = TBPF_PAUSED;
+ else
+ tbpFlags = _errorsWereDisplayed ? TBPF_ERROR: TBPF_NORMAL;
+ SetTaskbarProgressState(tbpFlags);
+ }
+ #endif
+}
+
+static const unsigned kTitleFileNameSizeLimit = 36;
+static const unsigned kCurrentFileNameSizeLimit = 82;
+
+static void ReduceString(UString &s, unsigned size)
+{
+ if (s.Len() <= size)
+ return;
+ s.Delete(size / 2, s.Len() - size);
+ s.Insert(size / 2, L" ... ");
+}
+
+void CProgressDialog::EnableErrorsControls(bool enable)
+{
+ ShowItem_Bool(IDT_PROGRESS_ERRORS, enable);
+ ShowItem_Bool(IDT_PROGRESS_ERRORS_VAL, enable);
+ ShowItem_Bool(IDL_PROGRESS_MESSAGES, enable);
+}
+
+bool CProgressDialog::OnInit()
+{
+ _hwndForTaskbar = MainWindow;
+ if (!_hwndForTaskbar)
+ _hwndForTaskbar = GetParent();
+ if (!_hwndForTaskbar)
+ _hwndForTaskbar = *this;
+
+ INIT_AS_UNDEFINED(_progressBar_Range);
+ INIT_AS_UNDEFINED(_progressBar_Pos);
+
+ INIT_AS_UNDEFINED(_prevPercentValue);
+ INIT_AS_UNDEFINED(_prevElapsedSec);
+ INIT_AS_UNDEFINED(_prevRemainingSec);
+
+ INIT_AS_UNDEFINED(_prevSpeed);
+ _prevSpeed_MoveBits = 0;
+
+ _prevTime = ::GetTickCount();
+ _elapsedTime = 0;
+
+ INIT_AS_UNDEFINED(_totalBytes_Prev);
+ INIT_AS_UNDEFINED(_processed_Prev);
+ INIT_AS_UNDEFINED(_packed_Prev);
+ INIT_AS_UNDEFINED(_ratio_Prev);
+ _filesStr_Prev.Empty();
+
+ _foreground = true;
+
+ m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));
+ _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES));
+ _messageList.SetUnicodeFormat();
+
+ _wasCreated = true;
+ _dialogCreatedEvent.Set();
+
+ #ifdef LANG
+ LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
+ LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon));
+ #endif
+
+ CWindow window(GetItem(IDB_PROGRESS_BACKGROUND));
+ window.GetText(_background_String);
+ _backgrounded_String = _background_String;
+ _backgrounded_String.RemoveChar(L'&');
+
+ window = GetItem(IDB_PAUSE);
+ window.GetText(_pause_String);
+
+ LangString(IDS_PROGRESS_FOREGROUND, _foreground_String);
+ LangString(IDS_CONTINUE, _continue_String);
+ LangString(IDS_PROGRESS_PAUSED, _paused_String);
+
+ SetText(_title);
+ SetPauseText();
+ SetPriorityText();
+
+ _messageList.InsertColumn(0, L"", 30);
+ _messageList.InsertColumn(1, L"", 600);
+
+ _messageList.SetColumnWidthAuto(0);
+ _messageList.SetColumnWidthAuto(1);
+
+ EnableErrorsControls(false);
+
+ GetItemSizes(IDCANCEL, _buttonSizeX, _buttonSizeY);
+ _numReduceSymbols = kCurrentFileNameSizeLimit;
+ NormalizeSize(true);
+
+ if (!ShowCompressionInfo)
+ {
+ HideItem(IDT_PROGRESS_PACKED);
+ HideItem(IDT_PROGRESS_PACKED_VAL);
+ HideItem(IDT_PROGRESS_RATIO);
+ HideItem(IDT_PROGRESS_RATIO_VAL);
+ }
+
+ if (IconID >= 0)
+ {
+ HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));
+ // SetIcon(ICON_SMALL, icon);
+ SetIcon(ICON_BIG, icon);
+ }
+ _timer = SetTimer(kTimerID, kTimerElapse);
+ #ifdef UNDER_CE
+ Foreground();
+ #endif
+
+ CheckNeedClose();
+
+ SetTaskbarProgressState();
+
+ return CModalDialog::OnInit();
+}
+
+static const UINT kIDs[] =
+{
+ IDT_PROGRESS_ELAPSED, IDT_PROGRESS_ELAPSED_VAL,
+ IDT_PROGRESS_REMAINING, IDT_PROGRESS_REMAINING_VAL,
+ IDT_PROGRESS_FILES, IDT_PROGRESS_FILES_VAL,
+ IDT_PROGRESS_RATIO, IDT_PROGRESS_RATIO_VAL,
+ IDT_PROGRESS_ERRORS, IDT_PROGRESS_ERRORS_VAL,
+
+ IDT_PROGRESS_TOTAL, IDT_PROGRESS_TOTAL_VAL,
+ IDT_PROGRESS_SPEED, IDT_PROGRESS_SPEED_VAL,
+ IDT_PROGRESS_PROCESSED, IDT_PROGRESS_PROCESSED_VAL,
+ IDT_PROGRESS_PACKED, IDT_PROGRESS_PACKED_VAL
+};
+
+bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
+{
+ int sY;
+ int sStep;
+ int mx, my;
+ {
+ RECT r;
+ GetClientRectOfItem(IDT_PROGRESS_ELAPSED, r);
+ mx = r.left;
+ my = r.top;
+ sY = RECT_SIZE_Y(r);
+ GetClientRectOfItem(IDT_PROGRESS_REMAINING, r);
+ sStep = r.top - my;
+ }
+
+ InvalidateRect(NULL);
+
+ int xSizeClient = xSize - mx * 2;
+
+ {
+ int i;
+ for (i = 800; i > 40; i = i * 9 / 10)
+ if (Units_To_Pixels_X(i) <= xSizeClient)
+ break;
+ _numReduceSymbols = i / 4;
+ }
+
+ int yPos = ySize - my - _buttonSizeY;
+
+ ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_STATUS), xSize - mx * 2);
+ ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - mx * 2);
+ ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2);
+
+ int bSizeX = _buttonSizeX;
+ int mx2 = mx;
+ for (;; mx2--)
+ {
+ int bSize2 = bSizeX * 3 + mx2 * 2;
+ if (bSize2 <= xSizeClient)
+ break;
+ if (mx2 < 5)
+ {
+ bSizeX = (xSizeClient - mx2 * 2) / 3;
+ break;
+ }
+ }
+ if (bSizeX < 2)
+ bSizeX = 2;
+
+ {
+ RECT r;
+ GetClientRectOfItem(IDL_PROGRESS_MESSAGES, r);
+ int y = r.top;
+ int ySize2 = yPos - my - y;
+ const int kMinYSize = _buttonSizeY + _buttonSizeY * 3 / 4;
+ int xx = xSize - mx * 2;
+ if (ySize2 < kMinYSize)
+ {
+ ySize2 = kMinYSize;
+ if (xx > bSizeX * 2)
+ xx -= bSizeX;
+ }
+
+ _messageList.Move(mx, y, xx, ySize2);
+ }
+
+ {
+ int xPos = xSize - mx;
+ xPos -= bSizeX;
+ MoveItem(IDCANCEL, xPos, yPos, bSizeX, _buttonSizeY);
+ xPos -= (mx2 + bSizeX);
+ MoveItem(IDB_PAUSE, xPos, yPos, bSizeX, _buttonSizeY);
+ xPos -= (mx2 + bSizeX);
+ MoveItem(IDB_PROGRESS_BACKGROUND, xPos, yPos, bSizeX, _buttonSizeY);
+ }
+
+ int valueSize;
+ int labelSize;
+ int padSize;
+
+ labelSize = Units_To_Pixels_X(MY_PROGRESS_LABEL_UNITS_MIN);
+ valueSize = Units_To_Pixels_X(MY_PROGRESS_VAL_UNITS);
+ padSize = Units_To_Pixels_X(MY_PROGRESS_PAD_UNITS);
+ int requiredSize = (labelSize + valueSize) * 2 + padSize;
+
+ int gSize;
+ {
+ if (requiredSize < xSizeClient)
+ {
+ int incr = (xSizeClient - requiredSize) / 3;
+ labelSize += incr;
+ }
+ else
+ labelSize = (xSizeClient - valueSize * 2 - padSize) / 2;
+ if (labelSize < 0)
+ labelSize = 0;
+
+ gSize = labelSize + valueSize;
+ padSize = xSizeClient - gSize * 2;
+ }
+
+ labelSize = gSize - valueSize;
+
+ yPos = my;
+ for (int i = 0; i < ARRAY_SIZE(kIDs); i += 2)
+ {
+ int x = mx;
+ const int kNumColumn1Items = 5 * 2;
+ if (i >= kNumColumn1Items)
+ {
+ if (i == kNumColumn1Items)
+ yPos = my;
+ x = mx + gSize + padSize;
+ }
+ MoveItem(kIDs[i], x, yPos, labelSize, sY);
+ MoveItem(kIDs[i + 1], x + labelSize, yPos, valueSize, sY);
+ yPos += sStep;
+ }
+ return false;
+}
+
+void CProgressDialog::OnCancel() { Sync.Set_Stopped(true); }
+void CProgressDialog::OnOK() { }
+
+void CProgressDialog::SetProgressRange(UInt64 range)
+{
+ if (range == _progressBar_Range)
+ return;
+ _progressBar_Range = range;
+ INIT_AS_UNDEFINED(_progressBar_Pos);
+ _progressConv.Init(range);
+ m_ProgressBar.SetRange32(0, _progressConv.Count(range));
+}
+
+void CProgressDialog::SetProgressPos(UInt64 pos)
+{
+ if (pos >= _progressBar_Range ||
+ pos <= _progressBar_Pos ||
+ pos - _progressBar_Pos >= (_progressBar_Range >> 10))
+ {
+ m_ProgressBar.SetPos(_progressConv.Count(pos));
+ #ifdef __ITaskbarList3_INTERFACE_DEFINED__
+ if (_taskbarList && _hwndForTaskbar)
+ _taskbarList->SetProgressValue(_hwndForTaskbar, pos, _progressBar_Range);
+ #endif
+ _progressBar_Pos = pos;
+ }
+}
+
+#define UINT_TO_STR_2(val) { s[0] = (wchar_t)('0' + (val) / 10); s[1] = (wchar_t)('0' + (val) % 10); s += 2; }
+
+void GetTimeString(UInt64 timeValue, wchar_t *s)
+{
+ 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;
+}
+
+static void ConvertSizeToString(UInt64 v, wchar_t *s)
+{
+ Byte c = 0;
+ if (v >= ((UInt64)100000 << 20)) { v >>= 30; c = 'G'; }
+ else if (v >= ((UInt64)100000 << 10)) { v >>= 20; c = 'M'; }
+ else if (v >= ((UInt64)100000 << 0)) { v >>= 10; c = 'K'; }
+ ConvertUInt64ToString(v, s);
+ if (c != 0)
+ {
+ s += MyStringLen(s);
+ *s++ = ' ';
+ *s++ = c;
+ *s++ = 0;
+ }
+}
+
+void CProgressDialog::ShowSize(int id, UInt64 val, UInt64 &prev)
+{
+ if (val == prev)
+ return;
+ prev = val;
+ wchar_t s[40];
+ s[0] = 0;
+ if (IS_DEFINED_VAL(val))
+ ConvertSizeToString(val, s);
+ SetItemText(id, s);
+}
+
+static void GetChangedString(const UString &newStr, UString &prevStr, bool &hasChanged)
+{
+ hasChanged = !(prevStr == newStr);
+ if (hasChanged)
+ prevStr = newStr;
+}
+
+static unsigned GetPower32(UInt32 val)
+{
+ const unsigned kStart = 32;
+ UInt32 mask = ((UInt32)1 << (kStart - 1));
+ for (unsigned i = kStart;; i--)
+ {
+ if (i == 0 || (val & mask) != 0)
+ return i;
+ mask >>= 1;
+ }
+}
+
+static unsigned GetPower64(UInt64 val)
+{
+ UInt32 high = (UInt32)(val >> 32);
+ if (high == 0)
+ return GetPower32((UInt32)val);
+ return GetPower32(high) + 32;
+}
+
+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;
+}
+
+void CProgressDialog::UpdateStatInfo(bool showAll)
+{
+ UInt64 total, completed, totalFiles, completedFiles, inSize, outSize;
+ bool bytesProgressMode;
+
+ bool titleFileName_Changed;
+ bool curFilePath_Changed;
+ bool status_Changed;
+ unsigned numErrors;
+ {
+ NSynchronization::CCriticalSectionLock lock(Sync._cs);
+ total = Sync._totalBytes;
+ completed = Sync._completedBytes;
+ totalFiles = Sync._totalFiles;
+ completedFiles = Sync._curFiles;
+ inSize = Sync._inSize;
+ outSize = Sync._outSize;
+ bytesProgressMode = Sync._bytesProgressMode;
+
+ GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed);
+ GetChangedString(Sync._filePath, _filePath, curFilePath_Changed);
+ GetChangedString(Sync._status, _status, status_Changed);
+ if (_isDir != Sync._isDir)
+ {
+ curFilePath_Changed = true;
+ _isDir = Sync._isDir;
+ }
+ numErrors = Sync.Messages.Size();
+ }
+
+ UInt32 curTime = ::GetTickCount();
+
+ const UInt64 progressTotal = bytesProgressMode ? total : totalFiles;
+ const UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles;
+ {
+ if (IS_UNDEFINED_VAL(progressTotal))
+ {
+ // SetPos(0);
+ // SetRange(progressCompleted);
+ }
+ else
+ {
+ if (_progressBar_Pos != 0 || progressCompleted != 0 ||
+ (_progressBar_Range == 0 && progressTotal != 0))
+ {
+ SetProgressRange(progressTotal);
+ SetProgressPos(progressCompleted);
+ }
+ }
+ }
+
+ ShowSize(IDT_PROGRESS_TOTAL_VAL, total, _totalBytes_Prev);
+
+ _elapsedTime += (curTime - _prevTime);
+ _prevTime = curTime;
+ UInt64 elapsedSec = _elapsedTime / 1000;
+ bool elapsedChanged = false;
+ if (elapsedSec != _prevElapsedSec)
+ {
+ _prevElapsedSec = elapsedSec;
+ elapsedChanged = true;
+ wchar_t s[40];
+ GetTimeString(elapsedSec, s);
+ SetItemText(IDT_PROGRESS_ELAPSED_VAL, s);
+ }
+
+ bool needSetTitle = false;
+ if (elapsedChanged || showAll)
+ {
+ if (numErrors > _numPostedMessages)
+ {
+ UpdateMessagesDialog();
+ wchar_t s[32];
+ ConvertUInt64ToString(numErrors, s);
+ SetItemText(IDT_PROGRESS_ERRORS_VAL, s);
+ if (!_errorsWereDisplayed)
+ {
+ _errorsWereDisplayed = true;
+ EnableErrorsControls(true);
+ SetTaskbarProgressState();
+ }
+ }
+
+ if (progressCompleted != 0)
+ {
+ if (IS_UNDEFINED_VAL(progressTotal))
+ {
+ if (IS_DEFINED_VAL(_prevRemainingSec))
+ {
+ INIT_AS_UNDEFINED(_prevRemainingSec);
+ SetItemText(IDT_PROGRESS_REMAINING_VAL, L"");
+ }
+ }
+ else
+ {
+ UInt64 remainingTime = 0;
+ if (progressCompleted < progressTotal)
+ remainingTime = MyMultAndDiv(_elapsedTime, progressTotal - progressCompleted, progressCompleted);
+ UInt64 remainingSec = remainingTime / 1000;
+ if (remainingSec != _prevRemainingSec)
+ {
+ _prevRemainingSec = remainingSec;
+ wchar_t s[40];
+ GetTimeString(remainingSec, s);
+ SetItemText(IDT_PROGRESS_REMAINING_VAL, s);
+ }
+ }
+ {
+ UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime;
+ UInt64 v = (progressCompleted * 1000) / elapsedTime;
+ Byte c = 0;
+ unsigned moveBits = 0;
+ if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; }
+ else if (v >= ((UInt64)10000 << 0)) { moveBits = 10; c = 'K'; }
+ v >>= moveBits;
+ if (moveBits != _prevSpeed_MoveBits || v != _prevSpeed)
+ {
+ _prevSpeed_MoveBits = moveBits;
+ _prevSpeed = v;
+ wchar_t s[40];
+ ConvertUInt64ToString(v, s);
+ unsigned pos = MyStringLen(s);
+ s[pos++] = ' ';
+ if (moveBits != 0)
+ s[pos++] = c;
+ s[pos++] = 'B';
+ s[pos++] = '/';
+ s[pos++] = 's';
+ s[pos++] = 0;
+ SetItemText(IDT_PROGRESS_SPEED_VAL, s);
+ }
+ }
+ }
+
+ {
+ UInt64 percent = 0;
+ {
+ if (IS_DEFINED_VAL(progressTotal))
+ {
+ percent = progressCompleted * 100;
+ if (progressTotal != 0)
+ percent /= progressTotal;
+ }
+ }
+ if (percent != _prevPercentValue)
+ {
+ _prevPercentValue = percent;
+ needSetTitle = true;
+ }
+ }
+
+ {
+ wchar_t s[64];
+ ConvertUInt64ToString(completedFiles, s);
+ if (IS_DEFINED_VAL(totalFiles))
+ {
+ MyStringCat(s, L" / ");
+ ConvertUInt64ToString(totalFiles, s + MyStringLen(s));
+ }
+ if (_filesStr_Prev != s)
+ {
+ _filesStr_Prev = s;
+ SetItemText(IDT_PROGRESS_FILES_VAL, s);
+ }
+ }
+
+ const UInt64 packSize = CompressingMode ? outSize : inSize;
+ const UInt64 unpackSize = CompressingMode ? inSize : outSize;
+
+ if (IS_UNDEFINED_VAL(unpackSize) &&
+ IS_UNDEFINED_VAL(packSize))
+ {
+ ShowSize(IDT_PROGRESS_PROCESSED_VAL, completed, _processed_Prev);
+ ShowSize(IDT_PROGRESS_PACKED_VAL, UNDEFINED_VAL, _packed_Prev);
+ }
+ else
+ {
+ ShowSize(IDT_PROGRESS_PROCESSED_VAL, unpackSize, _processed_Prev);
+ ShowSize(IDT_PROGRESS_PACKED_VAL, packSize, _packed_Prev);
+
+ if (IS_DEFINED_VAL(packSize) &&
+ IS_DEFINED_VAL(unpackSize) &&
+ unpackSize != 0)
+ {
+ wchar_t s[32];
+ UInt64 ratio = packSize * 100 / unpackSize;
+ if (_ratio_Prev != ratio)
+ {
+ _ratio_Prev = ratio;
+ ConvertUInt64ToString(ratio, s);
+ MyStringCat(s, L"%");
+ SetItemText(IDT_PROGRESS_RATIO_VAL, s);
+ }
+ }
+ }
+ }
+
+ if (needSetTitle || titleFileName_Changed)
+ SetTitleText();
+
+ if (status_Changed)
+ {
+ UString s = _status;
+ ReduceString(s, _numReduceSymbols);
+ SetItemText(IDT_PROGRESS_STATUS, _status);
+ }
+
+ if (curFilePath_Changed)
+ {
+ UString s1, s2;
+ if (_isDir)
+ s1 = _filePath;
+ else
+ {
+ int slashPos = _filePath.ReverseFind_PathSepar();
+ if (slashPos >= 0)
+ {
+ s1.SetFrom(_filePath, slashPos + 1);
+ s2 = _filePath.Ptr(slashPos + 1);
+ }
+ else
+ s2 = _filePath;
+ }
+ ReduceString(s1, _numReduceSymbols);
+ ReduceString(s2, _numReduceSymbols);
+ s1.Add_LF();
+ s1 += s2;
+ SetItemText(IDT_PROGRESS_FILE_NAME, s1);
+ }
+}
+
+bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
+{
+ if (Sync.Get_Paused())
+ return true;
+ CheckNeedClose();
+ UpdateStatInfo(false);
+ return true;
+}
+
+struct CWaitCursor
+{
+ HCURSOR _waitCursor;
+ HCURSOR _oldCursor;
+ CWaitCursor()
+ {
+ _waitCursor = LoadCursor(NULL, IDC_WAIT);
+ if (_waitCursor != NULL)
+ _oldCursor = SetCursor(_waitCursor);
+ }
+ ~CWaitCursor()
+ {
+ if (_waitCursor != NULL)
+ SetCursor(_oldCursor);
+ }
+};
+
+INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, HWND wndParent)
+{
+ INT_PTR res = 0;
+ try
+ {
+ if (WaitMode)
+ {
+ CWaitCursor waitCursor;
+ HANDLE h[] = { thread, _createDialogEvent };
+
+ WRes res2 = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay);
+ if (res2 == WAIT_OBJECT_0 && !Sync.ThereIsMessage())
+ return 0;
+ }
+ _title = title;
+ BIG_DIALOG_SIZE(360, 192);
+ res = CModalDialog::Create(SIZED_DIALOG(IDD_PROGRESS), wndParent);
+ }
+ catch(...)
+ {
+ _wasCreated = true;
+ _dialogCreatedEvent.Set();
+ res = res;
+ }
+ thread.Wait();
+ if (!MessagesDisplayed)
+ MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR);
+ return res;
+}
+
+bool CProgressDialog::OnExternalCloseMessage()
+{
+ // it doesn't work if there is MessageBox.
+ #ifdef __ITaskbarList3_INTERFACE_DEFINED__
+ SetTaskbarProgressState(TBPF_NOPROGRESS);
+ #endif
+ // AddToTitle(L"Finished ");
+ // SetText(L"Finished2 ");
+
+ UpdateStatInfo(true);
+
+ SetItemText(IDCANCEL, LangString(IDS_CLOSE));
+ ::SendMessage(GetItem(IDCANCEL), BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));
+ HideItem(IDB_PROGRESS_BACKGROUND);
+ HideItem(IDB_PAUSE);
+
+ ProcessWasFinished_GuiVirt();
+
+ bool thereAreMessages;
+ CProgressFinalMessage fm;
+ {
+ NSynchronization::CCriticalSectionLock lock(Sync._cs);
+ thereAreMessages = !Sync.Messages.IsEmpty();
+ fm = Sync.FinalMessage;
+ }
+
+ if (!fm.ErrorMessage.Message.IsEmpty())
+ {
+ MessagesDisplayed = true;
+ if (fm.ErrorMessage.Title.IsEmpty())
+ fm.ErrorMessage.Title = "7-Zip";
+ MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR);
+ }
+ else if (!thereAreMessages)
+ {
+ MessagesDisplayed = true;
+
+ if (!fm.OkMessage.Message.IsEmpty())
+ {
+ if (fm.OkMessage.Title.IsEmpty())
+ fm.OkMessage.Title = "7-Zip";
+ MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK);
+ }
+ }
+
+ if (thereAreMessages && !_cancelWasPressed)
+ {
+ _waitCloseByCancelButton = true;
+ UpdateMessagesDialog();
+ return true;
+ }
+
+ End(0);
+ return true;
+}
+
+bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case kCloseMessage:
+ {
+ KillTimer(_timer);
+ _timer = 0;
+ if (_inCancelMessageBox)
+ {
+ _externalCloseMessageWasReceived = true;
+ break;
+ }
+ return OnExternalCloseMessage();
+ }
+ /*
+ case WM_SETTEXT:
+ {
+ if (_timer == 0)
+ return true;
+ break;
+ }
+ */
+ }
+ return CModalDialog::OnMessage(message, wParam, lParam);
+}
+
+void CProgressDialog::SetTitleText()
+{
+ UString s;
+ if (Sync.Get_Paused())
+ {
+ s += _paused_String;
+ s.Add_Space();
+ }
+ if (IS_DEFINED_VAL(_prevPercentValue))
+ {
+ char temp[32];
+ ConvertUInt64ToString(_prevPercentValue, temp);
+ s += temp;
+ s += '%';
+ }
+ if (!_foreground)
+ {
+ s.Add_Space();
+ s += _backgrounded_String;
+ }
+
+ s.Add_Space();
+ #ifndef _SFX
+ {
+ unsigned len = s.Len();
+ s += MainAddTitle;
+ AddToTitle(s);
+ s.DeleteFrom(len);
+ }
+ #endif
+
+ s += _title;
+ if (!_titleFileName.IsEmpty())
+ {
+ UString fileName = _titleFileName;
+ ReduceString(fileName, kTitleFileNameSizeLimit);
+ s.Add_Space();
+ s += fileName;
+ }
+ SetText(s);
+}
+
+void CProgressDialog::SetPauseText()
+{
+ SetItemText(IDB_PAUSE, Sync.Get_Paused() ? _continue_String : _pause_String);
+ SetTitleText();
+}
+
+void CProgressDialog::OnPauseButton()
+{
+ bool paused = !Sync.Get_Paused();
+ Sync.Set_Paused(paused);
+ UInt32 curTime = ::GetTickCount();
+ if (paused)
+ _elapsedTime += (curTime - _prevTime);
+ SetTaskbarProgressState();
+ _prevTime = curTime;
+ SetPauseText();
+}
+
+void CProgressDialog::SetPriorityText()
+{
+ SetItemText(IDB_PROGRESS_BACKGROUND, _foreground ?
+ _background_String :
+ _foreground_String);
+ SetTitleText();
+}
+
+void CProgressDialog::OnPriorityButton()
+{
+ _foreground = !_foreground;
+ #ifndef UNDER_CE
+ SetPriorityClass(GetCurrentProcess(), _foreground ? NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS);
+ #endif
+ SetPriorityText();
+}
+
+void CProgressDialog::AddMessageDirect(LPCWSTR message, bool needNumber)
+{
+ int itemIndex = _messageList.GetItemCount();
+ wchar_t sz[16];
+ sz[0] = 0;
+ if (needNumber)
+ ConvertUInt32ToString(_numMessages + 1, sz);
+ _messageList.InsertItem(itemIndex, sz);
+ _messageList.SetSubItem(itemIndex, 1, message);
+}
+
+void CProgressDialog::AddMessage(LPCWSTR message)
+{
+ UString s = message;
+ bool needNumber = true;
+ while (!s.IsEmpty())
+ {
+ int pos = s.Find(L'\n');
+ if (pos < 0)
+ break;
+ AddMessageDirect(s.Left(pos), needNumber);
+ needNumber = false;
+ s.DeleteFrontal(pos + 1);
+ }
+ AddMessageDirect(s, needNumber);
+ _numMessages++;
+}
+
+static unsigned GetNumDigits(UInt32 val)
+{
+ unsigned i;
+ for (i = 0; val >= 10; i++)
+ val /= 10;
+ return i;
+}
+
+void CProgressDialog::UpdateMessagesDialog()
+{
+ UStringVector messages;
+ {
+ NSynchronization::CCriticalSectionLock lock(Sync._cs);
+ unsigned num = Sync.Messages.Size();
+ if (num > _numPostedMessages)
+ {
+ messages.ClearAndReserve(num - _numPostedMessages);
+ for (unsigned i = _numPostedMessages; i < num; i++)
+ messages.AddInReserved(Sync.Messages[i]);
+ _numPostedMessages = num;
+ }
+ }
+ if (!messages.IsEmpty())
+ {
+ FOR_VECTOR (i, messages)
+ AddMessage(messages[i]);
+ if (_numAutoSizeMessages < 256 || GetNumDigits(_numPostedMessages) > GetNumDigits(_numAutoSizeMessages))
+ {
+ _messageList.SetColumnWidthAuto(0);
+ _messageList.SetColumnWidthAuto(1);
+ _numAutoSizeMessages = _numPostedMessages;
+ }
+ }
+}
+
+
+bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ switch (buttonID)
+ {
+ // case IDOK: // if IDCANCEL is not DEFPUSHBUTTON
+ case IDCANCEL:
+ {
+ if (_waitCloseByCancelButton)
+ {
+ MessagesDisplayed = true;
+ End(IDCLOSE);
+ break;
+ }
+
+ bool paused = Sync.Get_Paused();
+ if (!paused)
+ OnPauseButton();
+ _inCancelMessageBox = true;
+ int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL);
+ _inCancelMessageBox = false;
+ if (!paused)
+ OnPauseButton();
+ if (res == IDCANCEL || res == IDNO)
+ {
+ if (_externalCloseMessageWasReceived)
+ OnExternalCloseMessage();
+ return true;
+ }
+
+ _cancelWasPressed = true;
+ MessagesDisplayed = true;
+ break;
+ }
+
+ case IDB_PAUSE:
+ OnPauseButton();
+ return true;
+ case IDB_PROGRESS_BACKGROUND:
+ OnPriorityButton();
+ return true;
+ }
+ return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
+}
+
+void CProgressDialog::CheckNeedClose()
+{
+ if (_needClose)
+ {
+ PostMsg(kCloseMessage);
+ _needClose = false;
+ }
+}
+
+void CProgressDialog::ProcessWasFinished()
+{
+ // Set Window title here.
+ if (!WaitMode)
+ WaitCreating();
+
+ if (_wasCreated)
+ PostMsg(kCloseMessage);
+ else
+ _needClose = true;
+}
+
+
+static THREAD_FUNC_DECL MyThreadFunction(void *param)
+{
+ CProgressThreadVirt *p = (CProgressThreadVirt *)param;
+ try
+ {
+ p->Process();
+ p->ThreadFinishedOK = true;
+ }
+ catch (...) { p->Result = E_FAIL; }
+ return 0;
+}
+
+
+HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow)
+{
+ NWindows::CThread thread;
+ RINOK(thread.Create(MyThreadFunction, this));
+ CProgressDialog::Create(title, thread, parentWindow);
+ return S_OK;
+}
+
+static void AddMessageToString(UString &dest, const UString &src)
+{
+ if (!src.IsEmpty())
+ {
+ if (!dest.IsEmpty())
+ dest.Add_LF();
+ dest += src;
+ }
+}
+
+void CProgressThreadVirt::Process()
+{
+ CProgressCloser closer(*this);
+ UString m;
+ try { Result = ProcessVirt(); }
+ catch(const wchar_t *s) { m = s; }
+ catch(const UString &s) { m = s; }
+ catch(const char *s) { m = GetUnicodeString(s); }
+ catch(int v)
+ {
+ m = "Error #";
+ m.Add_UInt32(v);
+ }
+ catch(...) { m = "Error"; }
+ if (Result != E_ABORT)
+ {
+ if (m.IsEmpty() && Result != S_OK)
+ m = HResultToMessage(Result);
+ }
+ AddMessageToString(m, FinalMessage.ErrorMessage.Message);
+
+ {
+ FOR_VECTOR(i, ErrorPaths)
+ {
+ if (i >= 32)
+ break;
+ AddMessageToString(m, fs2us(ErrorPaths[i]));
+ }
+ }
+
+ CProgressSync &sync = Sync;
+ NSynchronization::CCriticalSectionLock lock(sync._cs);
+ if (m.IsEmpty())
+ {
+ if (!FinalMessage.OkMessage.Message.IsEmpty())
+ sync.FinalMessage.OkMessage = FinalMessage.OkMessage;
+ }
+ else
+ {
+ sync.FinalMessage.ErrorMessage.Message = m;
+ if (Result == S_OK)
+ Result = E_FAIL;
+ }
+}
+
+UString HResultToMessage(HRESULT errorCode)
+{
+ if (errorCode == E_OUTOFMEMORY)
+ return LangString(IDS_MEM_ERROR);
+ else
+ return NError::MyFormatMessage(errorCode);
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.h
new file mode 100644
index 0000000000..5e916e6f9f
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.h
@@ -0,0 +1,351 @@
+// ProgressDialog2.h
+
+#ifndef __PROGRESS_DIALOG_2_H
+#define __PROGRESS_DIALOG_2_H
+
+#include "../../../Common/MyCom.h"
+
+#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/Synchronization.h"
+#include "../../../Windows/Thread.h"
+
+#include "../../../Windows/Control/Dialog.h"
+#include "../../../Windows/Control/ListView.h"
+#include "../../../Windows/Control/ProgressBar.h"
+
+#include "MyWindowsNew.h"
+
+struct CProgressMessageBoxPair
+{
+ UString Title;
+ UString Message;
+};
+
+struct CProgressFinalMessage
+{
+ CProgressMessageBoxPair ErrorMessage;
+ CProgressMessageBoxPair OkMessage;
+
+ bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); }
+};
+
+class CProgressSync
+{
+ bool _stopped;
+ bool _paused;
+
+public:
+ bool _bytesProgressMode;
+ UInt64 _totalBytes;
+ UInt64 _completedBytes;
+ UInt64 _totalFiles;
+ UInt64 _curFiles;
+ UInt64 _inSize;
+ UInt64 _outSize;
+
+ UString _titleFileName;
+ UString _status;
+ UString _filePath;
+ bool _isDir;
+
+ UStringVector Messages;
+ CProgressFinalMessage FinalMessage;
+
+ NWindows::NSynchronization::CCriticalSection _cs;
+
+ CProgressSync();
+
+ bool Get_Stopped()
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ return _stopped;
+ }
+ void Set_Stopped(bool val)
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ _stopped = val;
+ }
+
+ bool Get_Paused();
+ void Set_Paused(bool val)
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ _paused = val;
+ }
+
+ void Set_BytesProgressMode(bool bytesProgressMode)
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
+ _bytesProgressMode = bytesProgressMode;
+ }
+
+ HRESULT CheckStop();
+ HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false);
+
+ HRESULT Set_NumFilesTotal(UInt64 val);
+ void Set_NumBytesTotal(UInt64 val);
+ void Set_NumFilesCur(UInt64 val);
+ HRESULT Set_NumBytesCur(const UInt64 *val);
+ HRESULT Set_NumBytesCur(UInt64 val);
+ void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize);
+
+ void Set_TitleFileName(const UString &fileName);
+ void Set_Status(const UString &s);
+ 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);
+ void AddError_Code_Name(DWORD systemError, const wchar_t *name);
+
+ bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); }
+};
+
+class CProgressDialog: public NWindows::NControl::CModalDialog
+{
+ UString _titleFileName;
+ UString _filePath;
+ UString _status;
+ bool _isDir;
+
+ UString _background_String;
+ UString _backgrounded_String;
+ UString _foreground_String;
+ UString _pause_String;
+ UString _continue_String;
+ UString _paused_String;
+
+ int _buttonSizeX;
+ int _buttonSizeY;
+
+ UINT_PTR _timer;
+
+ UString _title;
+
+ class CU64ToI32Converter
+ {
+ unsigned _numShiftBits;
+ UInt64 _range;
+ public:
+ CU64ToI32Converter(): _numShiftBits(0), _range(1) {}
+ void Init(UInt64 range)
+ {
+ _range = range;
+ // Windows CE doesn't like big number for ProgressBar.
+ for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++)
+ range >>= 1;
+ }
+ int Count(UInt64 val)
+ {
+ int res = (int)(val >> _numShiftBits);
+ if (val == _range)
+ res++;
+ return res;
+ }
+ };
+
+ CU64ToI32Converter _progressConv;
+ UInt64 _progressBar_Pos;
+ UInt64 _progressBar_Range;
+
+ NWindows::NControl::CProgressBar m_ProgressBar;
+ NWindows::NControl::CListView _messageList;
+
+ int _numMessages;
+
+ #ifdef __ITaskbarList3_INTERFACE_DEFINED__
+ CMyComPtr<ITaskbarList3> _taskbarList;
+ #endif
+ HWND _hwndForTaskbar;
+
+ UInt32 _prevTime;
+ UInt64 _elapsedTime;
+
+ UInt64 _prevPercentValue;
+ UInt64 _prevElapsedSec;
+ UInt64 _prevRemainingSec;
+
+ UInt64 _totalBytes_Prev;
+ UInt64 _processed_Prev;
+ UInt64 _packed_Prev;
+ UInt64 _ratio_Prev;
+ UString _filesStr_Prev;
+
+ unsigned _prevSpeed_MoveBits;
+ UInt64 _prevSpeed;
+
+ bool _foreground;
+
+ unsigned _numReduceSymbols;
+
+ bool _wasCreated;
+ bool _needClose;
+
+ unsigned _numPostedMessages;
+ UInt32 _numAutoSizeMessages;
+
+ bool _errorsWereDisplayed;
+
+ bool _waitCloseByCancelButton;
+ bool _cancelWasPressed;
+
+ bool _inCancelMessageBox;
+ bool _externalCloseMessageWasReceived;
+
+
+ #ifdef __ITaskbarList3_INTERFACE_DEFINED__
+ void SetTaskbarProgressState(TBPFLAG tbpFlags)
+ {
+ if (_taskbarList && _hwndForTaskbar)
+ _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags);
+ }
+ #endif
+ void SetTaskbarProgressState();
+
+ void UpdateStatInfo(bool showAll);
+ bool OnTimer(WPARAM timerID, LPARAM callback);
+ void SetProgressRange(UInt64 range);
+ void SetProgressPos(UInt64 pos);
+ virtual bool OnInit();
+ virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
+ virtual void OnCancel();
+ virtual void OnOK();
+ NWindows::NSynchronization::CManualResetEvent _createDialogEvent;
+ NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;
+ #ifndef _SFX
+ void AddToTitle(LPCWSTR string);
+ #endif
+
+ void SetPauseText();
+ void SetPriorityText();
+ void OnPauseButton();
+ void OnPriorityButton();
+ bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
+
+ void SetTitleText();
+ void ShowSize(int id, UInt64 val, UInt64 &prev);
+
+ void UpdateMessagesDialog();
+
+ void AddMessageDirect(LPCWSTR message, bool needNumber);
+ void AddMessage(LPCWSTR message);
+
+ bool OnExternalCloseMessage();
+ void EnableErrorsControls(bool enable);
+
+ void ShowAfterMessages(HWND wndParent);
+
+ void CheckNeedClose();
+public:
+ CProgressSync Sync;
+ bool CompressingMode;
+ bool WaitMode;
+ bool ShowCompressionInfo;
+ bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages.
+ int IconID;
+
+ HWND MainWindow;
+ #ifndef _SFX
+ UString MainTitle;
+ UString MainAddTitle;
+ ~CProgressDialog();
+ #endif
+
+ CProgressDialog();
+ void WaitCreating()
+ {
+ _createDialogEvent.Set();
+ _dialogCreatedEvent.Lock();
+ }
+
+ INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0);
+
+
+ /* how it works:
+ 1) the working thread calls ProcessWasFinished()
+ that sends kCloseMessage message to CProgressDialog (GUI) thread
+ 2) CProgressDialog (GUI) thread receives kCloseMessage message and
+ calls ProcessWasFinished_GuiVirt();
+ So we can implement ProcessWasFinished_GuiVirt() and show special
+ results window in GUI thread with CProgressDialog as parent window
+ */
+
+ void ProcessWasFinished();
+ virtual void ProcessWasFinished_GuiVirt() {}
+};
+
+
+class CProgressCloser
+{
+ CProgressDialog *_p;
+public:
+ CProgressCloser(CProgressDialog &p) : _p(&p) {}
+ ~CProgressCloser() { _p->ProcessWasFinished(); }
+};
+
+
+class CProgressThreadVirt: public CProgressDialog
+{
+protected:
+ FStringVector ErrorPaths;
+ CProgressFinalMessage FinalMessage;
+
+ // error if any of HRESULT, ErrorMessage, ErrorPath
+ virtual HRESULT ProcessVirt() = 0;
+public:
+ HRESULT Result;
+ bool ThreadFinishedOK; // if there is no fatal exception
+
+ void Process();
+ void AddErrorPath(const FString &path) { ErrorPaths.Add(path); }
+
+ HRESULT Create(const UString &title, HWND parentWindow = 0);
+ CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}
+
+ CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; }
+};
+
+UString HResultToMessage(HRESULT errorCode);
+
+/*
+how it works:
+
+client code inherits CProgressThreadVirt and calls
+CProgressThreadVirt::Create()
+{
+ it creates new thread that calls CProgressThreadVirt::Process();
+ it creates modal progress dialog window with ProgressDialog.Create()
+}
+
+CProgressThreadVirt::Process()
+{
+ {
+ ProcessVirt(); // virtual function that must implement real work
+ }
+ if (exceptions) or FinalMessage.ErrorMessage.Message
+ {
+ set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message
+ }
+ else if (FinalMessage.OkMessage.Message)
+ {
+ set message to ProgressDialog.Sync.FinalMessage.OkMessage
+ }
+
+ PostMsg(kCloseMessage);
+}
+
+
+CProgressDialog::OnExternalCloseMessage()
+{
+ if (ProgressDialog.Sync.FinalMessage)
+ {
+ WorkWasFinishedVirt();
+ Show (ProgressDialog.Sync.FinalMessage)
+ MessagesDisplayed = true;
+ }
+}
+
+*/
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.rc
new file mode 100644
index 0000000000..535a008178
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.rc
@@ -0,0 +1,40 @@
+#include "ProgressDialog2Res.h"
+#include "../../GuiCommon.rc"
+
+#undef DIALOG_ID
+#define DIALOG_ID IDD_PROGRESS
+#define xc 360
+#define k 11
+#define z1s 16
+
+#include "ProgressDialog2a.rc"
+
+#ifdef UNDER_CE
+
+#include "../../GuiCommon.rc"
+
+
+#undef DIALOG_ID
+#undef m
+#undef k
+#undef z1s
+
+#define DIALOG_ID IDD_PROGRESS_2
+#define m 4
+#define k 8
+#define z1s 12
+
+#define xc 280
+
+#include "ProgressDialog2a.rc"
+
+#endif
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_PROGRESS_PAUSED "Paused"
+ IDS_PROGRESS_FOREGROUND "&Foreground"
+ IDS_CONTINUE "&Continue"
+ IDS_PROGRESS_ASK_CANCEL "Are you sure you want to cancel?"
+ IDS_CLOSE "&Close"
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2Res.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2Res.h
new file mode 100644
index 0000000000..54f02f0308
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2Res.h
@@ -0,0 +1,48 @@
+#define IDD_PROGRESS 97
+#define IDD_PROGRESS_2 10097
+
+#define IDS_CLOSE 408
+#define IDS_CONTINUE 411
+
+#define IDB_PROGRESS_BACKGROUND 444
+#define IDS_PROGRESS_FOREGROUND 445
+#define IDB_PAUSE 446
+#define IDS_PROGRESS_PAUSED 447
+#define IDS_PROGRESS_ASK_CANCEL 448
+
+#define IDT_PROGRESS_PACKED 1008
+#define IDT_PROGRESS_FILES 1032
+
+#define IDT_PROGRESS_ELAPSED 3900
+#define IDT_PROGRESS_REMAINING 3901
+#define IDT_PROGRESS_TOTAL 3902
+#define IDT_PROGRESS_SPEED 3903
+#define IDT_PROGRESS_PROCESSED 3904
+#define IDT_PROGRESS_RATIO 3905
+#define IDT_PROGRESS_ERRORS 3906
+
+#define IDC_PROGRESS1 100
+#define IDL_PROGRESS_MESSAGES 101
+#define IDT_PROGRESS_FILE_NAME 102
+#define IDT_PROGRESS_STATUS 103
+
+#define IDT_PROGRESS_PACKED_VAL 110
+#define IDT_PROGRESS_FILES_VAL 111
+
+#define IDT_PROGRESS_ELAPSED_VAL 120
+#define IDT_PROGRESS_REMAINING_VAL 121
+#define IDT_PROGRESS_TOTAL_VAL 122
+#define IDT_PROGRESS_SPEED_VAL 123
+#define IDT_PROGRESS_PROCESSED_VAL 124
+#define IDT_PROGRESS_RATIO_VAL 125
+#define IDT_PROGRESS_ERRORS_VAL 126
+
+
+#ifdef UNDER_CE
+#define MY_PROGRESS_VAL_UNITS 44
+#else
+#define MY_PROGRESS_VAL_UNITS 76
+#endif
+#define MY_PROGRESS_LABEL_UNITS_MIN 60
+#define MY_PROGRESS_LABEL_UNITS_START 90
+#define MY_PROGRESS_PAD_UNITS 4
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2a.rc b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2a.rc
new file mode 100644
index 0000000000..f1daec70ad
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2a.rc
@@ -0,0 +1,80 @@
+#undef bxs
+#define bxs 80
+
+#define x0s MY_PROGRESS_LABEL_UNITS_START
+#define x1s MY_PROGRESS_VAL_UNITS
+#define x2s MY_PROGRESS_LABEL_UNITS_START
+#define x3s MY_PROGRESS_VAL_UNITS
+
+#define x1 (m + x0s)
+#define x3 (xs - m - x3s)
+#define x2 (x3 - x2s)
+
+#undef y0
+#undef y1
+#undef y2
+#undef y3
+#undef y4
+
+#undef z0
+#undef z1
+#undef z2
+#undef z3
+
+#define y0 m
+#define y1 (y0 + k)
+#define y2 (y1 + k)
+#define y3 (y2 + k)
+#define y4 (y3 + k)
+
+#define z3 (y4 + k + 1)
+
+#define z2 (z3 + k + 1)
+#define z2s 24
+
+#define z1 (z2 + z2s)
+
+#define z0 (z1 + z1s + m)
+#define z0s 48
+
+#define yc (z0 + z0s + bys)
+
+
+DIALOG_ID DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
+CAPTION "Progress"
+{
+ DEFPUSHBUTTON "&Background", IDB_PROGRESS_BACKGROUND, bx3, by, bxs, bys
+ PUSHBUTTON "&Pause", IDB_PAUSE bx2, by, bxs, bys
+ PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
+
+ LTEXT "Elapsed time:", IDT_PROGRESS_ELAPSED, m, y0, x0s, 8
+ LTEXT "Remaining time:", IDT_PROGRESS_REMAINING, m, y1, x0s, 8
+ LTEXT "Files:", IDT_PROGRESS_FILES, m, y2, x0s, 8
+ LTEXT "Compression ratio:", IDT_PROGRESS_RATIO, m, y3, x0s, 8
+ LTEXT "Errors:", IDT_PROGRESS_ERRORS, m, y4, x0s, 8
+
+ LTEXT "Total size:", IDT_PROGRESS_TOTAL, x2, y0, x2s, 8
+ LTEXT "Speed:", IDT_PROGRESS_SPEED, x2, y1, x2s, 8
+ LTEXT "Processed:", IDT_PROGRESS_PROCESSED,x2, y2, x2s, 8
+ LTEXT "Compressed size:" , IDT_PROGRESS_PACKED, x2, y3, x2s, 8
+
+ RTEXT "", IDT_PROGRESS_ELAPSED_VAL, x1, y0, x1s, MY_TEXT_NOPREFIX
+ RTEXT "", IDT_PROGRESS_REMAINING_VAL, x1, y1, x1s, MY_TEXT_NOPREFIX
+ RTEXT "", IDT_PROGRESS_FILES_VAL, x1, y2, x1s, MY_TEXT_NOPREFIX
+ RTEXT "", IDT_PROGRESS_RATIO_VAL, x1, y3, x1s, MY_TEXT_NOPREFIX
+ RTEXT "", IDT_PROGRESS_ERRORS_VAL, x1, y4, x1s, MY_TEXT_NOPREFIX
+
+ RTEXT "", IDT_PROGRESS_TOTAL_VAL, x3, y0, x3s, MY_TEXT_NOPREFIX
+ RTEXT "", IDT_PROGRESS_SPEED_VAL, x3, y1, x3s, MY_TEXT_NOPREFIX
+ RTEXT "", IDT_PROGRESS_PROCESSED_VAL, x3, y2, x3s, MY_TEXT_NOPREFIX
+ RTEXT "", IDT_PROGRESS_PACKED_VAL, x3, y3, x3s, MY_TEXT_NOPREFIX
+
+ LTEXT "", IDT_PROGRESS_STATUS, m, z3, xc, MY_TEXT_NOPREFIX
+ CONTROL "", IDT_PROGRESS_FILE_NAME, "Static", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc, z2s
+
+ CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s
+
+ CONTROL "List1", IDL_PROGRESS_MESSAGES, "SysListView32",
+ LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
+ m, z0, xc, z0s
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialogRes.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialogRes.h
new file mode 100644
index 0000000000..a2814188a5
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialogRes.h
@@ -0,0 +1,3 @@
+#define IDD_PROGRESS 97
+
+#define IDC_PROGRESS1 100
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.cpp
new file mode 100644
index 0000000000..a9552415f1
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.cpp
@@ -0,0 +1,23 @@
+// PropertyName.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+
+#include "LangUtils.h"
+#include "PropertyName.h"
+
+UString GetNameOfProperty(PROPID propID, const wchar_t *name)
+{
+ if (propID < 1000)
+ {
+ UString s = LangString(1000 + propID);
+ if (!s.IsEmpty())
+ return s;
+ }
+ if (name)
+ return name;
+ wchar_t temp[16];
+ ConvertUInt32ToString(propID, temp);
+ return temp;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.h
new file mode 100644
index 0000000000..a1061b74f5
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.h
@@ -0,0 +1,10 @@
+// PropertyName.h
+
+#ifndef __PROPERTY_NAME_H
+#define __PROPERTY_NAME_H
+
+#include "../../../Common/MyString.h"
+
+UString GetNameOfProperty(PROPID propID, const wchar_t *name);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyNameRes.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyNameRes.h
new file mode 100644
index 0000000000..1315b8995e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyNameRes.h
@@ -0,0 +1,95 @@
+
+
+#define IDS_PROP_PATH 1003
+#define IDS_PROP_NAME 1004
+#define IDS_PROP_EXTENSION 1005
+#define IDS_PROP_IS_FOLDER 1006
+#define IDS_PROP_SIZE 1007
+#define IDS_PROP_PACKED_SIZE 1008
+#define IDS_PROP_ATTRIBUTES 1009
+#define IDS_PROP_CTIME 1010
+#define IDS_PROP_ATIME 1011
+#define IDS_PROP_MTIME 1012
+#define IDS_PROP_SOLID 1013
+#define IDS_PROP_C0MMENTED 1014
+#define IDS_PROP_ENCRYPTED 1015
+#define IDS_PROP_SPLIT_BEFORE 1016
+#define IDS_PROP_SPLIT_AFTER 1017
+#define IDS_PROP_DICTIONARY_SIZE 1018
+#define IDS_PROP_CRC 1019
+#define IDS_PROP_FILE_TYPE 1020
+#define IDS_PROP_ANTI 1021
+#define IDS_PROP_METHOD 1022
+#define IDS_PROP_HOST_OS 1023
+#define IDS_PROP_FILE_SYSTEM 1024
+#define IDS_PROP_USER 1025
+#define IDS_PROP_GROUP 1026
+#define IDS_PROP_BLOCK 1027
+#define IDS_PROP_COMMENT 1028
+#define IDS_PROP_POSITION 1029
+#define IDS_PROP_PREFIX 1030
+#define IDS_PROP_FOLDERS 1031
+#define IDS_PROP_FILES 1032
+#define IDS_PROP_VERSION 1033
+#define IDS_PROP_VOLUME 1034
+#define IDS_PROP_IS_VOLUME 1035
+#define IDS_PROP_OFFSET 1036
+#define IDS_PROP_LINKS 1037
+#define IDS_PROP_NUM_BLOCKS 1038
+#define IDS_PROP_NUM_VOLUMES 1039
+
+#define IDS_PROP_BIT64 1041
+#define IDS_PROP_BIG_ENDIAN 1042
+#define IDS_PROP_CPU 1043
+#define IDS_PROP_PHY_SIZE 1044
+#define IDS_PROP_HEADERS_SIZE 1045
+#define IDS_PROP_CHECKSUM 1046
+#define IDS_PROP_CHARACTS 1047
+#define IDS_PROP_VA 1048
+#define IDS_PROP_ID 1049
+#define IDS_PROP_SHORT_NAME 1050
+#define IDS_PROP_CREATOR_APP 1051
+#define IDS_PROP_SECTOR_SIZE 1052
+#define IDS_PROP_POSIX_ATTRIB 1053
+#define IDS_PROP_SYM_LINK 1054
+#define IDS_PROP_ERROR 1055
+#define IDS_PROP_TOTAL_SIZE 1056
+#define IDS_PROP_FREE_SPACE 1057
+#define IDS_PROP_CLUSTER_SIZE 1058
+#define IDS_PROP_VOLUME_NAME 1059
+#define IDS_PROP_LOCAL_NAME 1060
+#define IDS_PROP_PROVIDER 1061
+#define IDS_PROP_NT_SECURITY 1062
+#define IDS_PROP_ALT_STREAM 1063
+#define IDS_PROP_AUX 1064
+#define IDS_PROP_DELETED 1065
+#define IDS_PROP_IS_TREE 1066
+#define IDS_PROP_SHA1 1067
+#define IDS_PROP_SHA256 1068
+#define IDS_PROP_ERROR_TYPE 1069
+#define IDS_PROP_NUM_ERRORS 1070
+#define IDS_PROP_ERROR_FLAGS 1071
+#define IDS_PROP_WARNING_FLAGS 1072
+#define IDS_PROP_WARNING 1073
+#define IDS_PROP_NUM_STREAMS 1074
+#define IDS_PROP_NUM_ALT_STREAMS 1075
+#define IDS_PROP_ALT_STREAMS_SIZE 1076
+#define IDS_PROP_VIRTUAL_SIZE 1077
+#define IDS_PROP_UNPACK_SIZE 1078
+#define IDS_PROP_TOTAL_PHY_SIZE 1079
+#define IDS_PROP_VOLUME_INDEX 1080
+#define IDS_PROP_SUBTYPE 1081
+#define IDS_PROP_SHORT_COMMENT 1082
+#define IDS_PROP_CODE_PAGE 1083
+#define IDS_PROP_IS_NOT_ARC_TYPE 1084
+#define IDS_PROP_PHY_SIZE_CANT_BE_DETECTED 1085
+#define IDS_PROP_ZEROS_TAIL_IS_ALLOWED 1086
+#define IDS_PROP_TAIL_SIZE 1087
+#define IDS_PROP_EMB_STUB_SIZE 1088
+#define IDS_PROP_NT_REPARSE 1089
+#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
+#define IDS_PROP_COPY_LINK 1095
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.cpp
new file mode 100644
index 0000000000..2100e82944
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.cpp
@@ -0,0 +1,255 @@
+// SysIconUtils.cpp
+
+#include "StdAfx.h"
+
+#ifndef _UNICODE
+#include "../../../Common/StringConvert.h"
+#endif
+
+#include "../../../Windows/FileDir.h"
+
+#include "SysIconUtils.h"
+
+#include <ShlObj.h>
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+int GetIconIndexForCSIDL(int csidl)
+{
+ LPITEMIDLIST pidl = 0;
+ SHGetSpecialFolderLocation(NULL, csidl, &pidl);
+ if (pidl)
+ {
+ SHFILEINFO shellInfo;
+ SHGetFileInfo(LPCTSTR(pidl), FILE_ATTRIBUTE_NORMAL,
+ &shellInfo, sizeof(shellInfo),
+ SHGFI_PIDL | SHGFI_SYSICONINDEX);
+ IMalloc *pMalloc;
+ SHGetMalloc(&pMalloc);
+ if (pMalloc)
+ {
+ pMalloc->Free(pidl);
+ pMalloc->Release();
+ }
+ return shellInfo.iIcon;
+ }
+ return 0;
+}
+
+#ifndef _UNICODE
+typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);
+
+struct CSHGetFileInfoInit
+{
+ SHGetFileInfoWP shGetFileInfoW;
+ CSHGetFileInfoInit()
+ {
+ shGetFileInfoW = (SHGetFileInfoWP)
+ ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW");
+ }
+} g_SHGetFileInfoInit;
+#endif
+
+static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)
+{
+ #ifdef _UNICODE
+ return SHGetFileInfo
+ #else
+ if (g_SHGetFileInfoInit.shGetFileInfoW == 0)
+ return 0;
+ return g_SHGetFileInfoInit.shGetFileInfoW
+ #endif
+ (pszPath, attrib, psfi, cbFileInfo, uFlags);
+}
+
+DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ SHFILEINFO shellInfo;
+ DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
+ sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
+ iconIndex = shellInfo.iIcon;
+ return res;
+ }
+ else
+ #endif
+ {
+ SHFILEINFOW shellInfo;
+ DWORD_PTR res = ::MySHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
+ sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
+ iconIndex = shellInfo.iIcon;
+ return res;
+ }
+}
+
+/*
+DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ SHFILEINFO shellInfo;
+ shellInfo.szTypeName[0] = 0;
+ DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
+ sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
+ if (typeName)
+ *typeName = GetUnicodeString(shellInfo.szTypeName);
+ iconIndex = shellInfo.iIcon;
+ return res;
+ }
+ else
+ #endif
+ {
+ SHFILEINFOW shellInfo;
+ shellInfo.szTypeName[0] = 0;
+ DWORD_PTR res = ::MySHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
+ sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
+ if (typeName)
+ *typeName = shellInfo.szTypeName;
+ iconIndex = shellInfo.iIcon;
+ return res;
+ }
+}
+*/
+
+static int FindInSorted_Attrib(const CRecordVector<CAttribIconPair> &vect, DWORD attrib, int &insertPos)
+{
+ unsigned left = 0, right = vect.Size();
+ while (left != right)
+ {
+ unsigned mid = (left + right) / 2;
+ DWORD midAttrib = vect[mid].Attrib;
+ if (attrib == midAttrib)
+ return mid;
+ if (attrib < midAttrib)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ insertPos = left;
+ return -1;
+}
+
+static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, int &insertPos)
+{
+ unsigned left = 0, right = vect.Size();
+ while (left != right)
+ {
+ unsigned mid = (left + right) / 2;
+ int compare = MyStringCompareNoCase(ext, vect[mid].Ext);
+ if (compare == 0)
+ return mid;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ insertPos = left;
+ return -1;
+}
+
+int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
+{
+ int dotPos = -1;
+ unsigned i;
+ for (i = 0;; i++)
+ {
+ wchar_t c = fileName[i];
+ if (c == 0)
+ break;
+ if (c == '.')
+ dotPos = i;
+ }
+
+ /*
+ if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0)
+ {
+ char s[256];
+ sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib);
+ OutputDebugStringA(s);
+ OutputDebugStringW(fileName);
+ }
+ */
+
+ if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0)
+ {
+ int insertPos = 0;
+ int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);
+ if (index >= 0)
+ {
+ // if (typeName) *typeName = _attribMap[index].TypeName;
+ return _attribMap[index].IconIndex;
+ }
+ CAttribIconPair pair;
+ GetRealIconIndex(
+ #ifdef UNDER_CE
+ FTEXT("\\")
+ #endif
+ FTEXT("__DIR__")
+ , attrib, pair.IconIndex
+ // , pair.TypeName
+ );
+
+ /*
+ char s[256];
+ sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);
+ OutputDebugStringA(s);
+ */
+
+ pair.Attrib = attrib;
+ _attribMap.Insert(insertPos, pair);
+ // if (typeName) *typeName = pair.TypeName;
+ return pair.IconIndex;
+ }
+
+ const wchar_t *ext = fileName + dotPos + 1;
+ int insertPos = 0;
+ int index = FindInSorted_Ext(_extMap, ext, insertPos);
+ if (index >= 0)
+ {
+ const CExtIconPair &pa = _extMap[index];
+ // if (typeName) *typeName = pa.TypeName;
+ return pa.IconIndex;
+ }
+
+ for (i = 0;; i++)
+ {
+ wchar_t c = ext[i];
+ if (c == 0)
+ break;
+ if (c < L'0' || c > L'9')
+ break;
+ }
+ if (i != 0 && ext[i] == 0)
+ {
+ // GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003
+ if (!SplitIconIndex_Defined)
+ {
+ GetRealIconIndex(
+ #ifdef UNDER_CE
+ FTEXT("\\")
+ #endif
+ FTEXT("__FILE__.001"), 0, SplitIconIndex);
+ SplitIconIndex_Defined = true;
+ }
+ return SplitIconIndex;
+ }
+
+ CExtIconPair pair;
+ pair.Ext = ext;
+ GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex);
+ _extMap.Insert(insertPos, pair);
+ // if (typeName) *typeName = pair.TypeName;
+ return pair.IconIndex;
+}
+
+/*
+int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName)
+{
+ return GetIconIndex(attrib, fileName, NULL);
+}
+*/
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.h
new file mode 100644
index 0000000000..2eedc4be40
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.h
@@ -0,0 +1,62 @@
+// SysIconUtils.h
+
+#ifndef __SYS_ICON_UTILS_H
+#define __SYS_ICON_UTILS_H
+
+#include "../../../Common/MyWindows.h"
+
+#include <commctrl.h>
+
+#include "../../../Common/MyString.h"
+
+struct CExtIconPair
+{
+ UString Ext;
+ int IconIndex;
+ // UString TypeName;
+
+ // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); }
+};
+
+struct CAttribIconPair
+{
+ DWORD Attrib;
+ int IconIndex;
+ // UString TypeName;
+
+ // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); }
+};
+
+class CExtToIconMap
+{
+public:
+ CRecordVector<CAttribIconPair> _attribMap;
+ CObjectVector<CExtIconPair> _extMap;
+ int SplitIconIndex;
+ int SplitIconIndex_Defined;
+
+ CExtToIconMap(): SplitIconIndex_Defined(false) {}
+
+ void Clear()
+ {
+ SplitIconIndex_Defined = false;
+ _extMap.Clear();
+ _attribMap.Clear();
+ }
+ int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */);
+ // int GetIconIndex(DWORD attrib, const UString &fileName);
+};
+
+DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex);
+int GetIconIndexForCSIDL(int csidl);
+
+inline HIMAGELIST GetSysImageList(bool smallIcons)
+{
+ SHFILEINFO shellInfo;
+ return (HIMAGELIST)SHGetFileInfo(TEXT(""),
+ FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY,
+ &shellInfo, sizeof(shellInfo),
+ SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | (smallIcons ? SHGFI_SMALLICON : SHGFI_ICON));
+}
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resource.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resource.h
new file mode 100644
index 0000000000..466626925e
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resource.h
@@ -0,0 +1,177 @@
+#include "resourceGui.h"
+
+#define IDR_MENUBAR1 70
+#define IDM_MENU 71
+#define IDR_ACCELERATOR1 72
+
+#define IDB_ADD 100
+#define IDB_EXTRACT 101
+#define IDB_TEST 102
+#define IDB_COPY 103
+#define IDB_MOVE 104
+#define IDB_DELETE 105
+#define IDB_INFO 106
+
+#define IDB_ADD2 150
+#define IDB_EXTRACT2 151
+#define IDB_TEST2 152
+#define IDB_COPY2 153
+#define IDB_MOVE2 154
+#define IDB_DELETE2 155
+#define IDB_INFO2 156
+
+#define IDM_HASH_ALL 101
+#define IDM_CRC32 102
+#define IDM_CRC64 103
+#define IDM_SHA1 104
+#define IDM_SHA256 105
+
+#define IDM_OPEN 540
+#define IDM_OPEN_INSIDE 541
+#define IDM_OPEN_OUTSIDE 542
+#define IDM_FILE_VIEW 543
+#define IDM_FILE_EDIT 544
+#define IDM_RENAME 545
+#define IDM_COPY_TO 546
+#define IDM_MOVE_TO 547
+#define IDM_DELETE 548
+#define IDM_SPLIT 549
+#define IDM_COMBINE 550
+#define IDM_PROPERTIES 551
+#define IDM_COMMENT 552
+#define IDM_CRC 553
+#define IDM_DIFF 554
+#define IDM_CREATE_FOLDER 555
+#define IDM_CREATE_FILE 556
+// #define IDM_EXIT 557
+#define IDM_LINK 558
+#define IDM_ALT_STREAMS 559
+
+#define IDM_OPEN_INSIDE_ONE 590
+#define IDM_OPEN_INSIDE_PARSER 591
+
+#define IDM_SELECT_ALL 600
+#define IDM_DESELECT_ALL 601
+#define IDM_INVERT_SELECTION 602
+#define IDM_SELECT 603
+#define IDM_DESELECT 604
+#define IDM_SELECT_BY_TYPE 605
+#define IDM_DESELECT_BY_TYPE 606
+
+#define IDM_VIEW_LARGE_ICONS 700
+#define IDM_VIEW_SMALL_ICONS 701
+#define IDM_VIEW_LIST 702
+#define IDM_VIEW_DETAILS 703
+
+#define IDM_VIEW_ARANGE_BY_NAME 710
+#define IDM_VIEW_ARANGE_BY_TYPE 711
+#define IDM_VIEW_ARANGE_BY_DATE 712
+#define IDM_VIEW_ARANGE_BY_SIZE 713
+
+#define IDM_VIEW_ARANGE_NO_SORT 730
+#define IDM_VIEW_FLAT_VIEW 731
+#define IDM_VIEW_TWO_PANELS 732
+#define IDM_VIEW_TOOLBARS 733
+#define IDM_OPEN_ROOT_FOLDER 734
+#define IDM_OPEN_PARENT_FOLDER 735
+#define IDM_FOLDERS_HISTORY 736
+#define IDM_VIEW_REFRESH 737
+#define IDM_VIEW_AUTO_REFRESH 738
+// #define IDM_VIEW_SHOW_DELETED 739
+// #define IDM_VIEW_SHOW_STREAMS 740
+
+#define IDM_VIEW_ARCHIVE_TOOLBAR 750
+#define IDM_VIEW_STANDARD_TOOLBAR 751
+#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 752
+#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753
+
+#define IDM_VIEW_TIME 761
+
+#define IDS_BOOKMARK 801
+
+#define IDM_OPTIONS 900
+#define IDM_BENCHMARK 901
+#define IDM_BENCHMARK2 902
+
+#define IDM_HELP_CONTENTS 960
+#define IDM_ABOUT 961
+
+#define IDS_OPTIONS 2100
+
+#define IDS_N_SELECTED_ITEMS 3002
+
+#define IDS_FILE_EXIST 3008
+#define IDS_WANT_UPDATE_MODIFIED_FILE 3009
+#define IDS_CANNOT_UPDATE_FILE 3010
+#define IDS_CANNOT_START_EDITOR 3011
+#define IDS_VIRUS 3012
+#define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER 3013
+#define IDS_SELECT_ONE_FILE 3014
+#define IDS_SELECT_FILES 3015
+#define IDS_TOO_MANY_ITEMS 3016
+
+#define IDS_COPY 6000
+#define IDS_MOVE 6001
+#define IDS_COPY_TO 6002
+#define IDS_MOVE_TO 6003
+#define IDS_COPYING 6004
+#define IDS_MOVING 6005
+#define IDS_RENAMING 6006
+
+#define IDS_OPERATION_IS_NOT_SUPPORTED 6008
+#define IDS_ERROR_RENAMING 6009
+#define IDS_CONFIRM_FILE_COPY 6010
+#define IDS_WANT_TO_COPY_FILES 6011
+
+#define IDS_CONFIRM_FILE_DELETE 6100
+#define IDS_CONFIRM_FOLDER_DELETE 6101
+#define IDS_CONFIRM_ITEMS_DELETE 6102
+#define IDS_WANT_TO_DELETE_FILE 6103
+#define IDS_WANT_TO_DELETE_FOLDER 6104
+#define IDS_WANT_TO_DELETE_ITEMS 6105
+#define IDS_DELETING 6106
+#define IDS_ERROR_DELETING 6107
+#define IDS_ERROR_LONG_PATH_TO_RECYCLE 6108
+
+#define IDS_CREATE_FOLDER 6300
+#define IDS_CREATE_FILE 6301
+#define IDS_CREATE_FOLDER_NAME 6302
+#define IDS_CREATE_FILE_NAME 6303
+#define IDS_CREATE_FOLDER_DEFAULT_NAME 6304
+#define IDS_CREATE_FILE_DEFAULT_NAME 6305
+#define IDS_CREATE_FOLDER_ERROR 6306
+#define IDS_CREATE_FILE_ERROR 6307
+
+#define IDS_COMMENT 6400
+#define IDS_COMMENT2 6401
+#define IDS_SELECT 6402
+#define IDS_DESELECT 6403
+#define IDS_SELECT_MASK 6404
+
+#define IDS_PROPERTIES 6600
+#define IDS_FOLDERS_HISTORY 6601
+
+#define IDS_COMPUTER 7100
+#define IDS_NETWORK 7101
+#define IDS_DOCUMENTS 7102
+#define IDS_SYSTEM 7103
+
+#define IDS_ADD 7200
+#define IDS_EXTRACT 7201
+#define IDS_TEST 7202
+#define IDS_BUTTON_COPY 7203
+#define IDS_BUTTON_MOVE 7204
+#define IDS_BUTTON_DELETE 7205
+#define IDS_BUTTON_INFO 7206
+
+#define IDS_SPLITTING 7303
+#define IDS_SPLIT_CONFIRM_TITLE 7304
+#define IDS_SPLIT_CONFIRM_MESSAGE 7305
+#define IDS_SPLIT_VOL_MUST_BE_SMALLER 7306
+
+#define IDS_COMBINE 7400
+#define IDS_COMBINE_TO 7401
+#define IDS_COMBINING 7402
+#define IDS_COMBINE_SELECT_ONE_FILE 7403
+#define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 7404
+#define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 7405
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resourceGui.h b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resourceGui.h
new file mode 100644
index 0000000000..025f316ecc
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resourceGui.h
@@ -0,0 +1,15 @@
+#define IDI_ICON 1
+
+#define IDS_MESSAGE_NO_ERRORS 3001
+
+#define IDS_PROGRESS_TESTING 3302
+#define IDS_OPENNING 3303
+#define IDS_SCANNING 3304
+
+#define IDS_CHECKSUM_CALCULATING 7500
+#define IDS_CHECKSUM_INFORMATION 7501
+#define IDS_CHECKSUM_CRC_DATA 7502
+#define IDS_CHECKSUM_CRC_DATA_NAMES 7503
+#define IDS_CHECKSUM_CRC_STREAMS_NAMES 7504
+
+#define IDS_INCORRECT_VOLUME_SIZE 7307
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/Extract.rc b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/Extract.rc
new file mode 100644
index 0000000000..6bda89e393
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/Extract.rc
@@ -0,0 +1,59 @@
+#include "ExtractRes.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_MEM_ERROR "The system cannot allocate the required amount of memory"
+ IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'"
+ IDS_UPDATE_NOT_SUPPORTED "Update operations are not supported for this archive."
+ IDS_CANT_OPEN_ARCHIVE "Can not open file '{0}' as archive"
+ 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"
+ IDS_EXTRACT_PATHS_NO "No pathnames"
+ IDS_EXTRACT_PATHS_ABS "Absolute pathnames"
+ IDS_PATH_MODE_RELAT "Relative pathnames"
+
+ IDS_EXTRACT_OVERWRITE_ASK "Ask before overwrite"
+ IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT "Overwrite without prompt"
+ IDS_EXTRACT_OVERWRITE_SKIP_EXISTING "Skip existing files"
+ IDS_EXTRACT_OVERWRITE_RENAME "Auto rename"
+ IDS_EXTRACT_OVERWRITE_RENAME_EXISTING "Auto rename existing files"
+
+ IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD "Unsupported compression method for '{0}'."
+ IDS_EXTRACT_MESSAGE_DATA_ERROR "Data error in '{0}'. File is broken"
+ IDS_EXTRACT_MESSAGE_CRC_ERROR "CRC failed in '{0}'. File is broken."
+ 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_GUESS "Wrong password?"
+ // IDS_EXTRACT_MSG_ENCRYPTED "Encrypted file"
+
+ IDS_EXTRACT_MSG_UNSUPPORTED_METHOD "Unsupported compression method"
+ IDS_EXTRACT_MSG_DATA_ERROR "Data error"
+ IDS_EXTRACT_MSG_CRC_ERROR "CRC failed"
+ IDS_EXTRACT_MSG_UNAVAILABLE_DATA "Unavailable data"
+ IDS_EXTRACT_MSG_UEXPECTED_END "Unexpected end of data";
+ 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"
+ // IDS_OPEN_MSG_ERROR_FLAGS + 5 "Unexpected end of archive"
+ // IDS_OPEN_MSG_ERROR_FLAGS + 6 "There are data after the end of archive"
+ IDS_OPEN_MSG_UNSUPPORTED_FEATURE "Unsupported feature"
+END
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.cpp
new file mode 100644
index 0000000000..71c2a3b614
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.cpp
@@ -0,0 +1,418 @@
+// ExtractDialog.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/ResourceString.h"
+
+#ifndef NO_REGISTRY
+#include "../FileManager/HelpUtils.h"
+#endif
+
+
+#include "../FileManager/BrowseDialog.h"
+#include "../FileManager/LangUtils.h"
+#include "../FileManager/resourceGui.h"
+
+#include "ExtractDialog.h"
+#include "ExtractDialogRes.h"
+#include "ExtractRes.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+
+extern HINSTANCE g_hInstance;
+
+static const UInt32 kPathMode_IDs[] =
+{
+ IDS_EXTRACT_PATHS_FULL,
+ IDS_EXTRACT_PATHS_NO,
+ IDS_EXTRACT_PATHS_ABS
+};
+
+static const UInt32 kOverwriteMode_IDs[] =
+{
+ IDS_EXTRACT_OVERWRITE_ASK,
+ IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT,
+ IDS_EXTRACT_OVERWRITE_SKIP_EXISTING,
+ IDS_EXTRACT_OVERWRITE_RENAME,
+ IDS_EXTRACT_OVERWRITE_RENAME_EXISTING
+};
+
+#ifndef _SFX
+
+static const
+ // NExtract::NPathMode::EEnum
+ int
+ kPathModeButtonsVals[] =
+{
+ NExtract::NPathMode::kFullPaths,
+ NExtract::NPathMode::kNoPaths,
+ NExtract::NPathMode::kAbsPaths
+};
+
+static const
+ int
+ // NExtract::NOverwriteMode::EEnum
+ kOverwriteButtonsVals[] =
+{
+ NExtract::NOverwriteMode::kAsk,
+ NExtract::NOverwriteMode::kOverwrite,
+ NExtract::NOverwriteMode::kSkip,
+ NExtract::NOverwriteMode::kRename,
+ NExtract::NOverwriteMode::kRenameExisting
+};
+
+#endif
+
+#ifdef LANG
+
+static const UInt32 kLangIDs[] =
+{
+ IDT_EXTRACT_EXTRACT_TO,
+ IDT_EXTRACT_PATH_MODE,
+ IDT_EXTRACT_OVERWRITE_MODE,
+ // IDX_EXTRACT_ALT_STREAMS,
+ IDX_EXTRACT_NT_SECUR,
+ IDX_EXTRACT_ELIM_DUP,
+ IDG_PASSWORD,
+ IDX_PASSWORD_SHOW
+};
+#endif
+
+// static const int kWildcardsButtonIndex = 2;
+
+#ifndef NO_REGISTRY
+static const unsigned kHistorySize = 16;
+#endif
+
+#ifndef _SFX
+
+// it's used in CompressDialog also
+void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal)
+{
+ int curSel = 0;
+ for (unsigned i = 0; i < numItems; i++)
+ {
+ UString s = LangString(langIDs[i]);
+ s.RemoveChar(L'&');
+ int index = (int)combo.AddString(s);
+ combo.SetItemData(index, i);
+ if (values[i] == curVal)
+ curSel = i;
+ }
+ combo.SetCurSel(curSel);
+}
+
+// it's used in CompressDialog also
+bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2)
+{
+ if (b1.Def) return b1.Val;
+ if (b2.Def) return b2.Val;
+ return b1.Val;
+}
+
+void CExtractDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2)
+{
+ CheckButton(id, GetBoolsVal(b1, b2));
+}
+
+void CExtractDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2)
+{
+ bool val = IsButtonCheckedBool(id);
+ bool oldVal = GetBoolsVal(b1, b2);
+ if (val != oldVal)
+ b1.Def = b2.Def = true;
+ b1.Val = b2.Val = val;
+}
+
+#endif
+
+bool CExtractDialog::OnInit()
+{
+ #ifdef LANG
+ {
+ UString s;
+ LangString_OnlyFromLangFile(IDD_EXTRACT, s);
+ if (s.IsEmpty())
+ GetText(s);
+ if (!ArcPath.IsEmpty())
+ {
+ s += " : ";
+ s += ArcPath;
+ }
+ SetText(s);
+ // LangSetWindowText(*this, IDD_EXTRACT);
+ LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
+ }
+ #endif
+
+ #ifndef _SFX
+ _passwordControl.Attach(GetItem(IDE_EXTRACT_PASSWORD));
+ _passwordControl.SetText(Password);
+ _passwordControl.SetPasswordChar(TEXT('*'));
+ _pathName.Attach(GetItem(IDE_EXTRACT_NAME));
+ #endif
+
+ #ifdef NO_REGISTRY
+
+ PathMode = NExtract::NPathMode::kFullPaths;
+ OverwriteMode = NExtract::NOverwriteMode::kAsk;
+
+ #else
+
+ _info.Load();
+
+ if (_info.PathMode == NExtract::NPathMode::kCurPaths)
+ _info.PathMode = NExtract::NPathMode::kFullPaths;
+
+ if (!PathMode_Force && _info.PathMode_Force)
+ PathMode = _info.PathMode;
+ if (!OverwriteMode_Force && _info.OverwriteMode_Force)
+ OverwriteMode = _info.OverwriteMode;
+
+ // CheckButton_TwoBools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams);
+ CheckButton_TwoBools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity);
+ CheckButton_TwoBools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup);
+
+ CheckButton(IDX_PASSWORD_SHOW, _info.ShowPassword.Val);
+ UpdatePasswordControl();
+
+ #endif
+
+ _path.Attach(GetItem(IDC_EXTRACT_PATH));
+
+ UString pathPrefix = DirPath;
+
+ #ifndef _SFX
+
+ if (_info.SplitDest.Val)
+ {
+ CheckButton(IDX_EXTRACT_NAME_ENABLE, true);
+ UString pathName;
+ SplitPathToParts_Smart(DirPath, pathPrefix, pathName);
+ if (pathPrefix.IsEmpty())
+ pathPrefix = pathName;
+ else
+ _pathName.SetText(pathName);
+ }
+ else
+ ShowItem_Bool(IDE_EXTRACT_NAME, false);
+
+ #endif
+
+ _path.SetText(pathPrefix);
+
+ #ifndef NO_REGISTRY
+ for (unsigned i = 0; i < _info.Paths.Size() && i < kHistorySize; i++)
+ _path.AddString(_info.Paths[i]);
+ #endif
+
+ /*
+ if (_info.Paths.Size() > 0)
+ _path.SetCurSel(0);
+ else
+ _path.SetCurSel(-1);
+ */
+
+ #ifndef _SFX
+
+ _pathMode.Attach(GetItem(IDC_EXTRACT_PATH_MODE));
+ _overwriteMode.Attach(GetItem(IDC_EXTRACT_OVERWRITE_MODE));
+
+ AddComboItems(_pathMode, kPathMode_IDs, ARRAY_SIZE(kPathMode_IDs), kPathModeButtonsVals, PathMode);
+ AddComboItems(_overwriteMode, kOverwriteMode_IDs, ARRAY_SIZE(kOverwriteMode_IDs), kOverwriteButtonsVals, OverwriteMode);
+
+ #endif
+
+ HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
+ SetIcon(ICON_BIG, icon);
+
+ // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES);
+ // filesWindow.Enable(_enableFilesButton);
+
+ NormalizePosition();
+
+ return CModalDialog::OnInit();
+}
+
+#ifndef _SFX
+void CExtractDialog::UpdatePasswordControl()
+{
+ _passwordControl.SetPasswordChar(IsShowPasswordChecked() ? 0 : TEXT('*'));
+ UString password;
+ _passwordControl.GetText(password);
+ _passwordControl.SetText(password);
+}
+#endif
+
+bool CExtractDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
+{
+ switch (buttonID)
+ {
+ case IDB_EXTRACT_SET_PATH:
+ OnButtonSetPath();
+ return true;
+ #ifndef _SFX
+ case IDX_EXTRACT_NAME_ENABLE:
+ ShowItem_Bool(IDE_EXTRACT_NAME, IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE));
+ return true;
+ case IDX_PASSWORD_SHOW:
+ {
+ UpdatePasswordControl();
+ return true;
+ }
+ #endif
+ }
+ return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
+}
+
+void CExtractDialog::OnButtonSetPath()
+{
+ UString currentPath;
+ _path.GetText(currentPath);
+ UString title = LangString(IDS_EXTRACT_SET_FOLDER);
+ UString resultPath;
+ if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
+ return;
+ #ifndef NO_REGISTRY
+ _path.SetCurSel(-1);
+ #endif
+ _path.SetText(resultPath);
+}
+
+void AddUniqueString(UStringVector &list, const UString &s)
+{
+ FOR_VECTOR (i, list)
+ if (s.IsEqualTo_NoCase(list[i]))
+ return;
+ list.Add(s);
+}
+
+void CExtractDialog::OnOK()
+{
+ #ifndef _SFX
+ int pathMode2 = kPathModeButtonsVals[_pathMode.GetCurSel()];
+ if (PathMode != NExtract::NPathMode::kCurPaths ||
+ pathMode2 != NExtract::NPathMode::kFullPaths)
+ PathMode = (NExtract::NPathMode::EEnum)pathMode2;
+
+ OverwriteMode = (NExtract::NOverwriteMode::EEnum)kOverwriteButtonsVals[_overwriteMode.GetCurSel()];
+
+ // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode();
+
+ _passwordControl.GetText(Password);
+
+ #endif
+
+ #ifndef NO_REGISTRY
+
+ // GetButton_Bools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams);
+ GetButton_Bools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity);
+ GetButton_Bools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup);
+
+ bool showPassword = IsShowPasswordChecked();
+ if (showPassword != _info.ShowPassword.Val)
+ {
+ _info.ShowPassword.Def = true;
+ _info.ShowPassword.Val = showPassword;
+ }
+
+ if (_info.PathMode != pathMode2)
+ {
+ _info.PathMode_Force = true;
+ _info.PathMode = (NExtract::NPathMode::EEnum)pathMode2;
+ /*
+ // we allow kAbsPaths in registry.
+ if (_info.PathMode == NExtract::NPathMode::kAbsPaths)
+ _info.PathMode = NExtract::NPathMode::kFullPaths;
+ */
+ }
+
+ if (!OverwriteMode_Force && _info.OverwriteMode != OverwriteMode)
+ _info.OverwriteMode_Force = true;
+ _info.OverwriteMode = OverwriteMode;
+
+
+ #else
+
+ ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP);
+
+ #endif
+
+ UString s;
+
+ #ifdef NO_REGISTRY
+
+ _path.GetText(s);
+
+ #else
+
+ int currentItem = _path.GetCurSel();
+ if (currentItem == CB_ERR)
+ {
+ _path.GetText(s);
+ if (_path.GetCount() >= kHistorySize)
+ currentItem = _path.GetCount() - 1;
+ }
+ else
+ _path.GetLBText(currentItem, s);
+
+ #endif
+
+ s.Trim();
+ NName::NormalizeDirPathPrefix(s);
+
+ #ifndef _SFX
+
+ bool splitDest = IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE);
+ if (splitDest)
+ {
+ UString pathName;
+ _pathName.GetText(pathName);
+ pathName.Trim();
+ s += pathName;
+ NName::NormalizeDirPathPrefix(s);
+ }
+ if (splitDest != _info.SplitDest.Val)
+ {
+ _info.SplitDest.Def = true;
+ _info.SplitDest.Val = splitDest;
+ }
+
+ #endif
+
+ DirPath = s;
+
+ #ifndef NO_REGISTRY
+ _info.Paths.Clear();
+ #ifndef _SFX
+ AddUniqueString(_info.Paths, s);
+ #endif
+ for (int i = 0; i < _path.GetCount(); i++)
+ if (i != currentItem)
+ {
+ UString sTemp;
+ _path.GetLBText(i, sTemp);
+ sTemp.Trim();
+ AddUniqueString(_info.Paths, sTemp);
+ }
+ _info.Save();
+ #endif
+
+ CModalDialog::OnOK();
+}
+
+#ifndef NO_REGISTRY
+#define kHelpTopic "fm/plugins/7-zip/extract.htm"
+void CExtractDialog::OnHelp()
+{
+ ShowHelpWindow(kHelpTopic);
+ CModalDialog::OnHelp();
+}
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.h b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.h
new file mode 100644
index 0000000000..308c786764
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.h
@@ -0,0 +1,113 @@
+// ExtractDialog.h
+
+#ifndef __EXTRACT_DIALOG_H
+#define __EXTRACT_DIALOG_H
+
+#include "ExtractDialogRes.h"
+
+#include "../../../Windows/Control/ComboBox.h"
+#include "../../../Windows/Control/Edit.h"
+
+#include "../Common/ExtractMode.h"
+
+#include "../FileManager/DialogSize.h"
+
+#ifndef NO_REGISTRY
+#include "../Common/ZipRegistry.h"
+#endif
+
+namespace NExtractionDialog
+{
+ /*
+ namespace NFilesMode
+ {
+ enum EEnum
+ {
+ kSelected,
+ kAll,
+ kSpecified
+ };
+ }
+ */
+}
+
+class CExtractDialog: public NWindows::NControl::CModalDialog
+{
+ #ifdef NO_REGISTRY
+ NWindows::NControl::CDialogChildControl _path;
+ #else
+ NWindows::NControl::CComboBox _path;
+ #endif
+
+ #ifndef _SFX
+ NWindows::NControl::CEdit _pathName;
+ NWindows::NControl::CEdit _passwordControl;
+ NWindows::NControl::CComboBox _pathMode;
+ NWindows::NControl::CComboBox _overwriteMode;
+ #endif
+
+ #ifndef _SFX
+ // int GetFilesMode() const;
+ void UpdatePasswordControl();
+ #endif
+
+ void OnButtonSetPath();
+
+ void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2);
+ void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2);
+ virtual bool OnInit();
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ virtual void OnOK();
+
+ #ifndef NO_REGISTRY
+
+ virtual void OnHelp();
+
+ NExtract::CInfo _info;
+
+ #endif
+
+ bool IsShowPasswordChecked() const { return IsButtonCheckedBool(IDX_PASSWORD_SHOW); }
+public:
+ // bool _enableSelectedFilesButton;
+ // bool _enableFilesButton;
+ // NExtractionDialog::NFilesMode::EEnum FilesMode;
+
+ UString DirPath;
+ UString ArcPath;
+
+ #ifndef _SFX
+ UString Password;
+ #endif
+ bool PathMode_Force;
+ bool OverwriteMode_Force;
+ NExtract::NPathMode::EEnum PathMode;
+ NExtract::NOverwriteMode::EEnum OverwriteMode;
+
+ #ifndef _SFX
+ // CBoolPair AltStreams;
+ CBoolPair NtSecurity;
+ #endif
+
+ CBoolPair ElimDup;
+
+ INT_PTR Create(HWND aWndParent = 0)
+ {
+ #ifdef _SFX
+ BIG_DIALOG_SIZE(240, 64);
+ #else
+ BIG_DIALOG_SIZE(300, 160);
+ #endif
+ return CModalDialog::Create(SIZED_DIALOG(IDD_EXTRACT), aWndParent);
+ }
+
+ CExtractDialog():
+ PathMode_Force(false),
+ OverwriteMode_Force(false)
+ {
+ ElimDup.Val = true;
+ }
+
+};
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.rc b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.rc
new file mode 100644
index 0000000000..f5d65281cb
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.rc
@@ -0,0 +1,98 @@
+#include "ExtractDialogRes.h"
+#include "../../GuiCommon.rc"
+
+#define xc 336
+#define yc 168
+
+#undef g1xs
+#undef g2x
+#undef g2x2
+#undef g2xs
+#undef g2xs2
+
+#define g1xs 160
+
+#define gSpace 20
+#define g2x (m + g1xs + gSpace)
+#define g2x2 (g2x + m)
+#define g2xs (xc - g1xs - gSpace)
+#define g2xs2 (g2xs - m - m)
+
+#undef GROUP_Y_SIZE
+#ifdef UNDER_CE
+#define GROUP_Y_SIZE 8
+#else
+#define GROUP_Y_SIZE 56
+#endif
+
+IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+CAPTION "Extract"
+BEGIN
+ LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8
+ COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 12, 100, MY_COMBO_WITH_EDIT
+ PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 2, bxsDots, bys, WS_GROUP
+
+ CONTROL "", IDX_EXTRACT_NAME_ENABLE, MY_CHECKBOX, m, m + 34, 12, 10
+ EDITTEXT IDE_EXTRACT_NAME, m + 12 + 2, m + 32, g1xs - 12 - 2, 14, ES_AUTOHSCROLL
+
+ LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 52, g1xs, 8
+ COMBOBOX IDC_EXTRACT_PATH_MODE, m, m + 64, g1xs, 140, MY_COMBO
+
+ CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX,
+ m, m + 84, g1xs, 10
+
+ LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 104, g1xs, 8
+ COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m, m + 116, g1xs, 140, MY_COMBO
+
+
+ GROUPBOX "Password", IDG_PASSWORD, g2x, m + 36, g2xs, GROUP_Y_SIZE
+ EDITTEXT IDE_EXTRACT_PASSWORD, g2x2, m + 50, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, g2x2, m + 72, g2xs2, 10
+
+// CONTROL "Restore alternate data streams", IDX_EXTRACT_ALT_STREAMS, MY_CHECKBOX,
+// g2x, m + 104, g2xs, 10
+ CONTROL "Restore file security", IDX_EXTRACT_NT_SECUR, MY_CHECKBOX,
+ g2x, m + 104, g2xs, 10
+
+ DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, bx2, by, bxs, bys
+ PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys
+END
+
+
+#ifdef UNDER_CE
+
+#undef m
+#define m 4
+
+#undef xc
+#undef yc
+
+#define xc 152
+#define yc 128
+
+#undef g1xs
+
+#define g1xs 64
+
+IDD_EXTRACT_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
+CAPTION "Extract"
+BEGIN
+ LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 8, 8
+ COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 8, 100, MY_COMBO_WITH_EDIT
+ PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 3, bxsDots, bys, WS_GROUP
+
+ LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8
+ COMBOBOX IDC_EXTRACT_PATH_MODE, m + g1xs, m + 36, xc - g1xs, 100, MY_COMBO
+
+ LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 56, g1xs, 8
+ COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m + g1xs, m + 56, xc - g1xs, 100, MY_COMBO
+
+ LTEXT "Password", IDG_PASSWORD, m, m + 76, g1xs, 8
+ EDITTEXT IDE_EXTRACT_PASSWORD, m + g1xs, m + 76, xc - g1xs, 14, ES_PASSWORD | ES_AUTOHSCROLL
+ CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, m + 92, xc, 10
+
+ OK_CANCEL
+END
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialogRes.h b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialogRes.h
new file mode 100644
index 0000000000..e198796aa5
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialogRes.h
@@ -0,0 +1,24 @@
+#define IDD_EXTRACT 3400
+#define IDD_EXTRACT_2 13400
+
+#define IDC_EXTRACT_PATH 100
+#define IDB_EXTRACT_SET_PATH 101
+#define IDC_EXTRACT_PATH_MODE 102
+#define IDC_EXTRACT_OVERWRITE_MODE 103
+
+#define IDE_EXTRACT_PASSWORD 120
+
+#define IDE_EXTRACT_NAME 130
+#define IDX_EXTRACT_NAME_ENABLE 131
+
+
+#define IDT_EXTRACT_EXTRACT_TO 3401
+#define IDT_EXTRACT_PATH_MODE 3410
+#define IDT_EXTRACT_OVERWRITE_MODE 3420
+
+#define IDX_EXTRACT_ELIM_DUP 3430
+#define IDX_EXTRACT_NT_SECUR 3431
+// #define IDX_EXTRACT_ALT_STREAMS 3432
+
+#define IDX_PASSWORD_SHOW 3803
+#define IDG_PASSWORD 3807
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.cpp b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.cpp
new file mode 100644
index 0000000000..37aa45b3f4
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.cpp
@@ -0,0 +1,278 @@
+// ExtractGUI.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/Thread.h"
+
+#include "../FileManager/ExtractCallback.h"
+#include "../FileManager/FormatUtils.h"
+#include "../FileManager/LangUtils.h"
+#include "../FileManager/resourceGui.h"
+#include "../FileManager/OverwriteDialogRes.h"
+
+#include "../Common/ArchiveExtractCallback.h"
+#include "../Common/PropIDUtils.h"
+
+#include "../Explorer/MyMessages.h"
+
+#include "resource2.h"
+#include "ExtractRes.h"
+
+#include "ExtractDialog.h"
+#include "ExtractGUI.h"
+#include "HashGUI.h"
+
+#include "../FileManager/PropertyNameRes.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+static const wchar_t * const kIncorrectOutDir = L"Incorrect output directory path";
+
+#ifndef _SFX
+
+static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true)
+{
+ AddLangString(s, resourceID);
+ if (addColon)
+ s += ':';
+ s.Add_Space();
+ char sz[32];
+ ConvertUInt64ToString(value, sz);
+ s += sz;
+ s.Add_LF();
+}
+
+static void AddSizePair(UString &s, UINT resourceID, UInt64 value)
+{
+ AddLangString(s, resourceID);
+ s += ": ";
+ AddSizeValue(s, value);
+ s.Add_LF();
+}
+
+#endif
+
+class CThreadExtracting: public CProgressThreadVirt
+{
+ HRESULT ProcessVirt();
+public:
+ CCodecs *codecs;
+ CExtractCallbackImp *ExtractCallbackSpec;
+ const CObjectVector<COpenType> *FormatIndices;
+ const CIntVector *ExcludedFormatIndices;
+
+ UStringVector *ArchivePaths;
+ UStringVector *ArchivePathsFull;
+ const NWildcard::CCensorNode *WildcardCensor;
+ const CExtractOptions *Options;
+
+ #ifndef _SFX
+ CHashBundle *HashBundle;
+ virtual void ProcessWasFinished_GuiVirt();
+ #endif
+
+ CMyComPtr<IExtractCallbackUI> ExtractCallback;
+ UString Title;
+
+ CPropNameValPairs Pairs;
+};
+
+
+#ifndef _SFX
+void CThreadExtracting::ProcessWasFinished_GuiVirt()
+{
+ if (HashBundle && !Pairs.IsEmpty())
+ ShowHashResults(Pairs, *this);
+}
+#endif
+
+HRESULT CThreadExtracting::ProcessVirt()
+{
+ CDecompressStat Stat;
+
+ #ifndef _SFX
+ if (HashBundle)
+ HashBundle->Init();
+ #endif
+
+ HRESULT res = Extract(codecs,
+ *FormatIndices, *ExcludedFormatIndices,
+ *ArchivePaths, *ArchivePathsFull,
+ *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback,
+ #ifndef _SFX
+ HashBundle,
+ #endif
+ FinalMessage.ErrorMessage.Message, Stat);
+
+ #ifndef _SFX
+ if (res == S_OK && ExtractCallbackSpec->IsOK())
+ {
+ if (HashBundle)
+ {
+ AddValuePair(Pairs, IDS_ARCHIVES_COLON, Stat.NumArchives);
+ AddSizeValuePair(Pairs, IDS_PROP_PACKED_SIZE, Stat.PackSize);
+ AddHashBundleRes(Pairs, *HashBundle, UString());
+ }
+ else if (Options->TestMode)
+ {
+ UString s;
+
+ AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false);
+ AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize);
+
+ if (Stat.NumFolders != 0)
+ AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders);
+ AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles);
+ AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize);
+ if (Stat.NumAltStreams != 0)
+ {
+ s.Add_LF();
+ AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams);
+ AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize);
+ }
+ s.Add_LF();
+ AddLangString(s, IDS_MESSAGE_NO_ERRORS);
+ FinalMessage.OkMessage.Title = Title;
+ FinalMessage.OkMessage.Message = s;
+ }
+ }
+ #endif
+
+ return res;
+}
+
+
+
+HRESULT ExtractGUI(
+ CCodecs *codecs,
+ const CObjectVector<COpenType> &formatIndices,
+ const CIntVector &excludedFormatIndices,
+ UStringVector &archivePaths,
+ UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ CExtractOptions &options,
+ #ifndef _SFX
+ CHashBundle *hb,
+ #endif
+ bool showDialog,
+ bool &messageWasDisplayed,
+ CExtractCallbackImp *extractCallback,
+ HWND hwndParent)
+{
+ messageWasDisplayed = false;
+
+ CThreadExtracting extracter;
+ extracter.codecs = codecs;
+ extracter.FormatIndices = &formatIndices;
+ extracter.ExcludedFormatIndices = &excludedFormatIndices;
+
+ if (!options.TestMode)
+ {
+ FString outputDir = options.OutputDir;
+ #ifndef UNDER_CE
+ if (outputDir.IsEmpty())
+ GetCurrentDir(outputDir);
+ #endif
+ if (showDialog)
+ {
+ CExtractDialog dialog;
+ FString outputDirFull;
+ if (!MyGetFullPathName(outputDir, outputDirFull))
+ {
+ ShowErrorMessage(kIncorrectOutDir);
+ messageWasDisplayed = true;
+ return E_FAIL;
+ }
+ NName::NormalizeDirPathPrefix(outputDirFull);
+
+ dialog.DirPath = fs2us(outputDirFull);
+
+ dialog.OverwriteMode = options.OverwriteMode;
+ dialog.OverwriteMode_Force = options.OverwriteMode_Force;
+ dialog.PathMode = options.PathMode;
+ dialog.PathMode_Force = options.PathMode_Force;
+ dialog.ElimDup = options.ElimDup;
+
+ if (archivePathsFull.Size() == 1)
+ dialog.ArcPath = archivePathsFull[0];
+
+ #ifndef _SFX
+ // dialog.AltStreams = options.NtOptions.AltStreams;
+ dialog.NtSecurity = options.NtOptions.NtSecurity;
+ if (extractCallback->PasswordIsDefined)
+ dialog.Password = extractCallback->Password;
+ #endif
+
+ if (dialog.Create(hwndParent) != IDOK)
+ return E_ABORT;
+
+ outputDir = us2fs(dialog.DirPath);
+
+ options.OverwriteMode = dialog.OverwriteMode;
+ options.PathMode = dialog.PathMode;
+ options.ElimDup = dialog.ElimDup;
+
+ #ifndef _SFX
+ // options.NtOptions.AltStreams = dialog.AltStreams;
+ options.NtOptions.NtSecurity = dialog.NtSecurity;
+ extractCallback->Password = dialog.Password;
+ extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty();
+ #endif
+ }
+ if (!MyGetFullPathName(outputDir, options.OutputDir))
+ {
+ ShowErrorMessage(kIncorrectOutDir);
+ messageWasDisplayed = true;
+ return E_FAIL;
+ }
+ NName::NormalizeDirPathPrefix(options.OutputDir);
+
+ /*
+ if (!CreateComplexDirectory(options.OutputDir))
+ {
+ UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError()));
+ UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,
+ #ifdef LANG
+ 0x02000603,
+ #endif
+ options.OutputDir);
+ s2.Add_LF();
+ s2 += s;
+ MyMessageBox(s2);
+ return E_FAIL;
+ }
+ */
+ }
+
+ UString title = LangString(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING);
+
+ extracter.Title = title;
+ extracter.ExtractCallbackSpec = extractCallback;
+ extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
+ extracter.ExtractCallback = extractCallback;
+ extracter.ExtractCallbackSpec->Init();
+
+ extracter.CompressingMode = false;
+
+ extracter.ArchivePaths = &archivePaths;
+ extracter.ArchivePathsFull = &archivePathsFull;
+ extracter.WildcardCensor = &wildcardCensor;
+ extracter.Options = &options;
+ #ifndef _SFX
+ extracter.HashBundle = hb;
+ #endif
+
+ extracter.IconID = IDI_ICON;
+
+ RINOK(extracter.Create(title, hwndParent));
+ messageWasDisplayed = extracter.ThreadFinishedOK && extracter.MessagesDisplayed;
+ return extracter.Result;
+}
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.h b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.h
new file mode 100644
index 0000000000..466e524e0c
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.h
@@ -0,0 +1,38 @@
+// GUI/ExtractGUI.h
+
+#ifndef __EXTRACT_GUI_H
+#define __EXTRACT_GUI_H
+
+#include "../Common/Extract.h"
+
+#include "../FileManager/ExtractCallback.h"
+
+/*
+ RESULT can be S_OK, even if there are errors!!!
+ if RESULT == S_OK, check extractCallback->IsOK() after ExtractGUI().
+
+ RESULT = E_ABORT - user break.
+ RESULT != E_ABORT:
+ {
+ messageWasDisplayed = true - message was displayed already.
+ messageWasDisplayed = false - there was some internal error, so you must show error message.
+ }
+*/
+
+HRESULT ExtractGUI(
+ CCodecs *codecs,
+ const CObjectVector<COpenType> &formatIndices,
+ const CIntVector &excludedFormatIndices,
+ UStringVector &archivePaths,
+ UStringVector &archivePathsFull,
+ const NWildcard::CCensorNode &wildcardCensor,
+ CExtractOptions &options,
+ #ifndef _SFX
+ CHashBundle *hb,
+ #endif
+ bool showDialog,
+ bool &messageWasDisplayed,
+ CExtractCallbackImp *extractCallback,
+ HWND hwndParent = NULL);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractRes.h b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractRes.h
new file mode 100644
index 0000000000..6437d953f8
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractRes.h
@@ -0,0 +1,51 @@
+#define IDS_MEM_ERROR 3000
+
+#define IDS_CANNOT_CREATE_FOLDER 3003
+#define IDS_UPDATE_NOT_SUPPORTED 3004
+#define IDS_CANT_OPEN_ARCHIVE 3005
+#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
+#define IDS_EXTRACT_PATHS_NO 3412
+#define IDS_EXTRACT_PATHS_ABS 3413
+#define IDS_PATH_MODE_RELAT 3414
+
+#define IDS_EXTRACT_OVERWRITE_ASK 3421
+#define IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT 3422
+#define IDS_EXTRACT_OVERWRITE_SKIP_EXISTING 3423
+#define IDS_EXTRACT_OVERWRITE_RENAME 3424
+#define IDS_EXTRACT_OVERWRITE_RENAME_EXISTING 3425
+
+#define IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD 3700
+#define IDS_EXTRACT_MESSAGE_DATA_ERROR 3701
+#define IDS_EXTRACT_MESSAGE_CRC_ERROR 3702
+#define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED 3703
+#define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED 3704
+
+#define IDS_EXTRACT_MSG_WRONG_PSW_GUESS 3710
+// #define IDS_EXTRACT_MSG_ENCRYPTED 3711
+
+#define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD 3721
+#define IDS_EXTRACT_MSG_DATA_ERROR 3722
+#define IDS_EXTRACT_MSG_CRC_ERROR 3723
+#define IDS_EXTRACT_MSG_UNAVAILABLE_DATA 3724
+#define IDS_EXTRACT_MSG_UEXPECTED_END 3725
+#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
+#define IDS_OPEN_MSG_UNSUPPORTED_FEATURE 3768
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/HashGUI.h b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/HashGUI.h
new file mode 100644
index 0000000000..d6caa53e5b
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/HashGUI.h
@@ -0,0 +1,27 @@
+// HashGUI.h
+
+#ifndef __HASH_GUI_H
+#define __HASH_GUI_H
+
+#include "../Common/HashCalc.h"
+#include "../Common/Property.h"
+
+HRESULT HashCalcGUI(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const NWildcard::CCensor &censor,
+ const CHashOptions &options,
+ bool &messageWasDisplayed);
+
+typedef CObjectVector<CProperty> CPropNameValPairs;
+
+void AddValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value);
+void AddSizeValue(UString &s, UInt64 value);
+void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value);
+
+void AddHashBundleRes(CPropNameValPairs &s, const CHashBundle &hb, const UString &firstFileName);
+void AddHashBundleRes(UString &s, const CHashBundle &hb, const UString &firstFileName);
+
+void ShowHashResults(const CPropNameValPairs &propPairs, HWND hwnd);
+void ShowHashResults(const CHashBundle &hb, const UString &firstFileName, HWND hwnd);
+
+#endif
diff --git a/other-licenses/7zstub/src/CPP/7zip/UI/GUI/resource2.h b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/resource2.h
new file mode 100644
index 0000000000..152e71f8a6
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/7zip/UI/GUI/resource2.h
@@ -0,0 +1,2 @@
+#define IDS_PROGRESS_COMPRESSING 3301
+#define IDS_ARCHIVES_COLON 3907