From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- other-licenses/7zstub/src/Asm/arm/7zCrcOpt.asm | 100 + other-licenses/7zstub/src/Asm/x86/7zAsm.asm | 147 + other-licenses/7zstub/src/Asm/x86/7zCrcOpt.asm | 147 + other-licenses/7zstub/src/Asm/x86/AesOpt.asm | 237 ++ other-licenses/7zstub/src/Asm/x86/LzmaDecOpt.asm | 1258 +++++++ other-licenses/7zstub/src/Asm/x86/XzCrc64Opt.asm | 205 ++ other-licenses/7zstub/src/C/7z.h | 202 ++ other-licenses/7zstub/src/C/7zAlloc.c | 80 + other-licenses/7zstub/src/C/7zAlloc.h | 19 + other-licenses/7zstub/src/C/7zArcIn.c | 1771 ++++++++++ other-licenses/7zstub/src/C/7zBuf.c | 36 + other-licenses/7zstub/src/C/7zBuf.h | 35 + other-licenses/7zstub/src/C/7zBuf2.c | 52 + other-licenses/7zstub/src/C/7zCrc.c | 128 + other-licenses/7zstub/src/C/7zCrc.h | 25 + other-licenses/7zstub/src/C/7zCrcOpt.c | 115 + other-licenses/7zstub/src/C/7zDec.c | 591 ++++ other-licenses/7zstub/src/C/7zFile.c | 286 ++ other-licenses/7zstub/src/C/7zFile.h | 83 + other-licenses/7zstub/src/C/7zStream.c | 176 + other-licenses/7zstub/src/C/7zTypes.h | 374 +++ other-licenses/7zstub/src/C/7zVersion.h | 27 + other-licenses/7zstub/src/C/7zVersion.rc | 55 + other-licenses/7zstub/src/C/Aes.c | 306 ++ other-licenses/7zstub/src/C/Aes.h | 38 + other-licenses/7zstub/src/C/AesOpt.c | 184 + other-licenses/7zstub/src/C/Alloc.c | 455 +++ other-licenses/7zstub/src/C/Alloc.h | 51 + other-licenses/7zstub/src/C/Bcj2.c | 257 ++ other-licenses/7zstub/src/C/Bcj2.h | 146 + other-licenses/7zstub/src/C/Bcj2Enc.c | 311 ++ other-licenses/7zstub/src/C/Bra.c | 230 ++ other-licenses/7zstub/src/C/Bra.h | 64 + other-licenses/7zstub/src/C/Bra86.c | 82 + other-licenses/7zstub/src/C/BraIA64.c | 53 + other-licenses/7zstub/src/C/Compiler.h | 33 + other-licenses/7zstub/src/C/CpuArch.c | 200 ++ other-licenses/7zstub/src/C/CpuArch.h | 335 ++ other-licenses/7zstub/src/C/Delta.c | 64 + other-licenses/7zstub/src/C/Delta.h | 19 + other-licenses/7zstub/src/C/DllSecur.c | 87 + other-licenses/7zstub/src/C/DllSecur.h | 19 + other-licenses/7zstub/src/C/LzFind.c | 1069 ++++++ other-licenses/7zstub/src/C/LzFind.h | 121 + other-licenses/7zstub/src/C/LzFindMt.c | 820 +++++ other-licenses/7zstub/src/C/LzFindMt.h | 101 + other-licenses/7zstub/src/C/LzHash.h | 57 + other-licenses/7zstub/src/C/Lzma2Dec.c | 488 +++ other-licenses/7zstub/src/C/Lzma2Dec.h | 120 + other-licenses/7zstub/src/C/Lzma2DecMt.c | 1082 ++++++ other-licenses/7zstub/src/C/Lzma2DecMt.h | 79 + other-licenses/7zstub/src/C/Lzma2Enc.c | 803 +++++ other-licenses/7zstub/src/C/Lzma2Enc.h | 55 + other-licenses/7zstub/src/C/Lzma86.h | 111 + other-licenses/7zstub/src/C/Lzma86Dec.c | 54 + other-licenses/7zstub/src/C/Lzma86Enc.c | 106 + other-licenses/7zstub/src/C/LzmaDec.c | 1185 +++++++ other-licenses/7zstub/src/C/LzmaDec.h | 234 ++ other-licenses/7zstub/src/C/LzmaEnc.c | 2787 +++++++++++++++ other-licenses/7zstub/src/C/LzmaEnc.h | 76 + other-licenses/7zstub/src/C/LzmaLib.c | 40 + other-licenses/7zstub/src/C/LzmaLib.h | 131 + other-licenses/7zstub/src/C/MtCoder.c | 601 ++++ other-licenses/7zstub/src/C/MtCoder.h | 141 + other-licenses/7zstub/src/C/MtDec.c | 1137 +++++++ other-licenses/7zstub/src/C/MtDec.h | 201 ++ other-licenses/7zstub/src/C/Ppmd.h | 85 + other-licenses/7zstub/src/C/Ppmd7.c | 712 ++++ other-licenses/7zstub/src/C/Ppmd7.h | 142 + other-licenses/7zstub/src/C/Ppmd7Dec.c | 191 ++ other-licenses/7zstub/src/C/Ppmd7Enc.c | 187 ++ other-licenses/7zstub/src/C/Precomp.h | 10 + other-licenses/7zstub/src/C/RotateDefs.h | 30 + other-licenses/7zstub/src/C/Sha256.c | 248 ++ other-licenses/7zstub/src/C/Sha256.h | 26 + other-licenses/7zstub/src/C/Sort.c | 141 + other-licenses/7zstub/src/C/Sort.h | 18 + other-licenses/7zstub/src/C/Threads.c | 95 + other-licenses/7zstub/src/C/Threads.h | 68 + other-licenses/7zstub/src/C/Util/7z/7z.dsp | 241 ++ other-licenses/7zstub/src/C/Util/7z/7z.dsw | 29 + other-licenses/7zstub/src/C/Util/7z/7zMain.c | 686 ++++ other-licenses/7zstub/src/C/Util/7z/Precomp.c | 4 + other-licenses/7zstub/src/C/Util/7z/Precomp.h | 10 + other-licenses/7zstub/src/C/Util/7z/makefile | 40 + other-licenses/7zstub/src/C/Util/7z/makefile.gcc | 75 + other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.c | 258 ++ other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsp | 168 + other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsw | 29 + other-licenses/7zstub/src/C/Util/Lzma/makefile | 28 + other-licenses/7zstub/src/C/Util/Lzma/makefile.gcc | 44 + .../7zstub/src/C/Util/LzmaLib/LzmaLib.def | 4 + .../7zstub/src/C/Util/LzmaLib/LzmaLib.dsp | 178 + .../7zstub/src/C/Util/LzmaLib/LzmaLib.dsw | 29 + .../7zstub/src/C/Util/LzmaLib/LzmaLibExports.c | 14 + other-licenses/7zstub/src/C/Util/LzmaLib/makefile | 34 + .../7zstub/src/C/Util/LzmaLib/resource.rc | 3 + .../7zstub/src/C/Util/SfxSetup/Precomp.c | 4 + .../7zstub/src/C/Util/SfxSetup/Precomp.h | 10 + .../7zstub/src/C/Util/SfxSetup/SfxSetup.c | 640 ++++ .../7zstub/src/C/Util/SfxSetup/SfxSetup.dsp | 231 ++ .../7zstub/src/C/Util/SfxSetup/SfxSetup.dsw | 29 + other-licenses/7zstub/src/C/Util/SfxSetup/makefile | 37 + .../7zstub/src/C/Util/SfxSetup/makefile_con | 38 + .../7zstub/src/C/Util/SfxSetup/resource.rc | 5 + .../7zstub/src/C/Util/SfxSetup/setup.ico | Bin 0 -> 1078 bytes other-licenses/7zstub/src/C/Xz.c | 90 + other-licenses/7zstub/src/C/Xz.h | 460 +++ other-licenses/7zstub/src/C/XzCrc64.c | 86 + other-licenses/7zstub/src/C/XzCrc64.h | 26 + other-licenses/7zstub/src/C/XzCrc64Opt.c | 69 + other-licenses/7zstub/src/C/XzDec.c | 2773 +++++++++++++++ other-licenses/7zstub/src/C/XzEnc.c | 1329 ++++++++ other-licenses/7zstub/src/C/XzEnc.h | 60 + other-licenses/7zstub/src/C/XzIn.c | 319 ++ other-licenses/7zstub/src/CPP/7zip/7zip.mak | 240 ++ other-licenses/7zstub/src/CPP/7zip/Aes.mak | 7 + .../src/CPP/7zip/Archive/7z/7zCompressionMode.cpp | 3 + .../src/CPP/7zip/Archive/7z/7zCompressionMode.h | 76 + .../7zstub/src/CPP/7zip/Archive/7z/7zDecode.cpp | 567 ++++ .../7zstub/src/CPP/7zip/Archive/7z/7zDecode.h | 70 + .../7zstub/src/CPP/7zip/Archive/7z/7zEncode.cpp | 678 ++++ .../7zstub/src/CPP/7zip/Archive/7z/7zEncode.h | 92 + .../7zstub/src/CPP/7zip/Archive/7z/7zExtract.cpp | 423 +++ .../src/CPP/7zip/Archive/7z/7zFolderInStream.cpp | 139 + .../src/CPP/7zip/Archive/7z/7zFolderInStream.h | 61 + .../7zstub/src/CPP/7zip/Archive/7z/7zHandler.cpp | 756 +++++ .../7zstub/src/CPP/7zip/Archive/7z/7zHandler.h | 181 + .../src/CPP/7zip/Archive/7z/7zHandlerOut.cpp | 939 ++++++ .../7zstub/src/CPP/7zip/Archive/7z/7zHeader.cpp | 19 + .../7zstub/src/CPP/7zip/Archive/7z/7zHeader.h | 148 + .../7zstub/src/CPP/7zip/Archive/7z/7zIn.cpp | 1663 +++++++++ .../7zstub/src/CPP/7zip/Archive/7z/7zIn.h | 435 +++ .../7zstub/src/CPP/7zip/Archive/7z/7zItem.h | 202 ++ .../7zstub/src/CPP/7zip/Archive/7z/7zOut.cpp | 901 +++++ .../7zstub/src/CPP/7zip/Archive/7z/7zOut.h | 335 ++ .../src/CPP/7zip/Archive/7z/7zProperties.cpp | 174 + .../7zstub/src/CPP/7zip/Archive/7z/7zProperties.h | 22 + .../7zstub/src/CPP/7zip/Archive/7z/7zRegister.cpp | 21 + .../src/CPP/7zip/Archive/7z/7zSpecStream.cpp | 22 + .../7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.h | 35 + .../7zstub/src/CPP/7zip/Archive/7z/7zUpdate.cpp | 2497 ++++++++++++++ .../7zstub/src/CPP/7zip/Archive/7z/7zUpdate.h | 139 + .../7zstub/src/CPP/7zip/Archive/7z/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/Archive/7z/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Archive/Archive.def | 12 + .../7zstub/src/CPP/7zip/Archive/Archive2.def | 19 + .../7zstub/src/CPP/7zip/Archive/ArchiveExports.cpp | 151 + .../src/CPP/7zip/Archive/Common/CoderMixer2.cpp | 1124 +++++++ .../src/CPP/7zip/Archive/Common/CoderMixer2.h | 447 +++ .../src/CPP/7zip/Archive/Common/DummyOutStream.cpp | 17 + .../src/CPP/7zip/Archive/Common/DummyOutStream.h | 25 + .../src/CPP/7zip/Archive/Common/HandlerOut.cpp | 232 ++ .../src/CPP/7zip/Archive/Common/HandlerOut.h | 110 + .../CPP/7zip/Archive/Common/InStreamWithCRC.cpp | 46 + .../src/CPP/7zip/Archive/Common/InStreamWithCRC.h | 67 + .../src/CPP/7zip/Archive/Common/ItemNameUtils.cpp | 88 + .../src/CPP/7zip/Archive/Common/ItemNameUtils.h | 28 + .../src/CPP/7zip/Archive/Common/MultiStream.cpp | 191 ++ .../src/CPP/7zip/Archive/Common/MultiStream.h | 89 + .../CPP/7zip/Archive/Common/OutStreamWithCRC.cpp | 18 + .../src/CPP/7zip/Archive/Common/OutStreamWithCRC.h | 37 + .../CPP/7zip/Archive/Common/ParseProperties.cpp | 3 + .../src/CPP/7zip/Archive/Common/ParseProperties.h | 6 + .../7zstub/src/CPP/7zip/Archive/Common/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Archive/DllExports2.cpp | 122 + .../7zstub/src/CPP/7zip/Archive/IArchive.h | 608 ++++ .../7zstub/src/CPP/7zip/Archive/Icons/7z.ico | Bin 0 -> 4710 bytes .../7zstub/src/CPP/7zip/Archive/LzmaHandler.cpp | 605 ++++ .../7zstub/src/CPP/7zip/Archive/SplitHandler.cpp | 359 ++ .../7zstub/src/CPP/7zip/Archive/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Archive/XzHandler.cpp | 1308 ++++++++ .../7zstub/src/CPP/7zip/Archive/XzHandler.h | 11 + other-licenses/7zstub/src/CPP/7zip/Asm.mak | 9 + .../7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsp | 1901 +++++++++++ .../7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsw | 29 + .../7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Bundles/Alone7z/makefile | 158 + .../src/CPP/7zip/Bundles/Alone7z/resource.rc | 7 + .../CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp | 3 + .../src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h | 8 + .../src/CPP/7zip/Bundles/Format7zExtractR/makefile | 96 + .../CPP/7zip/Bundles/Format7zExtractR/resource.rc | 5 + .../src/CPP/7zip/Bundles/Format7zR/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Bundles/Format7zR/makefile | 116 + .../src/CPP/7zip/Bundles/Format7zR/resource.rc | 5 + .../src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp | 799 +++++ .../src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp | 477 +++ .../src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw | 29 + .../7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile | 59 + .../src/CPP/7zip/Bundles/LzmaCon/makefile.gcc | 195 ++ .../src/CPP/7zip/Bundles/LzmaCon/resource.rc | 3 + .../src/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp | 715 ++++ .../7zstub/src/CPP/7zip/Bundles/SFXCon/7z.ico | Bin 0 -> 1078 bytes .../7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsp | 912 +++++ .../7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsw | 29 + .../7zstub/src/CPP/7zip/Bundles/SFXCon/SfxCon.cpp | 482 +++ .../7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Bundles/SFXCon/makefile | 135 + .../7zstub/src/CPP/7zip/Bundles/SFXCon/resource.rc | 5 + .../7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp | 246 ++ .../CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h | 86 + .../CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp | 137 + .../src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h | 11 + .../src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp | 803 +++++ .../src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw | 29 + .../src/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp | 875 +++++ .../src/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.h | 13 + .../7zstub/src/CPP/7zip/Bundles/SFXSetup/makefile | 117 + .../src/CPP/7zip/Bundles/SFXSetup/resource.h | 8 + .../src/CPP/7zip/Bundles/SFXSetup/resource.rc | 18 + .../7zstub/src/CPP/7zip/Bundles/SFXSetup/setup.ico | Bin 0 -> 1078 bytes .../7zstub/src/CPP/7zip/Bundles/SFXWin/7z.ico | Bin 0 -> 1078 bytes .../7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsp | 988 ++++++ .../7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsw | 29 + .../7zstub/src/CPP/7zip/Bundles/SFXWin/SfxWin.cpp | 241 ++ .../7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.h | 14 + .../7zstub/src/CPP/7zip/Bundles/SFXWin/makefile | 153 + .../7zstub/src/CPP/7zip/Bundles/SFXWin/resource.h | 1 + .../7zstub/src/CPP/7zip/Bundles/SFXWin/resource.rc | 50 + .../7zstub/src/CPP/7zip/Common/CWrappers.cpp | 250 ++ .../7zstub/src/CPP/7zip/Common/CWrappers.h | 120 + .../7zstub/src/CPP/7zip/Common/CreateCoder.cpp | 536 +++ .../7zstub/src/CPP/7zip/Common/CreateCoder.h | 192 ++ .../src/CPP/7zip/Common/FilePathAutoRename.cpp | 46 + .../src/CPP/7zip/Common/FilePathAutoRename.h | 10 + .../7zstub/src/CPP/7zip/Common/FileStreams.cpp | 475 +++ .../7zstub/src/CPP/7zip/Common/FileStreams.h | 166 + .../7zstub/src/CPP/7zip/Common/FilterCoder.cpp | 418 +++ .../7zstub/src/CPP/7zip/Common/FilterCoder.h | 235 ++ .../7zstub/src/CPP/7zip/Common/InBuffer.cpp | 163 + .../7zstub/src/CPP/7zip/Common/InBuffer.h | 92 + .../7zstub/src/CPP/7zip/Common/InOutTempBuffer.cpp | 127 + .../7zstub/src/CPP/7zip/Common/InOutTempBuffer.h | 48 + .../7zstub/src/CPP/7zip/Common/LimitedStreams.cpp | 367 ++ .../7zstub/src/CPP/7zip/Common/LimitedStreams.h | 252 ++ .../7zstub/src/CPP/7zip/Common/LockedStream.cpp | 3 + .../7zstub/src/CPP/7zip/Common/LockedStream.h | 6 + .../7zstub/src/CPP/7zip/Common/MethodId.cpp | 3 + .../7zstub/src/CPP/7zip/Common/MethodId.h | 10 + .../7zstub/src/CPP/7zip/Common/MethodProps.cpp | 509 +++ .../7zstub/src/CPP/7zip/Common/MethodProps.h | 264 ++ .../7zstub/src/CPP/7zip/Common/OffsetStream.cpp | 39 + .../7zstub/src/CPP/7zip/Common/OffsetStream.h | 26 + .../7zstub/src/CPP/7zip/Common/OutBuffer.cpp | 111 + .../7zstub/src/CPP/7zip/Common/OutBuffer.h | 66 + .../7zstub/src/CPP/7zip/Common/ProgressUtils.cpp | 51 + .../7zstub/src/CPP/7zip/Common/ProgressUtils.h | 35 + .../7zstub/src/CPP/7zip/Common/PropId.cpp | 108 + .../7zstub/src/CPP/7zip/Common/RegisterArc.h | 78 + .../7zstub/src/CPP/7zip/Common/RegisterCodec.h | 106 + other-licenses/7zstub/src/CPP/7zip/Common/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Common/StreamBinder.cpp | 156 + .../7zstub/src/CPP/7zip/Common/StreamBinder.h | 60 + .../7zstub/src/CPP/7zip/Common/StreamObjects.cpp | 285 ++ .../7zstub/src/CPP/7zip/Common/StreamObjects.h | 157 + .../7zstub/src/CPP/7zip/Common/StreamUtils.cpp | 56 + .../7zstub/src/CPP/7zip/Common/StreamUtils.h | 13 + .../7zstub/src/CPP/7zip/Common/UniqBlocks.cpp | 57 + .../7zstub/src/CPP/7zip/Common/UniqBlocks.h | 26 + .../7zstub/src/CPP/7zip/Common/VirtThread.cpp | 48 + .../7zstub/src/CPP/7zip/Common/VirtThread.h | 24 + .../7zstub/src/CPP/7zip/Compress/Bcj2Coder.cpp | 666 ++++ .../7zstub/src/CPP/7zip/Compress/Bcj2Coder.h | 120 + .../7zstub/src/CPP/7zip/Compress/Bcj2Register.cpp | 24 + .../7zstub/src/CPP/7zip/Compress/BcjCoder.cpp | 24 + .../7zstub/src/CPP/7zip/Compress/BcjCoder.h | 31 + .../7zstub/src/CPP/7zip/Compress/BcjRegister.cpp | 17 + .../7zstub/src/CPP/7zip/Compress/BranchMisc.cpp | 23 + .../7zstub/src/CPP/7zip/Compress/BranchMisc.h | 35 + .../src/CPP/7zip/Compress/BranchRegister.cpp | 41 + .../7zstub/src/CPP/7zip/Compress/ByteSwap.cpp | 92 + .../7zstub/src/CPP/7zip/Compress/CodecExports.cpp | 344 ++ .../7zstub/src/CPP/7zip/Compress/CopyCoder.cpp | 120 + .../7zstub/src/CPP/7zip/Compress/CopyCoder.h | 49 + .../7zstub/src/CPP/7zip/Compress/CopyRegister.cpp | 15 + .../7zstub/src/CPP/7zip/Compress/DeltaFilter.cpp | 128 + .../7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp | 265 ++ .../7zstub/src/CPP/7zip/Compress/Lzma2Decoder.h | 96 + .../7zstub/src/CPP/7zip/Compress/Lzma2Encoder.cpp | 122 + .../7zstub/src/CPP/7zip/Compress/Lzma2Encoder.h | 42 + .../7zstub/src/CPP/7zip/Compress/Lzma2Register.cpp | 22 + .../7zstub/src/CPP/7zip/Compress/LzmaDecoder.cpp | 343 ++ .../7zstub/src/CPP/7zip/Compress/LzmaDecoder.h | 113 + .../7zstub/src/CPP/7zip/Compress/LzmaEncoder.cpp | 182 + .../7zstub/src/CPP/7zip/Compress/LzmaEncoder.h | 46 + .../7zstub/src/CPP/7zip/Compress/LzmaRegister.cpp | 22 + .../7zstub/src/CPP/7zip/Compress/PpmdDecoder.cpp | 170 + .../7zstub/src/CPP/7zip/Compress/PpmdDecoder.h | 86 + .../7zstub/src/CPP/7zip/Compress/PpmdEncoder.cpp | 152 + .../7zstub/src/CPP/7zip/Compress/PpmdEncoder.h | 58 + .../7zstub/src/CPP/7zip/Compress/PpmdRegister.cpp | 22 + .../7zstub/src/CPP/7zip/Compress/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/Compress/XzDecoder.cpp | 150 + .../7zstub/src/CPP/7zip/Compress/XzDecoder.h | 92 + .../7zstub/src/CPP/7zip/Compress/XzEncoder.cpp | 245 ++ .../7zstub/src/CPP/7zip/Compress/XzEncoder.h | 46 + other-licenses/7zstub/src/CPP/7zip/Crc.mak | 8 + other-licenses/7zstub/src/CPP/7zip/Crc64.mak | 8 + .../7zstub/src/CPP/7zip/Crypto/7zAes.cpp | 280 ++ other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.h | 118 + .../7zstub/src/CPP/7zip/Crypto/7zAesRegister.cpp | 17 + .../7zstub/src/CPP/7zip/Crypto/MyAes.cpp | 112 + other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.h | 57 + .../7zstub/src/CPP/7zip/Crypto/MyAesReg.cpp | 16 + .../7zstub/src/CPP/7zip/Crypto/RandGen.cpp | 124 + .../7zstub/src/CPP/7zip/Crypto/RandGen.h | 21 + other-licenses/7zstub/src/CPP/7zip/Crypto/StdAfx.h | 8 + other-licenses/7zstub/src/CPP/7zip/GuiCommon.rc | 84 + other-licenses/7zstub/src/CPP/7zip/Guid.txt | 220 ++ other-licenses/7zstub/src/CPP/7zip/ICoder.h | 399 +++ other-licenses/7zstub/src/CPP/7zip/IDecl.h | 28 + other-licenses/7zstub/src/CPP/7zip/IPassword.h | 23 + other-licenses/7zstub/src/CPP/7zip/IProgress.h | 19 + other-licenses/7zstub/src/CPP/7zip/IStream.h | 127 + other-licenses/7zstub/src/CPP/7zip/LzmaDec.mak | 5 + other-licenses/7zstub/src/CPP/7zip/MyVersion.h | 2 + .../7zstub/src/CPP/7zip/MyVersionInfo.rc | 2 + other-licenses/7zstub/src/CPP/7zip/PropID.h | 127 + other-licenses/7zstub/src/CPP/7zip/SubBuild.mak | 3 + .../7zstub/src/CPP/7zip/UI/Client7z/Client7z.cpp | 993 ++++++ .../7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsp | 235 ++ .../7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsw | 29 + .../7zstub/src/CPP/7zip/UI/Client7z/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/UI/Client7z/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/UI/Client7z/makefile | 28 + .../7zstub/src/CPP/7zip/UI/Client7z/resource.rc | 3 + .../src/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 1281 +++++++ .../src/CPP/7zip/UI/Common/ArchiveCommandLine.h | 136 + .../CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 1691 ++++++++++ .../CPP/7zip/UI/Common/ArchiveExtractCallback.h | 403 +++ .../7zstub/src/CPP/7zip/UI/Common/ArchiveName.cpp | 78 + .../7zstub/src/CPP/7zip/UI/Common/ArchiveName.h | 13 + .../src/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp | 154 + .../src/CPP/7zip/UI/Common/ArchiveOpenCallback.h | 112 + .../7zstub/src/CPP/7zip/UI/Common/Bench.cpp | 3492 +++++++++++++++++++ .../7zstub/src/CPP/7zip/UI/Common/Bench.h | 72 + .../7zstub/src/CPP/7zip/UI/Common/DefaultName.cpp | 37 + .../7zstub/src/CPP/7zip/UI/Common/DefaultName.h | 11 + .../7zstub/src/CPP/7zip/UI/Common/DirItem.h | 190 ++ .../7zstub/src/CPP/7zip/UI/Common/EnumDirItems.cpp | 1086 ++++++ .../7zstub/src/CPP/7zip/UI/Common/EnumDirItems.h | 41 + .../7zstub/src/CPP/7zip/UI/Common/ExitCode.h | 27 + .../7zstub/src/CPP/7zip/UI/Common/Extract.cpp | 482 +++ .../7zstub/src/CPP/7zip/UI/Common/Extract.h | 94 + .../7zstub/src/CPP/7zip/UI/Common/ExtractMode.h | 34 + .../src/CPP/7zip/UI/Common/ExtractingFilePath.cpp | 280 ++ .../src/CPP/7zip/UI/Common/ExtractingFilePath.h | 31 + .../7zstub/src/CPP/7zip/UI/Common/HashCalc.cpp | 347 ++ .../7zstub/src/CPP/7zip/UI/Common/HashCalc.h | 106 + .../src/CPP/7zip/UI/Common/IFileExtractCallback.h | 114 + .../7zstub/src/CPP/7zip/UI/Common/LoadCodecs.cpp | 1074 ++++++ .../7zstub/src/CPP/7zip/UI/Common/LoadCodecs.h | 424 +++ .../7zstub/src/CPP/7zip/UI/Common/OpenArchive.cpp | 3550 ++++++++++++++++++++ .../7zstub/src/CPP/7zip/UI/Common/OpenArchive.h | 436 +++ .../7zstub/src/CPP/7zip/UI/Common/PropIDUtils.cpp | 668 ++++ .../7zstub/src/CPP/7zip/UI/Common/PropIDUtils.h | 18 + .../7zstub/src/CPP/7zip/UI/Common/Property.h | 14 + .../src/CPP/7zip/UI/Common/SetProperties.cpp | 80 + .../7zstub/src/CPP/7zip/UI/Common/SetProperties.h | 10 + .../7zstub/src/CPP/7zip/UI/Common/SortUtils.cpp | 25 + .../7zstub/src/CPP/7zip/UI/Common/SortUtils.h | 10 + .../7zstub/src/CPP/7zip/UI/Common/StdAfx.h | 8 + .../7zstub/src/CPP/7zip/UI/Common/TempFiles.cpp | 19 + .../7zstub/src/CPP/7zip/UI/Common/TempFiles.h | 16 + .../7zstub/src/CPP/7zip/UI/Common/Update.cpp | 1667 +++++++++ .../7zstub/src/CPP/7zip/UI/Common/Update.h | 200 ++ .../7zstub/src/CPP/7zip/UI/Common/UpdateAction.cpp | 64 + .../7zstub/src/CPP/7zip/UI/Common/UpdateAction.h | 66 + .../src/CPP/7zip/UI/Common/UpdateCallback.cpp | 771 +++++ .../7zstub/src/CPP/7zip/UI/Common/UpdateCallback.h | 162 + .../7zstub/src/CPP/7zip/UI/Common/UpdatePair.cpp | 233 ++ .../7zstub/src/CPP/7zip/UI/Common/UpdatePair.h | 27 + .../src/CPP/7zip/UI/Common/UpdateProduce.cpp | 70 + .../7zstub/src/CPP/7zip/UI/Common/UpdateProduce.h | 55 + .../7zstub/src/CPP/7zip/UI/Common/WorkDir.cpp | 94 + .../7zstub/src/CPP/7zip/UI/Common/WorkDir.h | 26 + .../7zstub/src/CPP/7zip/UI/Common/ZipRegistry.h | 130 + .../7zstub/src/CPP/7zip/UI/Console/BenchCon.cpp | 41 + .../7zstub/src/CPP/7zip/UI/Console/BenchCon.h | 14 + .../7zstub/src/CPP/7zip/UI/Console/Console.mak | 36 + .../src/CPP/7zip/UI/Console/Console.manifest | 13 + .../src/CPP/7zip/UI/Console/ConsoleClose.cpp | 69 + .../7zstub/src/CPP/7zip/UI/Console/ConsoleClose.h | 33 + .../CPP/7zip/UI/Console/ExtractCallbackConsole.cpp | 825 +++++ .../CPP/7zip/UI/Console/ExtractCallbackConsole.h | 164 + .../7zstub/src/CPP/7zip/UI/Console/HashCon.cpp | 367 ++ .../7zstub/src/CPP/7zip/UI/Console/HashCon.h | 48 + .../7zstub/src/CPP/7zip/UI/Console/List.cpp | 1349 ++++++++ .../7zstub/src/CPP/7zip/UI/Console/List.h | 27 + .../7zstub/src/CPP/7zip/UI/Console/Main.cpp | 1151 +++++++ .../7zstub/src/CPP/7zip/UI/Console/MainAr.cpp | 167 + .../CPP/7zip/UI/Console/OpenCallbackConsole.cpp | 115 + .../src/CPP/7zip/UI/Console/OpenCallbackConsole.h | 66 + .../src/CPP/7zip/UI/Console/PercentPrinter.cpp | 183 + .../src/CPP/7zip/UI/Console/PercentPrinter.h | 62 + .../7zstub/src/CPP/7zip/UI/Console/StdAfx.cpp | 3 + .../7zstub/src/CPP/7zip/UI/Console/StdAfx.h | 8 + .../CPP/7zip/UI/Console/UpdateCallbackConsole.cpp | 702 ++++ .../CPP/7zip/UI/Console/UpdateCallbackConsole.h | 124 + .../src/CPP/7zip/UI/Console/UserInputUtils.cpp | 110 + .../src/CPP/7zip/UI/Console/UserInputUtils.h | 27 + .../7zstub/src/CPP/7zip/UI/Console/makefile | 69 + .../7zstub/src/CPP/7zip/UI/Console/resource.rc | 7 + .../7zstub/src/CPP/7zip/UI/Explorer/MyMessages.cpp | 37 + .../7zstub/src/CPP/7zip/UI/Explorer/MyMessages.h | 16 + .../src/CPP/7zip/UI/FileManager/BrowseDialog.cpp | 1025 ++++++ .../src/CPP/7zip/UI/FileManager/BrowseDialog.h | 21 + .../src/CPP/7zip/UI/FileManager/BrowseDialogRes.h | 9 + .../src/CPP/7zip/UI/FileManager/ComboDialog.cpp | 64 + .../src/CPP/7zip/UI/FileManager/ComboDialog.h | 28 + .../src/CPP/7zip/UI/FileManager/ComboDialogRes.h | 4 + .../src/CPP/7zip/UI/FileManager/DialogSize.h | 16 + .../CPP/7zip/UI/FileManager/ExtractCallback.cpp | 1033 ++++++ .../src/CPP/7zip/UI/FileManager/ExtractCallback.h | 328 ++ .../src/CPP/7zip/UI/FileManager/FormatUtils.cpp | 28 + .../src/CPP/7zip/UI/FileManager/FormatUtils.h | 14 + .../7zstub/src/CPP/7zip/UI/FileManager/LangUtils.h | 40 + .../src/CPP/7zip/UI/FileManager/MyWindowsNew.h | 76 + .../CPP/7zip/UI/FileManager/OverwriteDialog.cpp | 122 + .../src/CPP/7zip/UI/FileManager/OverwriteDialog.h | 69 + .../src/CPP/7zip/UI/FileManager/OverwriteDialog.rc | 91 + .../CPP/7zip/UI/FileManager/OverwriteDialogRes.h | 17 + .../src/CPP/7zip/UI/FileManager/PasswordDialog.cpp | 58 + .../src/CPP/7zip/UI/FileManager/PasswordDialog.h | 28 + .../src/CPP/7zip/UI/FileManager/PasswordDialog.rc | 14 + .../CPP/7zip/UI/FileManager/PasswordDialogRes.h | 5 + .../src/CPP/7zip/UI/FileManager/ProgressDialog.cpp | 197 ++ .../src/CPP/7zip/UI/FileManager/ProgressDialog.h | 170 + .../src/CPP/7zip/UI/FileManager/ProgressDialog.rc | 12 + .../CPP/7zip/UI/FileManager/ProgressDialog2.cpp | 1337 ++++++++ .../src/CPP/7zip/UI/FileManager/ProgressDialog2.h | 351 ++ .../src/CPP/7zip/UI/FileManager/ProgressDialog2.rc | 40 + .../CPP/7zip/UI/FileManager/ProgressDialog2Res.h | 48 + .../CPP/7zip/UI/FileManager/ProgressDialog2a.rc | 80 + .../CPP/7zip/UI/FileManager/ProgressDialogRes.h | 3 + .../src/CPP/7zip/UI/FileManager/PropertyName.cpp | 23 + .../src/CPP/7zip/UI/FileManager/PropertyName.h | 10 + .../src/CPP/7zip/UI/FileManager/PropertyNameRes.h | 95 + .../src/CPP/7zip/UI/FileManager/SysIconUtils.cpp | 255 ++ .../src/CPP/7zip/UI/FileManager/SysIconUtils.h | 62 + .../7zstub/src/CPP/7zip/UI/FileManager/resource.h | 177 + .../src/CPP/7zip/UI/FileManager/resourceGui.h | 15 + .../7zstub/src/CPP/7zip/UI/GUI/Extract.rc | 59 + .../7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.cpp | 418 +++ .../7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.h | 113 + .../7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.rc | 98 + .../7zstub/src/CPP/7zip/UI/GUI/ExtractDialogRes.h | 24 + .../7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.cpp | 278 ++ .../7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.h | 38 + .../7zstub/src/CPP/7zip/UI/GUI/ExtractRes.h | 51 + .../7zstub/src/CPP/7zip/UI/GUI/HashGUI.h | 27 + .../7zstub/src/CPP/7zip/UI/GUI/resource2.h | 2 + other-licenses/7zstub/src/CPP/Build.mak | 145 + other-licenses/7zstub/src/CPP/Common/AutoPtr.h | 35 + other-licenses/7zstub/src/CPP/Common/CRC.cpp | 7 + other-licenses/7zstub/src/CPP/Common/C_FileIO.cpp | 92 + other-licenses/7zstub/src/CPP/Common/C_FileIO.h | 53 + other-licenses/7zstub/src/CPP/Common/ComTry.h | 21 + .../7zstub/src/CPP/Common/CommandLineParser.cpp | 197 ++ .../7zstub/src/CPP/Common/CommandLineParser.h | 63 + other-licenses/7zstub/src/CPP/Common/Common.h | 43 + other-licenses/7zstub/src/CPP/Common/CrcReg.cpp | 98 + other-licenses/7zstub/src/CPP/Common/Defs.h | 15 + .../7zstub/src/CPP/Common/DynamicBuffer.h | 64 + .../7zstub/src/CPP/Common/IntToString.cpp | 193 ++ other-licenses/7zstub/src/CPP/Common/IntToString.h | 28 + other-licenses/7zstub/src/CPP/Common/Lang.h | 23 + .../7zstub/src/CPP/Common/ListFileUtils.cpp | 117 + .../7zstub/src/CPP/Common/ListFileUtils.h | 14 + other-licenses/7zstub/src/CPP/Common/MyBuffer.h | 259 ++ other-licenses/7zstub/src/CPP/Common/MyBuffer2.h | 45 + other-licenses/7zstub/src/CPP/Common/MyCom.h | 277 ++ other-licenses/7zstub/src/CPP/Common/MyException.h | 14 + other-licenses/7zstub/src/CPP/Common/MyGuidDef.h | 54 + other-licenses/7zstub/src/CPP/Common/MyInitGuid.h | 45 + other-licenses/7zstub/src/CPP/Common/MyLinux.h | 42 + other-licenses/7zstub/src/CPP/Common/MyString.cpp | 1659 +++++++++ other-licenses/7zstub/src/CPP/Common/MyString.h | 867 +++++ other-licenses/7zstub/src/CPP/Common/MyTypes.h | 35 + other-licenses/7zstub/src/CPP/Common/MyUnknown.h | 17 + other-licenses/7zstub/src/CPP/Common/MyVector.cpp | 3 + other-licenses/7zstub/src/CPP/Common/MyVector.h | 634 ++++ other-licenses/7zstub/src/CPP/Common/MyWindows.cpp | 145 + other-licenses/7zstub/src/CPP/Common/MyWindows.h | 231 ++ .../7zstub/src/CPP/Common/NewHandler.cpp | 163 + other-licenses/7zstub/src/CPP/Common/NewHandler.h | 88 + other-licenses/7zstub/src/CPP/Common/Sha256Reg.cpp | 40 + other-licenses/7zstub/src/CPP/Common/StdAfx.h | 8 + .../7zstub/src/CPP/Common/StdInStream.cpp | 89 + other-licenses/7zstub/src/CPP/Common/StdInStream.h | 38 + .../7zstub/src/CPP/Common/StdOutStream.cpp | 163 + .../7zstub/src/CPP/Common/StdOutStream.h | 71 + .../7zstub/src/CPP/Common/StringConvert.cpp | 319 ++ .../7zstub/src/CPP/Common/StringConvert.h | 88 + .../7zstub/src/CPP/Common/StringToInt.cpp | 144 + other-licenses/7zstub/src/CPP/Common/StringToInt.h | 21 + .../7zstub/src/CPP/Common/TextConfig.cpp | 124 + other-licenses/7zstub/src/CPP/Common/TextConfig.h | 19 + .../7zstub/src/CPP/Common/UTFConvert.cpp | 288 ++ other-licenses/7zstub/src/CPP/Common/UTFConvert.h | 12 + other-licenses/7zstub/src/CPP/Common/Wildcard.cpp | 676 ++++ other-licenses/7zstub/src/CPP/Common/Wildcard.h | 149 + .../7zstub/src/CPP/Common/XzCrc64Init.cpp | 7 + .../7zstub/src/CPP/Common/XzCrc64Reg.cpp | 42 + other-licenses/7zstub/src/CPP/Windows/COM.h | 70 + .../7zstub/src/CPP/Windows/CommonDialog.cpp | 185 + .../7zstub/src/CPP/Windows/CommonDialog.h | 23 + .../7zstub/src/CPP/Windows/Control/ComboBox.cpp | 66 + .../7zstub/src/CPP/Windows/Control/ComboBox.h | 65 + .../7zstub/src/CPP/Windows/Control/CommandBar.h | 52 + .../7zstub/src/CPP/Windows/Control/Dialog.cpp | 251 ++ .../7zstub/src/CPP/Windows/Control/Dialog.h | 170 + .../7zstub/src/CPP/Windows/Control/Edit.h | 19 + .../7zstub/src/CPP/Windows/Control/ImageList.cpp | 10 + .../7zstub/src/CPP/Windows/Control/ImageList.h | 87 + .../7zstub/src/CPP/Windows/Control/ListView.cpp | 155 + .../7zstub/src/CPP/Windows/Control/ListView.h | 146 + .../7zstub/src/CPP/Windows/Control/ProgressBar.h | 35 + .../src/CPP/Windows/Control/PropertyPage.cpp | 143 + .../7zstub/src/CPP/Windows/Control/PropertyPage.h | 50 + .../7zstub/src/CPP/Windows/Control/ReBar.h | 34 + .../7zstub/src/CPP/Windows/Control/Static.h | 28 + .../7zstub/src/CPP/Windows/Control/StatusBar.h | 42 + .../7zstub/src/CPP/Windows/Control/StdAfx.h | 8 + .../7zstub/src/CPP/Windows/Control/ToolBar.h | 43 + .../7zstub/src/CPP/Windows/Control/Trackbar.h | 27 + .../7zstub/src/CPP/Windows/Control/Window2.cpp | 200 ++ .../7zstub/src/CPP/Windows/Control/Window2.h | 51 + other-licenses/7zstub/src/CPP/Windows/DLL.cpp | 109 + other-licenses/7zstub/src/CPP/Windows/DLL.h | 58 + other-licenses/7zstub/src/CPP/Windows/Defs.h | 17 + other-licenses/7zstub/src/CPP/Windows/ErrorMsg.cpp | 66 + other-licenses/7zstub/src/CPP/Windows/ErrorMsg.h | 15 + other-licenses/7zstub/src/CPP/Windows/FileDir.cpp | 714 ++++ other-licenses/7zstub/src/CPP/Windows/FileDir.h | 117 + other-licenses/7zstub/src/CPP/Windows/FileFind.cpp | 749 +++++ other-licenses/7zstub/src/CPP/Windows/FileFind.h | 161 + other-licenses/7zstub/src/CPP/Windows/FileIO.cpp | 432 +++ other-licenses/7zstub/src/CPP/Windows/FileIO.h | 212 ++ other-licenses/7zstub/src/CPP/Windows/FileLink.cpp | 440 +++ .../7zstub/src/CPP/Windows/FileMapping.cpp | 12 + .../7zstub/src/CPP/Windows/FileMapping.h | 66 + other-licenses/7zstub/src/CPP/Windows/FileName.cpp | 839 +++++ other-licenses/7zstub/src/CPP/Windows/FileName.h | 115 + .../7zstub/src/CPP/Windows/FileSystem.cpp | 131 + other-licenses/7zstub/src/CPP/Windows/FileSystem.h | 27 + other-licenses/7zstub/src/CPP/Windows/Handle.h | 37 + .../7zstub/src/CPP/Windows/MemoryLock.cpp | 97 + other-licenses/7zstub/src/CPP/Windows/MemoryLock.h | 40 + other-licenses/7zstub/src/CPP/Windows/NtCheck.h | 46 + .../7zstub/src/CPP/Windows/PropVariant.cpp | 347 ++ .../7zstub/src/CPP/Windows/PropVariant.h | 114 + .../7zstub/src/CPP/Windows/PropVariantConv.cpp | 138 + .../7zstub/src/CPP/Windows/PropVariantConv.h | 37 + other-licenses/7zstub/src/CPP/Windows/Registry.cpp | 390 +++ other-licenses/7zstub/src/CPP/Windows/Registry.h | 84 + .../7zstub/src/CPP/Windows/ResourceString.cpp | 103 + .../7zstub/src/CPP/Windows/ResourceString.h | 16 + .../7zstub/src/CPP/Windows/SecurityUtils.cpp | 181 + .../7zstub/src/CPP/Windows/SecurityUtils.h | 167 + other-licenses/7zstub/src/CPP/Windows/Shell.cpp | 340 ++ other-licenses/7zstub/src/CPP/Windows/Shell.h | 94 + other-licenses/7zstub/src/CPP/Windows/StdAfx.h | 8 + .../7zstub/src/CPP/Windows/Synchronization.cpp | 10 + .../7zstub/src/CPP/Windows/Synchronization.h | 164 + other-licenses/7zstub/src/CPP/Windows/System.cpp | 142 + other-licenses/7zstub/src/CPP/Windows/System.h | 40 + other-licenses/7zstub/src/CPP/Windows/Thread.h | 38 + .../7zstub/src/CPP/Windows/TimeUtils.cpp | 213 ++ other-licenses/7zstub/src/CPP/Windows/TimeUtils.h | 32 + other-licenses/7zstub/src/CPP/Windows/Window.cpp | 179 + other-licenses/7zstub/src/CPP/Windows/Window.h | 284 ++ other-licenses/7zstub/src/CS/7zip/Common/CRC.cs | 55 + .../7zstub/src/CS/7zip/Common/CommandLineParser.cs | 274 ++ .../7zstub/src/CS/7zip/Common/InBuffer.cs | 72 + .../7zstub/src/CS/7zip/Common/OutBuffer.cs | 47 + .../7zstub/src/CS/7zip/Compress/LZ/IMatchFinder.cs | 24 + .../7zstub/src/CS/7zip/Compress/LZ/LzBinTree.cs | 367 ++ .../7zstub/src/CS/7zip/Compress/LZ/LzInWindow.cs | 132 + .../7zstub/src/CS/7zip/Compress/LZ/LzOutWindow.cs | 110 + .../7zstub/src/CS/7zip/Compress/LZMA/LzmaBase.cs | 76 + .../src/CS/7zip/Compress/LZMA/LzmaDecoder.cs | 398 +++ .../src/CS/7zip/Compress/LZMA/LzmaEncoder.cs | 1480 ++++++++ .../src/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs | 364 ++ .../CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj | 90 + .../src/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln | 20 + .../src/CS/7zip/Compress/LzmaAlone/LzmaBench.cs | 340 ++ .../Compress/LzmaAlone/Properties/AssemblyInfo.cs | 29 + .../Compress/LzmaAlone/Properties/Resources.cs | 70 + .../7zip/Compress/LzmaAlone/Properties/Settings.cs | 42 + .../src/CS/7zip/Compress/RangeCoder/RangeCoder.cs | 234 ++ .../CS/7zip/Compress/RangeCoder/RangeCoderBit.cs | 117 + .../7zip/Compress/RangeCoder/RangeCoderBitTree.cs | 157 + other-licenses/7zstub/src/CS/7zip/ICoder.cs | 157 + other-licenses/7zstub/src/DOC/7zC.txt | 187 ++ other-licenses/7zstub/src/DOC/7zFormat.txt | 469 +++ other-licenses/7zstub/src/DOC/Methods.txt | 167 + other-licenses/7zstub/src/DOC/installer.txt | 166 + other-licenses/7zstub/src/DOC/lzma-history.txt | 424 +++ other-licenses/7zstub/src/DOC/lzma-sdk.txt | 357 ++ .../7zstub/src/DOC/lzma-specification.txt | 1176 +++++++ other-licenses/7zstub/src/DOC/lzma.txt | 328 ++ other-licenses/7zstub/src/Java/SevenZip/CRC.java | 52 + .../src/Java/SevenZip/Compression/LZ/BinTree.java | 382 +++ .../src/Java/SevenZip/Compression/LZ/InWindow.java | 131 + .../Java/SevenZip/Compression/LZ/OutWindow.java | 85 + .../src/Java/SevenZip/Compression/LZMA/Base.java | 88 + .../Java/SevenZip/Compression/LZMA/Decoder.java | 329 ++ .../Java/SevenZip/Compression/LZMA/Encoder.java | 1416 ++++++++ .../Compression/RangeCoder/BitTreeDecoder.java | 55 + .../Compression/RangeCoder/BitTreeEncoder.java | 99 + .../SevenZip/Compression/RangeCoder/Decoder.java | 88 + .../SevenZip/Compression/RangeCoder/Encoder.java | 151 + .../7zstub/src/Java/SevenZip/ICodeProgress.java | 6 + .../7zstub/src/Java/SevenZip/LzmaAlone.java | 253 ++ .../7zstub/src/Java/SevenZip/LzmaBench.java | 392 +++ other-licenses/7zstub/src/bin/7zS2.sfx | Bin 0 -> 34816 bytes other-licenses/7zstub/src/bin/7zS2con.sfx | Bin 0 -> 34816 bytes other-licenses/7zstub/src/bin/7zSD.sfx | Bin 0 -> 124928 bytes other-licenses/7zstub/src/bin/7zdec.exe | Bin 0 -> 42496 bytes other-licenses/7zstub/src/bin/7zr.exe | Bin 0 -> 518656 bytes other-licenses/7zstub/src/bin/installer/config.txt | 5 + other-licenses/7zstub/src/bin/installer/cr.bat | 5 + other-licenses/7zstub/src/bin/lzma.exe | Bin 0 -> 106496 bytes other-licenses/7zstub/src/bin/x64/7zr.exe | Bin 0 -> 798720 bytes 633 files changed, 132542 insertions(+) create mode 100644 other-licenses/7zstub/src/Asm/arm/7zCrcOpt.asm create mode 100644 other-licenses/7zstub/src/Asm/x86/7zAsm.asm create mode 100644 other-licenses/7zstub/src/Asm/x86/7zCrcOpt.asm create mode 100644 other-licenses/7zstub/src/Asm/x86/AesOpt.asm create mode 100644 other-licenses/7zstub/src/Asm/x86/LzmaDecOpt.asm create mode 100644 other-licenses/7zstub/src/Asm/x86/XzCrc64Opt.asm create mode 100644 other-licenses/7zstub/src/C/7z.h create mode 100644 other-licenses/7zstub/src/C/7zAlloc.c create mode 100644 other-licenses/7zstub/src/C/7zAlloc.h create mode 100644 other-licenses/7zstub/src/C/7zArcIn.c create mode 100644 other-licenses/7zstub/src/C/7zBuf.c create mode 100644 other-licenses/7zstub/src/C/7zBuf.h create mode 100644 other-licenses/7zstub/src/C/7zBuf2.c create mode 100644 other-licenses/7zstub/src/C/7zCrc.c create mode 100644 other-licenses/7zstub/src/C/7zCrc.h create mode 100644 other-licenses/7zstub/src/C/7zCrcOpt.c create mode 100644 other-licenses/7zstub/src/C/7zDec.c create mode 100644 other-licenses/7zstub/src/C/7zFile.c create mode 100644 other-licenses/7zstub/src/C/7zFile.h create mode 100644 other-licenses/7zstub/src/C/7zStream.c create mode 100644 other-licenses/7zstub/src/C/7zTypes.h create mode 100644 other-licenses/7zstub/src/C/7zVersion.h create mode 100644 other-licenses/7zstub/src/C/7zVersion.rc create mode 100644 other-licenses/7zstub/src/C/Aes.c create mode 100644 other-licenses/7zstub/src/C/Aes.h create mode 100644 other-licenses/7zstub/src/C/AesOpt.c create mode 100644 other-licenses/7zstub/src/C/Alloc.c create mode 100644 other-licenses/7zstub/src/C/Alloc.h create mode 100644 other-licenses/7zstub/src/C/Bcj2.c create mode 100644 other-licenses/7zstub/src/C/Bcj2.h create mode 100644 other-licenses/7zstub/src/C/Bcj2Enc.c create mode 100644 other-licenses/7zstub/src/C/Bra.c create mode 100644 other-licenses/7zstub/src/C/Bra.h create mode 100644 other-licenses/7zstub/src/C/Bra86.c create mode 100644 other-licenses/7zstub/src/C/BraIA64.c create mode 100644 other-licenses/7zstub/src/C/Compiler.h create mode 100644 other-licenses/7zstub/src/C/CpuArch.c create mode 100644 other-licenses/7zstub/src/C/CpuArch.h create mode 100644 other-licenses/7zstub/src/C/Delta.c create mode 100644 other-licenses/7zstub/src/C/Delta.h create mode 100644 other-licenses/7zstub/src/C/DllSecur.c create mode 100644 other-licenses/7zstub/src/C/DllSecur.h create mode 100644 other-licenses/7zstub/src/C/LzFind.c create mode 100644 other-licenses/7zstub/src/C/LzFind.h create mode 100644 other-licenses/7zstub/src/C/LzFindMt.c create mode 100644 other-licenses/7zstub/src/C/LzFindMt.h create mode 100644 other-licenses/7zstub/src/C/LzHash.h create mode 100644 other-licenses/7zstub/src/C/Lzma2Dec.c create mode 100644 other-licenses/7zstub/src/C/Lzma2Dec.h create mode 100644 other-licenses/7zstub/src/C/Lzma2DecMt.c create mode 100644 other-licenses/7zstub/src/C/Lzma2DecMt.h create mode 100644 other-licenses/7zstub/src/C/Lzma2Enc.c create mode 100644 other-licenses/7zstub/src/C/Lzma2Enc.h create mode 100644 other-licenses/7zstub/src/C/Lzma86.h create mode 100644 other-licenses/7zstub/src/C/Lzma86Dec.c create mode 100644 other-licenses/7zstub/src/C/Lzma86Enc.c create mode 100644 other-licenses/7zstub/src/C/LzmaDec.c create mode 100644 other-licenses/7zstub/src/C/LzmaDec.h create mode 100644 other-licenses/7zstub/src/C/LzmaEnc.c create mode 100644 other-licenses/7zstub/src/C/LzmaEnc.h create mode 100644 other-licenses/7zstub/src/C/LzmaLib.c create mode 100644 other-licenses/7zstub/src/C/LzmaLib.h create mode 100644 other-licenses/7zstub/src/C/MtCoder.c create mode 100644 other-licenses/7zstub/src/C/MtCoder.h create mode 100644 other-licenses/7zstub/src/C/MtDec.c create mode 100644 other-licenses/7zstub/src/C/MtDec.h create mode 100644 other-licenses/7zstub/src/C/Ppmd.h create mode 100644 other-licenses/7zstub/src/C/Ppmd7.c create mode 100644 other-licenses/7zstub/src/C/Ppmd7.h create mode 100644 other-licenses/7zstub/src/C/Ppmd7Dec.c create mode 100644 other-licenses/7zstub/src/C/Ppmd7Enc.c create mode 100644 other-licenses/7zstub/src/C/Precomp.h create mode 100644 other-licenses/7zstub/src/C/RotateDefs.h create mode 100644 other-licenses/7zstub/src/C/Sha256.c create mode 100644 other-licenses/7zstub/src/C/Sha256.h create mode 100644 other-licenses/7zstub/src/C/Sort.c create mode 100644 other-licenses/7zstub/src/C/Sort.h create mode 100644 other-licenses/7zstub/src/C/Threads.c create mode 100644 other-licenses/7zstub/src/C/Threads.h create mode 100644 other-licenses/7zstub/src/C/Util/7z/7z.dsp create mode 100644 other-licenses/7zstub/src/C/Util/7z/7z.dsw create mode 100644 other-licenses/7zstub/src/C/Util/7z/7zMain.c create mode 100644 other-licenses/7zstub/src/C/Util/7z/Precomp.c create mode 100644 other-licenses/7zstub/src/C/Util/7z/Precomp.h create mode 100644 other-licenses/7zstub/src/C/Util/7z/makefile create mode 100644 other-licenses/7zstub/src/C/Util/7z/makefile.gcc create mode 100644 other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.c create mode 100644 other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsp create mode 100644 other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsw create mode 100644 other-licenses/7zstub/src/C/Util/Lzma/makefile create mode 100644 other-licenses/7zstub/src/C/Util/Lzma/makefile.gcc create mode 100644 other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.def create mode 100644 other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.dsp create mode 100644 other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.dsw create mode 100644 other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLibExports.c create mode 100644 other-licenses/7zstub/src/C/Util/LzmaLib/makefile create mode 100644 other-licenses/7zstub/src/C/Util/LzmaLib/resource.rc create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/Precomp.c create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/Precomp.h create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.c create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.dsp create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.dsw create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/makefile create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/makefile_con create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/resource.rc create mode 100644 other-licenses/7zstub/src/C/Util/SfxSetup/setup.ico create mode 100644 other-licenses/7zstub/src/C/Xz.c create mode 100644 other-licenses/7zstub/src/C/Xz.h create mode 100644 other-licenses/7zstub/src/C/XzCrc64.c create mode 100644 other-licenses/7zstub/src/C/XzCrc64.h create mode 100644 other-licenses/7zstub/src/C/XzCrc64Opt.c create mode 100644 other-licenses/7zstub/src/C/XzDec.c create mode 100644 other-licenses/7zstub/src/C/XzEnc.c create mode 100644 other-licenses/7zstub/src/C/XzEnc.h create mode 100644 other-licenses/7zstub/src/C/XzIn.c create mode 100644 other-licenses/7zstub/src/CPP/7zip/7zip.mak create mode 100644 other-licenses/7zstub/src/CPP/7zip/Aes.mak create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zCompressionMode.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zDecode.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zEncode.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zExtract.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zFolderInStream.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandler.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHandlerOut.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zHeader.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zIn.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zItem.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zOut.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zProperties.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zRegister.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zSpecStream.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/7zUpdate.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/7z/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Archive.def create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Archive2.def create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/ArchiveExports.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/CoderMixer2.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/DummyOutStream.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/HandlerOut.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/InStreamWithCRC.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/ItemNameUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/MultiStream.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/OutStreamWithCRC.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/ParseProperties.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Common/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/DllExports2.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/IArchive.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/Icons/7z.ico create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/LzmaHandler.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/SplitHandler.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Archive/XzHandler.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Asm.mak create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/Alone.dsw create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Alone7z/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zExtractR/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/Format7zR/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/makefile.gcc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaCon/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/7z.ico create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SFXCon.dsw create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/SfxCon.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/setup.ico create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/7z.ico create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SFXWin.dsw create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/SfxWin.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/CWrappers.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/CreateCoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/FilePathAutoRename.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/FileStreams.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/FilterCoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/InBuffer.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/InOutTempBuffer.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/LimitedStreams.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/LockedStream.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/MethodId.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/MethodId.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/OffsetStream.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/OutBuffer.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/ProgressUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/PropId.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/RegisterArc.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/RegisterCodec.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/StreamBinder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/StreamObjects.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/StreamUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/UniqBlocks.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Common/VirtThread.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Coder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/Bcj2Register.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/BcjCoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/BcjRegister.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/BranchMisc.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/BranchRegister.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/ByteSwap.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/CodecExports.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/CopyCoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/CopyRegister.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/DeltaFilter.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Decoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Encoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/Lzma2Register.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/LzmaDecoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/LzmaEncoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/LzmaRegister.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/PpmdDecoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/PpmdEncoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/PpmdRegister.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/XzDecoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Compress/XzEncoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crc.mak create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crc64.mak create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/7zAes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/7zAesRegister.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/MyAes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/MyAesReg.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/RandGen.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/Crypto/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/GuiCommon.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/Guid.txt create mode 100644 other-licenses/7zstub/src/CPP/7zip/ICoder.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/IDecl.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/IPassword.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/IProgress.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/IStream.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/LzmaDec.mak create mode 100644 other-licenses/7zstub/src/CPP/7zip/MyVersion.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/MyVersionInfo.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/PropID.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/SubBuild.mak create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Client7z/Client7z.dsw create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Client7z/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Client7z/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Client7z/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveCommandLine.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveExtractCallback.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveName.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ArchiveOpenCallback.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/Bench.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/DefaultName.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/DirItem.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/EnumDirItems.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ExitCode.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/Extract.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractMode.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ExtractingFilePath.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/HashCalc.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/IFileExtractCallback.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/LoadCodecs.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/OpenArchive.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/PropIDUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/Property.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/SetProperties.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/SortUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/TempFiles.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/Update.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateAction.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateCallback.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdatePair.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/UpdateProduce.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/WorkDir.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Common/ZipRegistry.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/BenchCon.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.mak create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/Console.manifest create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/ConsoleClose.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/ExtractCallbackConsole.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/HashCon.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/List.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/List.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/Main.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/MainAr.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/OpenCallbackConsole.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/PercentPrinter.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/UpdateCallbackConsole.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/UserInputUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/makefile create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Console/resource.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/Explorer/MyMessages.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialog.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/BrowseDialogRes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialog.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ComboDialogRes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/DialogSize.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ExtractCallback.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/FormatUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/LangUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/MyWindowsNew.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialog.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/OverwriteDialogRes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialog.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PasswordDialogRes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2Res.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialog2a.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/ProgressDialogRes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyName.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/PropertyNameRes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/SysIconUtils.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resource.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/FileManager/resourceGui.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/Extract.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialog.rc create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractDialogRes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.cpp create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractGUI.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/ExtractRes.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/HashGUI.h create mode 100644 other-licenses/7zstub/src/CPP/7zip/UI/GUI/resource2.h create mode 100644 other-licenses/7zstub/src/CPP/Build.mak create mode 100644 other-licenses/7zstub/src/CPP/Common/AutoPtr.h create mode 100644 other-licenses/7zstub/src/CPP/Common/CRC.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/C_FileIO.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/C_FileIO.h create mode 100644 other-licenses/7zstub/src/CPP/Common/ComTry.h create mode 100644 other-licenses/7zstub/src/CPP/Common/CommandLineParser.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/CommandLineParser.h create mode 100644 other-licenses/7zstub/src/CPP/Common/Common.h create mode 100644 other-licenses/7zstub/src/CPP/Common/CrcReg.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/Defs.h create mode 100644 other-licenses/7zstub/src/CPP/Common/DynamicBuffer.h create mode 100644 other-licenses/7zstub/src/CPP/Common/IntToString.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/IntToString.h create mode 100644 other-licenses/7zstub/src/CPP/Common/Lang.h create mode 100644 other-licenses/7zstub/src/CPP/Common/ListFileUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/ListFileUtils.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyBuffer.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyBuffer2.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyCom.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyException.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyGuidDef.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyInitGuid.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyLinux.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyString.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/MyString.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyTypes.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyUnknown.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyVector.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/MyVector.h create mode 100644 other-licenses/7zstub/src/CPP/Common/MyWindows.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/MyWindows.h create mode 100644 other-licenses/7zstub/src/CPP/Common/NewHandler.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/NewHandler.h create mode 100644 other-licenses/7zstub/src/CPP/Common/Sha256Reg.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/Common/StdInStream.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/StdInStream.h create mode 100644 other-licenses/7zstub/src/CPP/Common/StdOutStream.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/StdOutStream.h create mode 100644 other-licenses/7zstub/src/CPP/Common/StringConvert.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/StringConvert.h create mode 100644 other-licenses/7zstub/src/CPP/Common/StringToInt.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/StringToInt.h create mode 100644 other-licenses/7zstub/src/CPP/Common/TextConfig.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/TextConfig.h create mode 100644 other-licenses/7zstub/src/CPP/Common/UTFConvert.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/UTFConvert.h create mode 100644 other-licenses/7zstub/src/CPP/Common/Wildcard.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/Wildcard.h create mode 100644 other-licenses/7zstub/src/CPP/Common/XzCrc64Init.cpp create mode 100644 other-licenses/7zstub/src/CPP/Common/XzCrc64Reg.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/COM.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/CommonDialog.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/CommonDialog.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ComboBox.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ComboBox.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/CommandBar.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/Dialog.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/Dialog.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/Edit.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ImageList.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ImageList.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ListView.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ListView.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ProgressBar.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/PropertyPage.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/PropertyPage.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ReBar.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/Static.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/StatusBar.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/ToolBar.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/Trackbar.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/Window2.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Control/Window2.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/DLL.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/DLL.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Defs.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/ErrorMsg.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/ErrorMsg.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileDir.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileDir.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileFind.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileFind.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileIO.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileIO.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileLink.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileMapping.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileMapping.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileName.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileName.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileSystem.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/FileSystem.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Handle.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/MemoryLock.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/MemoryLock.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/NtCheck.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/PropVariant.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/PropVariant.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/PropVariantConv.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/PropVariantConv.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Registry.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Registry.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/ResourceString.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/ResourceString.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/SecurityUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/SecurityUtils.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Shell.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Shell.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/StdAfx.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Synchronization.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Synchronization.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/System.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/System.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Thread.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/TimeUtils.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/TimeUtils.h create mode 100644 other-licenses/7zstub/src/CPP/Windows/Window.cpp create mode 100644 other-licenses/7zstub/src/CPP/Windows/Window.h create mode 100644 other-licenses/7zstub/src/CS/7zip/Common/CRC.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Common/CommandLineParser.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Common/InBuffer.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Common/OutBuffer.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LZ/IMatchFinder.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzBinTree.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzInWindow.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzOutWindow.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaBase.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaDecoder.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaEncoder.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaBench.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoder.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs create mode 100644 other-licenses/7zstub/src/CS/7zip/ICoder.cs create mode 100644 other-licenses/7zstub/src/DOC/7zC.txt create mode 100644 other-licenses/7zstub/src/DOC/7zFormat.txt create mode 100644 other-licenses/7zstub/src/DOC/Methods.txt create mode 100644 other-licenses/7zstub/src/DOC/installer.txt create mode 100644 other-licenses/7zstub/src/DOC/lzma-history.txt create mode 100644 other-licenses/7zstub/src/DOC/lzma-sdk.txt create mode 100644 other-licenses/7zstub/src/DOC/lzma-specification.txt create mode 100644 other-licenses/7zstub/src/DOC/lzma.txt create mode 100644 other-licenses/7zstub/src/Java/SevenZip/CRC.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/BinTree.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/InWindow.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/OutWindow.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Base.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Decoder.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Encoder.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Decoder.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Encoder.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/ICodeProgress.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/LzmaAlone.java create mode 100644 other-licenses/7zstub/src/Java/SevenZip/LzmaBench.java create mode 100644 other-licenses/7zstub/src/bin/7zS2.sfx create mode 100644 other-licenses/7zstub/src/bin/7zS2con.sfx create mode 100644 other-licenses/7zstub/src/bin/7zSD.sfx create mode 100644 other-licenses/7zstub/src/bin/7zdec.exe create mode 100644 other-licenses/7zstub/src/bin/7zr.exe create mode 100644 other-licenses/7zstub/src/bin/installer/config.txt create mode 100644 other-licenses/7zstub/src/bin/installer/cr.bat create mode 100644 other-licenses/7zstub/src/bin/lzma.exe create mode 100644 other-licenses/7zstub/src/bin/x64/7zr.exe (limited to 'other-licenses/7zstub/src') diff --git a/other-licenses/7zstub/src/Asm/arm/7zCrcOpt.asm b/other-licenses/7zstub/src/Asm/arm/7zCrcOpt.asm new file mode 100644 index 0000000000..f008d658c3 --- /dev/null +++ b/other-licenses/7zstub/src/Asm/arm/7zCrcOpt.asm @@ -0,0 +1,100 @@ + CODE32 + + EXPORT |CrcUpdateT4@16| + + AREA |.text|, CODE, ARM + + MACRO + CRC32_STEP_1 + + ldrb r4, [r1], #1 + subs r2, r2, #1 + eor r4, r4, r0 + and r4, r4, #0xFF + ldr r4, [r3, +r4, lsl #2] + eor r0, r4, r0, lsr #8 + + MEND + + + MACRO + CRC32_STEP_4 $STREAM_WORD + + eor r7, r7, r8 + eor r7, r7, r9 + eor r0, r0, r7 + eor r0, r0, $STREAM_WORD + ldr $STREAM_WORD, [r1], #4 + + and r7, r0, #0xFF + and r8, r0, #0xFF00 + and r9, r0, #0xFF0000 + and r0, r0, #0xFF000000 + + ldr r7, [r6, +r7, lsl #2] + ldr r8, [r5, +r8, lsr #6] + ldr r9, [r4, +r9, lsr #14] + ldr r0, [r3, +r0, lsr #22] + + MEND + + +|CrcUpdateT4@16| PROC + + stmdb sp!, {r4-r11, lr} + cmp r2, #0 + beq |$fin| + +|$v1| + tst r1, #7 + beq |$v2| + CRC32_STEP_1 + bne |$v1| + +|$v2| + cmp r2, #16 + blo |$v3| + + ldr r10, [r1], #4 + ldr r11, [r1], #4 + + add r4, r3, #0x400 + add r5, r3, #0x800 + add r6, r3, #0xC00 + + mov r7, #0 + mov r8, #0 + mov r9, #0 + + sub r2, r2, #16 + +|$loop| + ; pld [r1, #0x40] + + CRC32_STEP_4 r10 + CRC32_STEP_4 r11 + + subs r2, r2, #8 + bhs |$loop| + + sub r1, r1, #8 + add r2, r2, #16 + + eor r7, r7, r8 + eor r7, r7, r9 + eor r0, r0, r7 + +|$v3| + cmp r2, #0 + beq |$fin| + +|$v4| + CRC32_STEP_1 + bne |$v4| + +|$fin| + ldmia sp!, {r4-r11, pc} + +|CrcUpdateT4@16| ENDP + + END diff --git a/other-licenses/7zstub/src/Asm/x86/7zAsm.asm b/other-licenses/7zstub/src/Asm/x86/7zAsm.asm new file mode 100644 index 0000000000..8c30d7b7e3 --- /dev/null +++ b/other-licenses/7zstub/src/Asm/x86/7zAsm.asm @@ -0,0 +1,147 @@ +; 7zAsm.asm -- ASM macros +; 2018-02-03 : Igor Pavlov : Public domain + +MY_ASM_START macro + ifdef x64 + .code + else + .386 + .model flat + _TEXT$00 SEGMENT PARA PUBLIC 'CODE' + endif +endm + +MY_PROC macro name:req, numParams:req + align 16 + proc_numParams = numParams + ifdef x64 + proc_name equ name + else + proc_name equ @CatStr(@,name,@, %numParams * 4) + endif + proc_name PROC +endm + +MY_ENDP macro + ifdef x64 + ret + else + if proc_numParams LT 3 + ret + else + ret (proc_numParams - 2) * 4 + endif + endif + proc_name ENDP +endm + +ifdef x64 + REG_SIZE equ 8 + REG_LOGAR_SIZE equ 3 +else + REG_SIZE equ 4 + REG_LOGAR_SIZE equ 2 +endif + + x0 equ EAX + x1 equ ECX + x2 equ EDX + x3 equ EBX + x4 equ ESP + x5 equ EBP + x6 equ ESI + x7 equ EDI + + x0_W equ AX + x1_W equ CX + x2_W equ DX + x3_W equ BX + + x5_W equ BP + x6_W equ SI + x7_W equ DI + + x0_L equ AL + x1_L equ CL + x2_L equ DL + x3_L equ BL + + x0_H equ AH + x1_H equ CH + x2_H equ DH + x3_H equ BH + +ifdef x64 + x5_L equ BPL + x6_L equ SIL + x7_L equ DIL + + r0 equ RAX + r1 equ RCX + r2 equ RDX + r3 equ RBX + r4 equ RSP + r5 equ RBP + r6 equ RSI + r7 equ RDI + x8 equ r8d + x9 equ r9d + x10 equ r10d + x11 equ r11d + x12 equ r12d + x13 equ r13d + x14 equ r14d + x15 equ r15d +else + r0 equ x0 + r1 equ x1 + r2 equ x2 + r3 equ x3 + r4 equ x4 + r5 equ x5 + r6 equ x6 + r7 equ x7 +endif + +MY_PUSH_4_REGS macro + push r3 + push r5 + push r6 + push r7 +endm + +MY_POP_4_REGS macro + pop r7 + pop r6 + pop r5 + pop r3 +endm + + +ifdef x64 + +; for WIN64-x64 ABI: + +REG_PARAM_0 equ r1 +REG_PARAM_1 equ r2 +REG_PARAM_2 equ r8 +REG_PARAM_3 equ r9 + +MY_PUSH_PRESERVED_REGS macro + MY_PUSH_4_REGS + push r12 + push r13 + push r14 + push r15 +endm + + +MY_POP_PRESERVED_REGS macro + pop r15 + pop r14 + pop r13 + pop r12 + MY_POP_4_REGS +endm + +endif diff --git a/other-licenses/7zstub/src/Asm/x86/7zCrcOpt.asm b/other-licenses/7zstub/src/Asm/x86/7zCrcOpt.asm new file mode 100644 index 0000000000..2de51719ad --- /dev/null +++ b/other-licenses/7zstub/src/Asm/x86/7zCrcOpt.asm @@ -0,0 +1,147 @@ +; 7zCrcOpt.asm -- CRC32 calculation : optimized version +; 2009-12-12 : Igor Pavlov : Public domain + +include 7zAsm.asm + +MY_ASM_START + +rD equ r2 +rN equ r7 + +ifdef x64 + num_VAR equ r8 + table_VAR equ r9 +else + data_size equ (REG_SIZE * 5) + crc_table equ (REG_SIZE + data_size) + num_VAR equ [r4 + data_size] + table_VAR equ [r4 + crc_table] +endif + +SRCDAT equ rN + rD + 4 * + +CRC macro op:req, dest:req, src:req, t:req + op dest, DWORD PTR [r5 + src * 4 + 0400h * t] +endm + +CRC_XOR macro dest:req, src:req, t:req + CRC xor, dest, src, t +endm + +CRC_MOV macro dest:req, src:req, t:req + CRC mov, dest, src, t +endm + +CRC1b macro + movzx x6, BYTE PTR [rD] + inc rD + movzx x3, x0_L + xor x6, x3 + shr x0, 8 + CRC xor, x0, r6, 0 + dec rN +endm + +MY_PROLOG macro crc_end:req + MY_PUSH_4_REGS + + mov x0, x1 + mov rN, num_VAR + mov r5, table_VAR + test rN, rN + jz crc_end + @@: + test rD, 7 + jz @F + CRC1b + jnz @B + @@: + cmp rN, 16 + jb crc_end + add rN, rD + mov num_VAR, rN + sub rN, 8 + and rN, NOT 7 + sub rD, rN + xor x0, [SRCDAT 0] +endm + +MY_EPILOG macro crc_end:req + xor x0, [SRCDAT 0] + mov rD, rN + mov rN, num_VAR + sub rN, rD + crc_end: + test rN, rN + jz @F + CRC1b + jmp crc_end + @@: + MY_POP_4_REGS +endm + +MY_PROC CrcUpdateT8, 4 + MY_PROLOG crc_end_8 + mov x1, [SRCDAT 1] + align 16 + main_loop_8: + mov x6, [SRCDAT 2] + movzx x3, x1_L + CRC_XOR x6, r3, 3 + movzx x3, x1_H + CRC_XOR x6, r3, 2 + shr x1, 16 + movzx x3, x1_L + movzx x1, x1_H + CRC_XOR x6, r3, 1 + movzx x3, x0_L + CRC_XOR x6, r1, 0 + + mov x1, [SRCDAT 3] + CRC_XOR x6, r3, 7 + movzx x3, x0_H + shr x0, 16 + CRC_XOR x6, r3, 6 + movzx x3, x0_L + CRC_XOR x6, r3, 5 + movzx x3, x0_H + CRC_MOV x0, r3, 4 + xor x0, x6 + add rD, 8 + jnz main_loop_8 + + MY_EPILOG crc_end_8 +MY_ENDP + +MY_PROC CrcUpdateT4, 4 + MY_PROLOG crc_end_4 + align 16 + main_loop_4: + movzx x1, x0_L + movzx x3, x0_H + shr x0, 16 + movzx x6, x0_H + and x0, 0FFh + CRC_MOV x1, r1, 3 + xor x1, [SRCDAT 1] + CRC_XOR x1, r3, 2 + CRC_XOR x1, r6, 0 + CRC_XOR x1, r0, 1 + + movzx x0, x1_L + movzx x3, x1_H + shr x1, 16 + movzx x6, x1_H + and x1, 0FFh + CRC_MOV x0, r0, 3 + xor x0, [SRCDAT 2] + CRC_XOR x0, r3, 2 + CRC_XOR x0, r6, 0 + CRC_XOR x0, r1, 1 + add rD, 8 + jnz main_loop_4 + + MY_EPILOG crc_end_4 +MY_ENDP + +end diff --git a/other-licenses/7zstub/src/Asm/x86/AesOpt.asm b/other-licenses/7zstub/src/Asm/x86/AesOpt.asm new file mode 100644 index 0000000000..c32e48f886 --- /dev/null +++ b/other-licenses/7zstub/src/Asm/x86/AesOpt.asm @@ -0,0 +1,237 @@ +; AesOpt.asm -- Intel's AES. +; 2009-12-12 : Igor Pavlov : Public domain + +include 7zAsm.asm + +MY_ASM_START + +ifndef x64 + .xmm +endif + +ifdef x64 + num equ r8 +else + num equ [r4 + REG_SIZE * 4] +endif + +rD equ r2 +rN equ r0 + +MY_PROLOG macro reg:req + ifdef x64 + movdqa [r4 + 8], xmm6 + movdqa [r4 + 8 + 16], xmm7 + endif + + push r3 + push r5 + push r6 + + mov rN, num + mov x6, [r1 + 16] + shl x6, 5 + + movdqa reg, [r1] + add r1, 32 +endm + +MY_EPILOG macro + pop r6 + pop r5 + pop r3 + + ifdef x64 + movdqa xmm6, [r4 + 8] + movdqa xmm7, [r4 + 8 + 16] + endif + + MY_ENDP +endm + +ways equ 4 +ways16 equ (ways * 16) + +OP_W macro op, op2 + i = 0 + rept ways + op @CatStr(xmm,%i), op2 + i = i + 1 + endm +endm + +LOAD_OP macro op:req, offs:req + op xmm0, [r1 + r3 offs] +endm + +LOAD_OP_W macro op:req, offs:req + movdqa xmm7, [r1 + r3 offs] + OP_W op, xmm7 +endm + + +; ---------- AES-CBC Decode ---------- + +CBC_DEC_UPDATE macro reg, offs + pxor reg, xmm6 + movdqa xmm6, [rD + offs] + movdqa [rD + offs], reg +endm + +DECODE macro op:req + op aesdec, +16 + @@: + op aesdec, +0 + op aesdec, -16 + sub x3, 32 + jnz @B + op aesdeclast, +0 +endm + +MY_PROC AesCbc_Decode_Intel, 3 + MY_PROLOG xmm6 + + sub x6, 32 + + jmp check2 + + align 16 + nextBlocks2: + mov x3, x6 + OP_W movdqa, [rD + i * 16] + LOAD_OP_W pxor, +32 + DECODE LOAD_OP_W + OP_W CBC_DEC_UPDATE, i * 16 + add rD, ways16 + check2: + sub rN, ways + jnc nextBlocks2 + + add rN, ways + jmp check + + nextBlock: + mov x3, x6 + movdqa xmm1, [rD] + LOAD_OP movdqa, +32 + pxor xmm0, xmm1 + DECODE LOAD_OP + pxor xmm0, xmm6 + movdqa [rD], xmm0 + movdqa xmm6, xmm1 + add rD, 16 + check: + sub rN, 1 + jnc nextBlock + + movdqa [r1 - 32], xmm6 + MY_EPILOG + + +; ---------- AES-CBC Encode ---------- + +ENCODE macro op:req + op aesenc, -16 + @@: + op aesenc, +0 + op aesenc, +16 + add r3, 32 + jnz @B + op aesenclast, +0 +endm + +MY_PROC AesCbc_Encode_Intel, 3 + MY_PROLOG xmm0 + + add r1, r6 + neg r6 + add r6, 32 + + jmp check_e + + align 16 + nextBlock_e: + mov r3, r6 + pxor xmm0, [rD] + pxor xmm0, [r1 + r3 - 32] + ENCODE LOAD_OP + movdqa [rD], xmm0 + add rD, 16 + check_e: + sub rN, 1 + jnc nextBlock_e + + movdqa [r1 + r6 - 64], xmm0 + MY_EPILOG + + +; ---------- AES-CTR ---------- + +XOR_UPD_1 macro reg, offs + pxor reg, [rD + offs] +endm + +XOR_UPD_2 macro reg, offs + movdqa [rD + offs], reg +endm + +MY_PROC AesCtr_Code_Intel, 3 + MY_PROLOG xmm6 + + mov r5, r4 + shr r5, 4 + dec r5 + shl r5, 4 + + mov DWORD PTR [r5], 1 + mov DWORD PTR [r5 + 4], 0 + mov DWORD PTR [r5 + 8], 0 + mov DWORD PTR [r5 + 12], 0 + + add r1, r6 + neg r6 + add r6, 32 + + jmp check2_c + + align 16 + nextBlocks2_c: + movdqa xmm7, [r5] + + i = 0 + rept ways + paddq xmm6, xmm7 + movdqa @CatStr(xmm,%i), xmm6 + i = i + 1 + endm + + mov r3, r6 + LOAD_OP_W pxor, -32 + ENCODE LOAD_OP_W + OP_W XOR_UPD_1, i * 16 + OP_W XOR_UPD_2, i * 16 + add rD, ways16 + check2_c: + sub rN, ways + jnc nextBlocks2_c + + add rN, ways + jmp check_c + + nextBlock_c: + paddq xmm6, [r5] + mov r3, r6 + movdqa xmm0, [r1 + r3 - 32] + pxor xmm0, xmm6 + ENCODE LOAD_OP + XOR_UPD_1 xmm0, 0 + XOR_UPD_2 xmm0, 0 + add rD, 16 + check_c: + sub rN, 1 + jnc nextBlock_c + + movdqa [r1 + r6 - 64], xmm6 + MY_EPILOG + +end diff --git a/other-licenses/7zstub/src/Asm/x86/LzmaDecOpt.asm b/other-licenses/7zstub/src/Asm/x86/LzmaDecOpt.asm new file mode 100644 index 0000000000..0a89eb735f --- /dev/null +++ b/other-licenses/7zstub/src/Asm/x86/LzmaDecOpt.asm @@ -0,0 +1,1258 @@ +; LzmaDecOpt.asm -- ASM version of LzmaDec_DecodeReal_3() function +; 2018-02-06: Igor Pavlov : Public domain +; +; 3 - is the code compatibility version of LzmaDec_DecodeReal_*() +; function for check at link time. +; That code is tightly coupled with LzmaDec_TryDummy() +; and with another functions in LzmaDec.c file. +; CLzmaDec structure, (probs) array layout, input and output of +; LzmaDec_DecodeReal_*() must be equal in both versions (C / ASM). + +ifndef x64 +; x64=1 +; .err +endif + +include 7zAsm.asm + +MY_ASM_START + +_TEXT$LZMADECOPT SEGMENT ALIGN(64) 'CODE' + +MY_ALIGN macro num:req + align num +endm + +MY_ALIGN_16 macro + MY_ALIGN 16 +endm + +MY_ALIGN_32 macro + MY_ALIGN 32 +endm + +MY_ALIGN_64 macro + MY_ALIGN 64 +endm + + +; _LZMA_SIZE_OPT equ 1 + +; _LZMA_PROB32 equ 1 + +ifdef _LZMA_PROB32 + PSHIFT equ 2 + PLOAD macro dest, mem + mov dest, dword ptr [mem] + endm + PSTORE macro src, mem + mov dword ptr [mem], src + endm +else + PSHIFT equ 1 + PLOAD macro dest, mem + movzx dest, word ptr [mem] + endm + PSTORE macro src, mem + mov word ptr [mem], @CatStr(src, _W) + endm +endif + +PMULT equ (1 SHL PSHIFT) +PMULT_HALF equ (1 SHL (PSHIFT - 1)) +PMULT_2 equ (1 SHL (PSHIFT + 1)) + + +; x0 range +; x1 pbPos / (prob) TREE +; x2 probBranch / prm (MATCHED) / pbPos / cnt +; x3 sym +;====== r4 === RSP +; x5 cod +; x6 t1 NORM_CALC / probs_state / dist +; x7 t0 NORM_CALC / prob2 IF_BIT_1 +; x8 state +; x9 match (MATCHED) / sym2 / dist2 / lpMask_reg +; x10 kBitModelTotal_reg +; r11 probs +; x12 offs (MATCHED) / dic / len_temp +; x13 processedPos +; x14 bit (MATCHED) / dicPos +; r15 buf + + +cod equ x5 +cod_L equ x5_L +range equ x0 +state equ x8 +state_R equ r8 +buf equ r15 +processedPos equ x13 +kBitModelTotal_reg equ x10 + +probBranch equ x2 +probBranch_R equ r2 +probBranch_W equ x2_W + +pbPos equ x1 +pbPos_R equ r1 + +cnt equ x2 +cnt_R equ r2 + +lpMask_reg equ x9 +dicPos equ r14 + +sym equ x3 +sym_R equ r3 +sym_L equ x3_L + +probs equ r11 +dic equ r12 + +t0 equ x7 +t0_W equ x7_W +t0_R equ r7 + +prob2 equ t0 +prob2_W equ t0_W + +t1 equ x6 +t1_R equ r6 + +probs_state equ t1 +probs_state_R equ t1_R + +prm equ r2 +match equ x9 +match_R equ r9 +offs equ x12 +offs_R equ r12 +bit equ x14 +bit_R equ r14 + +sym2 equ x9 +sym2_R equ r9 + +len_temp equ x12 + +dist equ sym +dist2 equ x9 + + + +kNumBitModelTotalBits equ 11 +kBitModelTotal equ (1 SHL kNumBitModelTotalBits) +kNumMoveBits equ 5 +kBitModelOffset equ ((1 SHL kNumMoveBits) - 1) +kTopValue equ (1 SHL 24) + +NORM_2 macro + ; movzx t0, BYTE PTR [buf] + shl cod, 8 + mov cod_L, BYTE PTR [buf] + shl range, 8 + ; or cod, t0 + inc buf +endm + + +NORM macro + cmp range, kTopValue + jae SHORT @F + NORM_2 +@@: +endm + + +; ---------- Branch MACROS ---------- + +UPDATE_0 macro probsArray:req, probOffset:req, probDisp:req + mov prob2, kBitModelTotal_reg + sub prob2, probBranch + shr prob2, kNumMoveBits + add probBranch, prob2 + PSTORE probBranch, probOffset * 1 + probsArray + probDisp * PMULT +endm + + +UPDATE_1 macro probsArray:req, probOffset:req, probDisp:req + sub prob2, range + sub cod, range + mov range, prob2 + mov prob2, probBranch + shr probBranch, kNumMoveBits + sub prob2, probBranch + PSTORE prob2, probOffset * 1 + probsArray + probDisp * PMULT +endm + + +CMP_COD macro probsArray:req, probOffset:req, probDisp:req + PLOAD probBranch, probOffset * 1 + probsArray + probDisp * PMULT + NORM + mov prob2, range + shr range, kNumBitModelTotalBits + imul range, probBranch + cmp cod, range +endm + + +IF_BIT_1_NOUP macro probsArray:req, probOffset:req, probDisp:req, toLabel:req + CMP_COD probsArray, probOffset, probDisp + jae toLabel +endm + + +IF_BIT_1 macro probsArray:req, probOffset:req, probDisp:req, toLabel:req + IF_BIT_1_NOUP probsArray, probOffset, probDisp, toLabel + UPDATE_0 probsArray, probOffset, probDisp +endm + + +IF_BIT_0_NOUP macro probsArray:req, probOffset:req, probDisp:req, toLabel:req + CMP_COD probsArray, probOffset, probDisp + jb toLabel +endm + + +; ---------- CMOV MACROS ---------- + +NORM_CALC macro prob:req + NORM + mov t0, range + shr range, kNumBitModelTotalBits + imul range, prob + sub t0, range + mov t1, cod + sub cod, range +endm + + +PUP macro prob:req, probPtr:req + sub t0, prob + ; only sar works for both 16/32 bit prob modes + sar t0, kNumMoveBits + add t0, prob + PSTORE t0, probPtr +endm + + +PUP_SUB macro prob:req, probPtr:req, symSub:req + sbb sym, symSub + PUP prob, probPtr +endm + + +PUP_COD macro prob:req, probPtr:req, symSub:req + mov t0, kBitModelOffset + cmovb cod, t1 + mov t1, sym + cmovb t0, kBitModelTotal_reg + PUP_SUB prob, probPtr, symSub +endm + + +BIT_0 macro prob:req, probNext:req + PLOAD prob, probs + 1 * PMULT + PLOAD probNext, probs + 1 * PMULT_2 + + NORM_CALC prob + + cmovae range, t0 + PLOAD t0, probs + 1 * PMULT_2 + PMULT + cmovae probNext, t0 + mov t0, kBitModelOffset + cmovb cod, t1 + cmovb t0, kBitModelTotal_reg + mov sym, 2 + PUP_SUB prob, probs + 1 * PMULT, 0 - 1 +endm + + +BIT_1 macro prob:req, probNext:req + PLOAD probNext, probs + sym_R * PMULT_2 + add sym, sym + + NORM_CALC prob + + cmovae range, t0 + PLOAD t0, probs + sym_R * PMULT + PMULT + cmovae probNext, t0 + PUP_COD prob, probs + t1_R * PMULT_HALF, 0 - 1 +endm + + +BIT_2 macro prob:req, symSub:req + add sym, sym + + NORM_CALC prob + + cmovae range, t0 + PUP_COD prob, probs + t1_R * PMULT_HALF, symSub +endm + + +; ---------- MATCHED LITERAL ---------- + +LITM_0 macro + mov offs, 256 * PMULT + shl match, (PSHIFT + 1) + mov bit, offs + and bit, match + PLOAD x1, probs + 256 * PMULT + bit_R * 1 + 1 * PMULT + lea prm, [probs + 256 * PMULT + bit_R * 1 + 1 * PMULT] + ; lea prm, [probs + 256 * PMULT + 1 * PMULT] + ; add prm, bit_R + xor offs, bit + add match, match + + NORM_CALC x1 + + cmovae offs, bit + mov bit, match + cmovae range, t0 + mov t0, kBitModelOffset + cmovb cod, t1 + cmovb t0, kBitModelTotal_reg + mov sym, 0 + PUP_SUB x1, prm, -2-1 +endm + + +LITM macro + and bit, offs + lea prm, [probs + offs_R * 1] + add prm, bit_R + PLOAD x1, prm + sym_R * PMULT + xor offs, bit + add sym, sym + add match, match + + NORM_CALC x1 + + cmovae offs, bit + mov bit, match + cmovae range, t0 + PUP_COD x1, prm + t1_R * PMULT_HALF, - 1 +endm + + +LITM_2 macro + and bit, offs + lea prm, [probs + offs_R * 1] + add prm, bit_R + PLOAD x1, prm + sym_R * PMULT + add sym, sym + + NORM_CALC x1 + + cmovae range, t0 + PUP_COD x1, prm + t1_R * PMULT_HALF, 256 - 1 +endm + + +; ---------- REVERSE BITS ---------- + +REV_0 macro prob:req, probNext:req + ; PLOAD prob, probs + 1 * PMULT + ; lea sym2_R, [probs + 2 * PMULT] + ; PLOAD probNext, probs + 2 * PMULT + PLOAD probNext, sym2_R + + NORM_CALC prob + + cmovae range, t0 + PLOAD t0, probs + 3 * PMULT + cmovae probNext, t0 + cmovb cod, t1 + mov t0, kBitModelOffset + cmovb t0, kBitModelTotal_reg + lea t1_R, [probs + 3 * PMULT] + cmovae sym2_R, t1_R + PUP prob, probs + 1 * PMULT +endm + + +REV_1 macro prob:req, probNext:req, step:req + add sym2_R, step * PMULT + PLOAD probNext, sym2_R + + NORM_CALC prob + + cmovae range, t0 + PLOAD t0, sym2_R + step * PMULT + cmovae probNext, t0 + cmovb cod, t1 + mov t0, kBitModelOffset + cmovb t0, kBitModelTotal_reg + lea t1_R, [sym2_R + step * PMULT] + cmovae sym2_R, t1_R + PUP prob, t1_R - step * PMULT_2 +endm + + +REV_2 macro prob:req, step:req + sub sym2_R, probs + shr sym2, PSHIFT + or sym, sym2 + + NORM_CALC prob + + cmovae range, t0 + lea t0, [sym - step] + cmovb sym, t0 + cmovb cod, t1 + mov t0, kBitModelOffset + cmovb t0, kBitModelTotal_reg + PUP prob, probs + sym2_R * PMULT +endm + + +REV_1_VAR macro prob:req + PLOAD prob, sym_R + mov probs, sym_R + add sym_R, sym2_R + + NORM_CALC prob + + cmovae range, t0 + lea t0_R, [sym_R + sym2_R] + cmovae sym_R, t0_R + mov t0, kBitModelOffset + cmovb cod, t1 + ; mov t1, kBitModelTotal + ; cmovb t0, t1 + cmovb t0, kBitModelTotal_reg + add sym2, sym2 + PUP prob, probs +endm + + + + +LIT_PROBS macro lpMaskParam:req + ; prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc); + mov t0, processedPos + shl t0, 8 + add sym, t0 + and sym, lpMaskParam + add probs_state_R, pbPos_R + mov x1, LOC lc2 + lea sym, dword ptr[sym_R + 2 * sym_R] + add probs, Literal * PMULT + shl sym, x1_L + add probs, sym_R + UPDATE_0 probs_state_R, 0, IsMatch + inc processedPos +endm + + + +kNumPosBitsMax equ 4 +kNumPosStatesMax equ (1 SHL kNumPosBitsMax) + +kLenNumLowBits equ 3 +kLenNumLowSymbols equ (1 SHL kLenNumLowBits) +kLenNumHighBits equ 8 +kLenNumHighSymbols equ (1 SHL kLenNumHighBits) +kNumLenProbs equ (2 * kLenNumLowSymbols * kNumPosStatesMax + kLenNumHighSymbols) + +LenLow equ 0 +LenChoice equ LenLow +LenChoice2 equ (LenLow + kLenNumLowSymbols) +LenHigh equ (LenLow + 2 * kLenNumLowSymbols * kNumPosStatesMax) + +kNumStates equ 12 +kNumStates2 equ 16 +kNumLitStates equ 7 + +kStartPosModelIndex equ 4 +kEndPosModelIndex equ 14 +kNumFullDistances equ (1 SHL (kEndPosModelIndex SHR 1)) + +kNumPosSlotBits equ 6 +kNumLenToPosStates equ 4 + +kNumAlignBits equ 4 +kAlignTableSize equ (1 SHL kNumAlignBits) + +kMatchMinLen equ 2 +kMatchSpecLenStart equ (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +kStartOffset equ 1664 +SpecPos equ (-kStartOffset) +IsRep0Long equ (SpecPos + kNumFullDistances) +RepLenCoder equ (IsRep0Long + (kNumStates2 SHL kNumPosBitsMax)) +LenCoder equ (RepLenCoder + kNumLenProbs) +IsMatch equ (LenCoder + kNumLenProbs) +kAlign equ (IsMatch + (kNumStates2 SHL kNumPosBitsMax)) +IsRep equ (kAlign + kAlignTableSize) +IsRepG0 equ (IsRep + kNumStates) +IsRepG1 equ (IsRepG0 + kNumStates) +IsRepG2 equ (IsRepG1 + kNumStates) +PosSlot equ (IsRepG2 + kNumStates) +Literal equ (PosSlot + (kNumLenToPosStates SHL kNumPosSlotBits)) +NUM_BASE_PROBS equ (Literal + kStartOffset) + +if kAlign ne 0 + .err +endif + +if NUM_BASE_PROBS ne 1984 + .err +endif + + +PTR_FIELD equ dq ? + +CLzmaDec_Asm struct + lc db ? + lp db ? + pb db ? + _pad_ db ? + dicSize dd ? + + probs_Spec PTR_FIELD + probs_1664 PTR_FIELD + dic_Spec PTR_FIELD + dicBufSize PTR_FIELD + dicPos_Spec PTR_FIELD + buf_Spec PTR_FIELD + + range_Spec dd ? + code_Spec dd ? + processedPos_Spec dd ? + checkDicSize dd ? + rep0 dd ? + rep1 dd ? + rep2 dd ? + rep3 dd ? + state_Spec dd ? + remainLen dd ? +CLzmaDec_Asm ends + + +CLzmaDec_Asm_Loc struct + OLD_RSP PTR_FIELD + lzmaPtr PTR_FIELD + _pad0_ PTR_FIELD + _pad1_ PTR_FIELD + _pad2_ PTR_FIELD + dicBufSize PTR_FIELD + probs_Spec PTR_FIELD + dic_Spec PTR_FIELD + + limit PTR_FIELD + bufLimit PTR_FIELD + lc2 dd ? + lpMask dd ? + pbMask dd ? + checkDicSize dd ? + + _pad_ dd ? + remainLen dd ? + dicPos_Spec PTR_FIELD + rep0 dd ? + rep1 dd ? + rep2 dd ? + rep3 dd ? +CLzmaDec_Asm_Loc ends + + +GLOB_2 equ [sym_R].CLzmaDec_Asm. +GLOB equ [r1].CLzmaDec_Asm. +LOC_0 equ [r0].CLzmaDec_Asm_Loc. +LOC equ [RSP].CLzmaDec_Asm_Loc. + + +COPY_VAR macro name + mov t0, GLOB_2 name + mov LOC_0 name, t0 +endm + + +RESTORE_VAR macro name + mov t0, LOC name + mov GLOB name, t0 +endm + + + +IsMatchBranch_Pre macro reg + ; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + mov pbPos, LOC pbMask + and pbPos, processedPos + shl pbPos, (kLenNumLowBits + 1 + PSHIFT) + lea probs_state_R, [probs + state_R] +endm + + +IsMatchBranch macro reg + IsMatchBranch_Pre + IF_BIT_1 probs_state_R, pbPos_R, IsMatch, IsMatch_label +endm + + +CheckLimits macro reg + cmp buf, LOC bufLimit + jae fin_OK + cmp dicPos, LOC limit + jae fin_OK +endm + + + +; RSP is (16x + 8) bytes aligned in WIN64-x64 +; LocalSize equ ((((SIZEOF CLzmaDec_Asm_Loc) + 7) / 16 * 16) + 8) + +PARAM_lzma equ REG_PARAM_0 +PARAM_limit equ REG_PARAM_1 +PARAM_bufLimit equ REG_PARAM_2 + +; MY_ALIGN_64 +MY_PROC LzmaDec_DecodeReal_3, 3 +MY_PUSH_PRESERVED_REGS + + lea r0, [RSP - (SIZEOF CLzmaDec_Asm_Loc)] + and r0, -128 + mov r5, RSP + mov RSP, r0 + mov LOC_0 Old_RSP, r5 + mov LOC_0 lzmaPtr, PARAM_lzma + + mov LOC_0 remainLen, 0 ; remainLen must be ZERO + + mov LOC_0 bufLimit, PARAM_bufLimit + mov sym_R, PARAM_lzma ; CLzmaDec_Asm_Loc pointer for GLOB_2 + mov dic, GLOB_2 dic_Spec + add PARAM_limit, dic + mov LOC_0 limit, PARAM_limit + + COPY_VAR(rep0) + COPY_VAR(rep1) + COPY_VAR(rep2) + COPY_VAR(rep3) + + mov dicPos, GLOB_2 dicPos_Spec + add dicPos, dic + mov LOC_0 dicPos_Spec, dicPos + mov LOC_0 dic_Spec, dic + + mov x1_L, GLOB_2 pb + mov t0, 1 + shl t0, x1_L + dec t0 + mov LOC_0 pbMask, t0 + + ; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + ; unsigned lc = p->prop.lc; + ; unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc); + + mov x1_L, GLOB_2 lc + mov x2, 100h + mov t0, x2 + shr x2, x1_L + ; inc x1 + add x1_L, PSHIFT + mov LOC_0 lc2, x1 + mov x1_L, GLOB_2 lp + shl t0, x1_L + sub t0, x2 + mov LOC_0 lpMask, t0 + mov lpMask_reg, t0 + + ; mov probs, GLOB_2 probs_Spec + ; add probs, kStartOffset SHL PSHIFT + mov probs, GLOB_2 probs_1664 + mov LOC_0 probs_Spec, probs + + mov t0_R, GLOB_2 dicBufSize + mov LOC_0 dicBufSize, t0_R + + mov x1, GLOB_2 checkDicSize + mov LOC_0 checkDicSize, x1 + + mov processedPos, GLOB_2 processedPos_Spec + + mov state, GLOB_2 state_Spec + shl state, PSHIFT + + mov buf, GLOB_2 buf_Spec + mov range, GLOB_2 range_Spec + mov cod, GLOB_2 code_Spec + mov kBitModelTotal_reg, kBitModelTotal + xor sym, sym + + ; if (processedPos != 0 || checkDicSize != 0) + or x1, processedPos + jz @f + + add t0_R, dic + cmp dicPos, dic + cmovnz t0_R, dicPos + movzx sym, byte ptr[t0_R - 1] + +@@: + IsMatchBranch_Pre + cmp state, 4 * PMULT + jb lit_end + cmp state, kNumLitStates * PMULT + jb lit_matched_end + jmp lz_end + + + + +; ---------- LITERAL ---------- +MY_ALIGN_64 +lit_start: + xor state, state +lit_start_2: + LIT_PROBS lpMask_reg + + ifdef _LZMA_SIZE_OPT + + PLOAD x1, probs + 1 * PMULT + mov sym, 1 +MY_ALIGN_16 +lit_loop: + BIT_1 x1, x2 + mov x1, x2 + cmp sym, 127 + jbe lit_loop + + else + + BIT_0 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + + endif + + BIT_2 x2, 256 - 1 + + ; mov dic, LOC dic_Spec + mov probs, LOC probs_Spec + IsMatchBranch_Pre + mov byte ptr[dicPos], sym_L + inc dicPos + + CheckLimits +lit_end: + IF_BIT_0_NOUP probs_state_R, pbPos_R, IsMatch, lit_start + + ; jmp IsMatch_label + +; ---------- MATCHES ---------- +; MY_ALIGN_32 +IsMatch_label: + UPDATE_1 probs_state_R, pbPos_R, IsMatch + IF_BIT_1 probs_state_R, 0, IsRep, IsRep_label + + add probs, LenCoder * PMULT + add state, kNumStates * PMULT + +; ---------- LEN DECODE ---------- +len_decode: + mov len_temp, 8 - 1 - kMatchMinLen + IF_BIT_0_NOUP probs, 0, 0, len_mid_0 + UPDATE_1 probs, 0, 0 + add probs, (1 SHL (kLenNumLowBits + PSHIFT)) + mov len_temp, -1 - kMatchMinLen + IF_BIT_0_NOUP probs, 0, 0, len_mid_0 + UPDATE_1 probs, 0, 0 + add probs, LenHigh * PMULT - (1 SHL (kLenNumLowBits + PSHIFT)) + mov sym, 1 + PLOAD x1, probs + 1 * PMULT + +MY_ALIGN_32 +len8_loop: + BIT_1 x1, x2 + mov x1, x2 + cmp sym, 64 + jb len8_loop + + mov len_temp, (kLenNumHighSymbols - kLenNumLowSymbols * 2) - 1 - kMatchMinLen + jmp len_mid_2 + +MY_ALIGN_32 +len_mid_0: + UPDATE_0 probs, 0, 0 + add probs, pbPos_R + BIT_0 x2, x1 +len_mid_2: + BIT_1 x1, x2 + BIT_2 x2, len_temp + mov probs, LOC probs_Spec + cmp state, kNumStates * PMULT + jb copy_match + + +; ---------- DECODE DISTANCE ---------- + ; probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + + mov t0, 3 + kMatchMinLen + cmp sym, 3 + kMatchMinLen + cmovb t0, sym + add probs, PosSlot * PMULT - (kMatchMinLen SHL (kNumPosSlotBits + PSHIFT)) + shl t0, (kNumPosSlotBits + PSHIFT) + add probs, t0_R + + ; sym = Len + ; mov LOC remainLen, sym + mov len_temp, sym + + ifdef _LZMA_SIZE_OPT + + PLOAD x1, probs + 1 * PMULT + mov sym, 1 +MY_ALIGN_16 +slot_loop: + BIT_1 x1, x2 + mov x1, x2 + cmp sym, 32 + jb slot_loop + + else + + BIT_0 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + + endif + + mov x1, sym + BIT_2 x2, 64-1 + + and sym, 3 + mov probs, LOC probs_Spec + cmp x1, 32 + kEndPosModelIndex / 2 + jb short_dist + + ; unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); + sub x1, (32 + 1 + kNumAlignBits) + ; distance = (2 | (distance & 1)); + or sym, 2 + PLOAD x2, probs + 1 * PMULT + shl sym, kNumAlignBits + 1 + lea sym2_R, [probs + 2 * PMULT] + + jmp direct_norm + ; lea t1, [sym_R + (1 SHL kNumAlignBits)] + ; cmp range, kTopValue + ; jb direct_norm + +; ---------- DIRECT DISTANCE ---------- +MY_ALIGN_32 +direct_loop: + shr range, 1 + mov t0, cod + sub cod, range + cmovs cod, t0 + cmovns sym, t1 + + comment ~ + sub cod, range + mov x2, cod + sar x2, 31 + lea sym, dword ptr [r2 + sym_R * 2 + 1] + and x2, range + add cod, x2 + ~ + dec x1 + je direct_end + + add sym, sym +direct_norm: + lea t1, [sym_R + (1 SHL kNumAlignBits)] + cmp range, kTopValue + jae near ptr direct_loop + ; we align for 32 here with "near ptr" command above + NORM_2 + jmp direct_loop + +MY_ALIGN_32 +direct_end: + ; prob = + kAlign; + ; distance <<= kNumAlignBits; + REV_0 x2, x1 + REV_1 x1, x2, 2 + REV_1 x2, x1, 4 + REV_2 x1, 8 + +decode_dist_end: + + ; if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) + + mov t0, LOC checkDicSize + test t0, t0 + cmove t0, processedPos + cmp sym, t0 + jae end_of_payload + + ; rep3 = rep2; + ; rep2 = rep1; + ; rep1 = rep0; + ; rep0 = distance + 1; + + inc sym + mov t0, LOC rep0 + mov t1, LOC rep1 + mov x1, LOC rep2 + mov LOC rep0, sym + ; mov sym, LOC remainLen + mov sym, len_temp + mov LOC rep1, t0 + mov LOC rep2, t1 + mov LOC rep3, x1 + + ; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + cmp state, (kNumStates + kNumLitStates) * PMULT + mov state, kNumLitStates * PMULT + mov t0, (kNumLitStates + 3) * PMULT + cmovae state, t0 + + +; ---------- COPY MATCH ---------- +copy_match: + + ; len += kMatchMinLen; + ; add sym, kMatchMinLen + + ; if ((rem = limit - dicPos) == 0) + ; { + ; p->dicPos = dicPos; + ; return SZ_ERROR_DATA; + ; } + mov cnt_R, LOC limit + sub cnt_R, dicPos + jz fin_ERROR + + ; curLen = ((rem < len) ? (unsigned)rem : len); + cmp cnt_R, sym_R + ; cmovae cnt_R, sym_R ; 64-bit + cmovae cnt, sym ; 32-bit + + mov dic, LOC dic_Spec + mov x1, LOC rep0 + + mov t0_R, dicPos + add dicPos, cnt_R + ; processedPos += curLen; + add processedPos, cnt + ; len -= curLen; + sub sym, cnt + mov LOC remainLen, sym + + sub t0_R, dic + + ; pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); + sub t0_R, r1 + jae @f + + mov r1, LOC dicBufSize + add t0_R, r1 + sub r1, t0_R + cmp cnt_R, r1 + ja copy_match_cross +@@: + ; if (curLen <= dicBufSize - pos) + +; ---------- COPY MATCH FAST ---------- + ; Byte *dest = dic + dicPos; + ; mov r1, dic + ; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + ; sub t0_R, dicPos + ; dicPos += curLen; + + ; const Byte *lim = dest + curLen; + add t0_R, dic + movzx sym, byte ptr[t0_R] + add t0_R, cnt_R + neg cnt_R + ; lea r1, [dicPos - 1] +copy_common: + dec dicPos + ; cmp LOC rep0, 1 + ; je rep0Label + + ; t0_R - src_lim + ; r1 - dest_lim - 1 + ; cnt_R - (-cnt) + + IsMatchBranch_Pre + inc cnt_R + jz copy_end +MY_ALIGN_16 +@@: + mov byte ptr[cnt_R * 1 + dicPos], sym_L + movzx sym, byte ptr[cnt_R * 1 + t0_R] + inc cnt_R + jnz @b + +copy_end: +lz_end_match: + mov byte ptr[dicPos], sym_L + inc dicPos + + ; IsMatchBranch_Pre + CheckLimits +lz_end: + IF_BIT_1_NOUP probs_state_R, pbPos_R, IsMatch, IsMatch_label + + + +; ---------- LITERAL MATCHED ---------- + + LIT_PROBS LOC lpMask + + ; matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + mov x1, LOC rep0 + ; mov dic, LOC dic_Spec + mov LOC dicPos_Spec, dicPos + + ; state -= (state < 10) ? 3 : 6; + lea t0, [state_R - 6 * PMULT] + sub state, 3 * PMULT + cmp state, 7 * PMULT + cmovae state, t0 + + sub dicPos, dic + sub dicPos, r1 + jae @f + add dicPos, LOC dicBufSize +@@: + comment ~ + xor t0, t0 + sub dicPos, r1 + cmovb t0_R, LOC dicBufSize + ~ + + movzx match, byte ptr[dic + dicPos * 1] + + ifdef _LZMA_SIZE_OPT + + mov offs, 256 * PMULT + shl match, (PSHIFT + 1) + mov bit, match + mov sym, 1 +MY_ALIGN_16 +litm_loop: + LITM + cmp sym, 256 + jb litm_loop + sub sym, 256 + + else + + LITM_0 + LITM + LITM + LITM + LITM + LITM + LITM + LITM_2 + + endif + + mov probs, LOC probs_Spec + IsMatchBranch_Pre + ; mov dic, LOC dic_Spec + mov dicPos, LOC dicPos_Spec + mov byte ptr[dicPos], sym_L + inc dicPos + + CheckLimits +lit_matched_end: + IF_BIT_1_NOUP probs_state_R, pbPos_R, IsMatch, IsMatch_label + ; IsMatchBranch + mov lpMask_reg, LOC lpMask + sub state, 3 * PMULT + jmp lit_start_2 + + + +; ---------- REP 0 LITERAL ---------- +MY_ALIGN_32 +IsRep0Short_label: + UPDATE_0 probs_state_R, pbPos_R, IsRep0Long + + ; dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + mov dic, LOC dic_Spec + mov t0_R, dicPos + mov probBranch, LOC rep0 + sub t0_R, dic + + sub probs, RepLenCoder * PMULT + inc processedPos + ; state = state < kNumLitStates ? 9 : 11; + or state, 1 * PMULT + IsMatchBranch_Pre + + sub t0_R, probBranch_R + jae @f + add t0_R, LOC dicBufSize +@@: + movzx sym, byte ptr[dic + t0_R * 1] + jmp lz_end_match + + +MY_ALIGN_32 +IsRep_label: + UPDATE_1 probs_state_R, 0, IsRep + + ; The (checkDicSize == 0 && processedPos == 0) case was checked before in LzmaDec.c with kBadRepCode. + ; So we don't check it here. + + ; mov t0, processedPos + ; or t0, LOC checkDicSize + ; jz fin_ERROR_2 + + ; state = state < kNumLitStates ? 8 : 11; + cmp state, kNumLitStates * PMULT + mov state, 8 * PMULT + mov probBranch, 11 * PMULT + cmovae state, probBranch + + ; prob = probs + RepLenCoder; + add probs, RepLenCoder * PMULT + + IF_BIT_1 probs_state_R, 0, IsRepG0, IsRepG0_label + IF_BIT_0_NOUP probs_state_R, pbPos_R, IsRep0Long, IsRep0Short_label + UPDATE_1 probs_state_R, pbPos_R, IsRep0Long + jmp len_decode + +MY_ALIGN_32 +IsRepG0_label: + UPDATE_1 probs_state_R, 0, IsRepG0 + mov dist2, LOC rep0 + mov dist, LOC rep1 + mov LOC rep1, dist2 + + IF_BIT_1 probs_state_R, 0, IsRepG1, IsRepG1_label + mov LOC rep0, dist + jmp len_decode + +; MY_ALIGN_32 +IsRepG1_label: + UPDATE_1 probs_state_R, 0, IsRepG1 + mov dist2, LOC rep2 + mov LOC rep2, dist + + IF_BIT_1 probs_state_R, 0, IsRepG2, IsRepG2_label + mov LOC rep0, dist2 + jmp len_decode + +; MY_ALIGN_32 +IsRepG2_label: + UPDATE_1 probs_state_R, 0, IsRepG2 + mov dist, LOC rep3 + mov LOC rep3, dist2 + mov LOC rep0, dist + jmp len_decode + + + +; ---------- SPEC SHORT DISTANCE ---------- + +MY_ALIGN_32 +short_dist: + sub x1, 32 + 1 + jbe decode_dist_end + or sym, 2 + shl sym, x1_L + lea sym_R, [probs + sym_R * PMULT + SpecPos * PMULT + 1 * PMULT] + mov sym2, PMULT ; step +MY_ALIGN_32 +spec_loop: + REV_1_VAR x2 + dec x1 + jnz spec_loop + + mov probs, LOC probs_Spec + sub sym, sym2 + sub sym, SpecPos * PMULT + sub sym_R, probs + shr sym, PSHIFT + + jmp decode_dist_end + + +; ---------- COPY MATCH CROSS ---------- +copy_match_cross: + ; t0_R - src pos + ; r1 - len to dicBufSize + ; cnt_R - total copy len + + mov t1_R, t0_R ; srcPos + mov t0_R, dic + mov r1, LOC dicBufSize ; + neg cnt_R +@@: + movzx sym, byte ptr[t1_R * 1 + t0_R] + inc t1_R + mov byte ptr[cnt_R * 1 + dicPos], sym_L + inc cnt_R + cmp t1_R, r1 + jne @b + + movzx sym, byte ptr[t0_R] + sub t0_R, cnt_R + jmp copy_common + + + + +fin_ERROR: + mov LOC remainLen, len_temp +; fin_ERROR_2: + mov sym, 1 + jmp fin + +end_of_payload: + cmp sym, 0FFFFFFFFh ; -1 + jne fin_ERROR + + mov LOC remainLen, kMatchSpecLenStart + sub state, kNumStates * PMULT + +fin_OK: + xor sym, sym + +fin: + NORM + + mov r1, LOC lzmaPtr + + sub dicPos, LOC dic_Spec + mov GLOB dicPos_Spec, dicPos + mov GLOB buf_Spec, buf + mov GLOB range_Spec, range + mov GLOB code_Spec, cod + shr state, PSHIFT + mov GLOB state_Spec, state + mov GLOB processedPos_Spec, processedPos + + RESTORE_VAR(remainLen) + RESTORE_VAR(rep0) + RESTORE_VAR(rep1) + RESTORE_VAR(rep2) + RESTORE_VAR(rep3) + + mov x0, sym + + mov RSP, LOC Old_RSP + +MY_POP_PRESERVED_REGS +MY_ENDP + +_TEXT$LZMADECOPT ENDS + +end diff --git a/other-licenses/7zstub/src/Asm/x86/XzCrc64Opt.asm b/other-licenses/7zstub/src/Asm/x86/XzCrc64Opt.asm new file mode 100644 index 0000000000..3e6d490266 --- /dev/null +++ b/other-licenses/7zstub/src/Asm/x86/XzCrc64Opt.asm @@ -0,0 +1,205 @@ +; XzCrc64Opt.asm -- CRC64 calculation : optimized version +; 2011-06-28 : Igor Pavlov : Public domain + +include 7zAsm.asm + +MY_ASM_START + +ifdef x64 + + rD equ r9 + rN equ r10 + + num_VAR equ r8 + table_VAR equ r9 + + SRCDAT equ rN + rD + +CRC_XOR macro dest:req, src:req, t:req + xor dest, QWORD PTR [r5 + src * 8 + 0800h * t] +endm + +CRC1b macro + movzx x6, BYTE PTR [rD] + inc rD + movzx x3, x0_L + xor x6, x3 + shr r0, 8 + CRC_XOR r0, r6, 0 + dec rN +endm + +MY_PROLOG macro crc_end:req + MY_PUSH_4_REGS + + mov r0, r1 + mov rN, num_VAR + mov r5, table_VAR + mov rD, r2 + test rN, rN + jz crc_end + @@: + test rD, 3 + jz @F + CRC1b + jnz @B + @@: + cmp rN, 8 + jb crc_end + add rN, rD + mov num_VAR, rN + sub rN, 4 + and rN, NOT 3 + sub rD, rN + mov x1, [SRCDAT] + xor r0, r1 + add rN, 4 +endm + +MY_EPILOG macro crc_end:req + sub rN, 4 + mov x1, [SRCDAT] + xor r0, r1 + mov rD, rN + mov rN, num_VAR + sub rN, rD + crc_end: + test rN, rN + jz @F + CRC1b + jmp crc_end + @@: + MY_POP_4_REGS +endm + +MY_PROC XzCrc64UpdateT4, 4 + MY_PROLOG crc_end_4 + align 16 + main_loop_4: + mov x1, [SRCDAT] + movzx x2, x0_L + movzx x3, x0_H + shr r0, 16 + movzx x6, x0_L + movzx x7, x0_H + shr r0, 16 + CRC_XOR r1, r2, 3 + CRC_XOR r0, r3, 2 + CRC_XOR r1, r6, 1 + CRC_XOR r0, r7, 0 + xor r0, r1 + + add rD, 4 + jnz main_loop_4 + + MY_EPILOG crc_end_4 +MY_ENDP + +else + + rD equ r1 + rN equ r7 + + crc_val equ (REG_SIZE * 5) + crc_table equ (8 + crc_val) + table_VAR equ [r4 + crc_table] + num_VAR equ table_VAR + + + SRCDAT equ rN + rD + +CRC macro op0:req, op1:req, dest0:req, dest1:req, src:req, t:req + op0 dest0, DWORD PTR [r5 + src * 8 + 0800h * t] + op1 dest1, DWORD PTR [r5 + src * 8 + 0800h * t + 4] +endm + +CRC_XOR macro dest0:req, dest1:req, src:req, t:req + CRC xor, xor, dest0, dest1, src, t +endm + + +CRC1b macro + movzx x6, BYTE PTR [rD] + inc rD + movzx x3, x0_L + xor x6, x3 + shrd r0, r2, 8 + shr r2, 8 + CRC_XOR r0, r2, r6, 0 + dec rN +endm + +MY_PROLOG macro crc_end:req + MY_PUSH_4_REGS + + mov rN, r2 + + mov x0, [r4 + crc_val] + mov x2, [r4 + crc_val + 4] + mov r5, table_VAR + test rN, rN + jz crc_end + @@: + test rD, 3 + jz @F + CRC1b + jnz @B + @@: + cmp rN, 8 + jb crc_end + add rN, rD + + mov num_VAR, rN + + sub rN, 4 + and rN, NOT 3 + sub rD, rN + xor r0, [SRCDAT] + add rN, 4 +endm + +MY_EPILOG macro crc_end:req + sub rN, 4 + xor r0, [SRCDAT] + + mov rD, rN + mov rN, num_VAR + sub rN, rD + crc_end: + test rN, rN + jz @F + CRC1b + jmp crc_end + @@: + MY_POP_4_REGS +endm + +MY_PROC XzCrc64UpdateT4, 5 + MY_PROLOG crc_end_4 + movzx x6, x0_L + align 16 + main_loop_4: + mov r3, [SRCDAT] + xor r3, r2 + + CRC xor, mov, r3, r2, r6, 3 + movzx x6, x0_H + shr r0, 16 + CRC_XOR r3, r2, r6, 2 + + movzx x6, x0_L + movzx x0, x0_H + CRC_XOR r3, r2, r6, 1 + CRC_XOR r3, r2, r0, 0 + movzx x6, x3_L + mov r0, r3 + + add rD, 4 + jnz main_loop_4 + + MY_EPILOG crc_end_4 +MY_ENDP + +endif + +end diff --git a/other-licenses/7zstub/src/C/7z.h b/other-licenses/7zstub/src/C/7z.h new file mode 100644 index 0000000000..82813c298b --- /dev/null +++ b/other-licenses/7zstub/src/C/7z.h @@ -0,0 +1,202 @@ +/* 7z.h -- 7z interface +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_H +#define __7Z_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define k7zStartHeaderSize 0x20 +#define k7zSignatureSize 6 + +extern const Byte k7zSignature[k7zSignatureSize]; + +typedef struct +{ + const Byte *Data; + size_t Size; +} CSzData; + +/* CSzCoderInfo & CSzFolder support only default methods */ + +typedef struct +{ + size_t PropsOffset; + UInt32 MethodID; + Byte NumStreams; + Byte PropsSize; +} CSzCoderInfo; + +typedef struct +{ + UInt32 InIndex; + UInt32 OutIndex; +} CSzBond; + +#define SZ_NUM_CODERS_IN_FOLDER_MAX 4 +#define SZ_NUM_BONDS_IN_FOLDER_MAX 3 +#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4 + +typedef struct +{ + UInt32 NumCoders; + UInt32 NumBonds; + UInt32 NumPackStreams; + UInt32 UnpackStream; + UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; + CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX]; + CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; +} CSzFolder; + + +SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd); + +typedef struct +{ + UInt32 Low; + UInt32 High; +} CNtfsFileTime; + +typedef struct +{ + Byte *Defs; /* MSB 0 bit numbering */ + UInt32 *Vals; +} CSzBitUi32s; + +typedef struct +{ + Byte *Defs; /* MSB 0 bit numbering */ + // UInt64 *Vals; + CNtfsFileTime *Vals; +} CSzBitUi64s; + +#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) + +#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) + +typedef struct +{ + UInt32 NumPackStreams; + UInt32 NumFolders; + + UInt64 *PackPositions; // NumPackStreams + 1 + CSzBitUi32s FolderCRCs; // NumFolders + + size_t *FoCodersOffsets; // NumFolders + 1 + UInt32 *FoStartPackStreamIndex; // NumFolders + 1 + UInt32 *FoToCoderUnpackSizes; // NumFolders + 1 + Byte *FoToMainUnpackSizeIndex; // NumFolders + UInt64 *CoderUnpackSizes; // for all coders in all folders + + Byte *CodersData; +} CSzAr; + +UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex); + +SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, + ISzAllocPtr allocMain); + +typedef struct +{ + CSzAr db; + + UInt64 startPosAfterHeader; + UInt64 dataPos; + + UInt32 NumFiles; + + UInt64 *UnpackPositions; // NumFiles + 1 + // Byte *IsEmptyFiles; + Byte *IsDirs; + CSzBitUi32s CRCs; + + CSzBitUi32s Attribs; + // CSzBitUi32s Parents; + CSzBitUi64s MTime; + CSzBitUi64s CTime; + + UInt32 *FolderToFile; // NumFolders + 1 + UInt32 *FileToFolder; // NumFiles + + size_t *FileNameOffsets; /* in 2-byte steps */ + Byte *FileNames; /* UTF-16-LE */ +} CSzArEx; + +#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i)) + +#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i]) + +void SzArEx_Init(CSzArEx *p); +void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc); +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); + +/* +if dest == NULL, the return value specifies the required size of the buffer, + in 16-bit characters, including the null-terminating character. +if dest != NULL, the return value specifies the number of 16-bit characters that + are written to the dest, including the null-terminating character. */ + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); + +/* +size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex); +UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); +*/ + + + +/* + SzArEx_Extract extracts file from archive + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +SRes SzArEx_Extract( + const CSzArEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp); + + +/* +SzArEx_Open Errors: +SZ_ERROR_NO_ARCHIVE +SZ_ERROR_ARCHIVE +SZ_ERROR_UNSUPPORTED +SZ_ERROR_MEM +SZ_ERROR_CRC +SZ_ERROR_INPUT_EOF +SZ_ERROR_FAIL +*/ + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, + ISzAllocPtr allocMain, ISzAllocPtr allocTemp); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/7zAlloc.c b/other-licenses/7zstub/src/C/7zAlloc.c new file mode 100644 index 0000000000..ea32809c65 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zAlloc.c @@ -0,0 +1,80 @@ +/* 7zAlloc.c -- Allocation functions +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zAlloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ + +#ifdef _SZ_ALLOC_DEBUG + +#ifdef _WIN32 +#include +#endif + +#include +int g_allocCount = 0; +int g_allocCountTemp = 0; + +#endif + +void *SzAlloc(ISzAllocPtr p, size_t size) +{ + UNUSED_VAR(p); + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10u bytes; count = %10d", (unsigned)size, g_allocCount); + g_allocCount++; + #endif + return malloc(size); +} + +void SzFree(ISzAllocPtr p, void *address) +{ + UNUSED_VAR(p); + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCount--; + fprintf(stderr, "\nFree; count = %10d", g_allocCount); + } + #endif + free(address); +} + +void *SzAllocTemp(ISzAllocPtr p, size_t size) +{ + UNUSED_VAR(p); + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_temp %10u bytes; count = %10d", (unsigned)size, g_allocCountTemp); + g_allocCountTemp++; + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + #endif + return malloc(size); +} + +void SzFreeTemp(ISzAllocPtr p, void *address) +{ + UNUSED_VAR(p); + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCountTemp--; + fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); + } + #ifdef _WIN32 + HeapFree(GetProcessHeap(), 0, address); + return; + #endif + #endif + free(address); +} diff --git a/other-licenses/7zstub/src/C/7zAlloc.h b/other-licenses/7zstub/src/C/7zAlloc.h new file mode 100644 index 0000000000..c0f89d73cb --- /dev/null +++ b/other-licenses/7zstub/src/C/7zAlloc.h @@ -0,0 +1,19 @@ +/* 7zAlloc.h -- Allocation functions +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void *SzAlloc(ISzAllocPtr p, size_t size); +void SzFree(ISzAllocPtr p, void *address); + +void *SzAllocTemp(ISzAllocPtr p, size_t size); +void SzFreeTemp(ISzAllocPtr p, void *address); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/7zArcIn.c b/other-licenses/7zstub/src/C/7zArcIn.c new file mode 100644 index 0000000000..70d7175e3d --- /dev/null +++ b/other-licenses/7zstub/src/C/7zArcIn.c @@ -0,0 +1,1771 @@ +/* 7zArcIn.c -- 7z Input functions +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7z.h" +#include "7zBuf.h" +#include "7zCrc.h" +#include "CpuArch.h" + +#define MY_ALLOC(T, p, size, alloc) { \ + if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } + +#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) } + +#define MY_ALLOC_AND_CPY(to, size, from, alloc) \ + { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); } + +#define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \ + { if ((size) == 0) p = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } } + +#define k7zMajorVersion 0 + +enum EIdEnum +{ + k7zIdEnd, + k7zIdHeader, + k7zIdArchiveProperties, + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + k7zIdPackInfo, + k7zIdUnpackInfo, + k7zIdSubStreamsInfo, + k7zIdSize, + k7zIdCRC, + k7zIdFolder, + k7zIdCodersUnpackSize, + k7zIdNumUnpackStream, + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + k7zIdName, + k7zIdCTime, + k7zIdATime, + k7zIdMTime, + k7zIdWinAttrib, + k7zIdComment, + k7zIdEncodedHeader, + k7zIdStartPos, + k7zIdDummy + // k7zNtSecure, + // k7zParent, + // k7zIsReal +}; + +const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + +#define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } + +static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) +{ + if (num == 0) + { + p->Defs = NULL; + p->Vals = NULL; + } + else + { + MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc); + MY_ALLOC(UInt32, p->Vals, num, alloc); + } + return SZ_OK; +} + +void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; + ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; +} + +#define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } + +void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; + ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; +} + + +static void SzAr_Init(CSzAr *p) +{ + p->NumPackStreams = 0; + p->NumFolders = 0; + + p->PackPositions = NULL; + SzBitUi32s_Init(&p->FolderCRCs); + + p->FoCodersOffsets = NULL; + p->FoStartPackStreamIndex = NULL; + p->FoToCoderUnpackSizes = NULL; + p->FoToMainUnpackSizeIndex = NULL; + p->CoderUnpackSizes = NULL; + + p->CodersData = NULL; +} + +static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->PackPositions); + SzBitUi32s_Free(&p->FolderCRCs, alloc); + + ISzAlloc_Free(alloc, p->FoCodersOffsets); + ISzAlloc_Free(alloc, p->FoStartPackStreamIndex); + ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes); + ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex); + ISzAlloc_Free(alloc, p->CoderUnpackSizes); + + ISzAlloc_Free(alloc, p->CodersData); + + SzAr_Init(p); +} + + +void SzArEx_Init(CSzArEx *p) +{ + SzAr_Init(&p->db); + + p->NumFiles = 0; + p->dataPos = 0; + + p->UnpackPositions = NULL; + p->IsDirs = NULL; + + p->FolderToFile = NULL; + p->FileToFolder = NULL; + + p->FileNameOffsets = NULL; + p->FileNames = NULL; + + SzBitUi32s_Init(&p->CRCs); + SzBitUi32s_Init(&p->Attribs); + // SzBitUi32s_Init(&p->Parents); + SzBitUi64s_Init(&p->MTime); + SzBitUi64s_Init(&p->CTime); +} + +void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->UnpackPositions); + ISzAlloc_Free(alloc, p->IsDirs); + + ISzAlloc_Free(alloc, p->FolderToFile); + ISzAlloc_Free(alloc, p->FileToFolder); + + ISzAlloc_Free(alloc, p->FileNameOffsets); + ISzAlloc_Free(alloc, p->FileNames); + + SzBitUi32s_Free(&p->CRCs, alloc); + SzBitUi32s_Free(&p->Attribs, alloc); + // SzBitUi32s_Free(&p->Parents, alloc); + SzBitUi64s_Free(&p->MTime, alloc); + SzBitUi64s_Free(&p->CTime, alloc); + + SzAr_Free(&p->db, alloc); + SzArEx_Init(p); +} + + +static int TestSignatureCandidate(const Byte *testBytes) +{ + unsigned i; + for (i = 0; i < k7zSignatureSize; i++) + if (testBytes[i] != k7zSignature[i]) + return 0; + return 1; +} + +#define SzData_Clear(p) { (p)->Data = NULL; (p)->Size = 0; } + +#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++; +#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest) +#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++; + +#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } +#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } + +#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \ + dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4); + +static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) +{ + Byte firstByte, mask; + unsigned i; + UInt32 v; + + SZ_READ_BYTE(firstByte); + if ((firstByte & 0x80) == 0) + { + *value = firstByte; + return SZ_OK; + } + SZ_READ_BYTE(v); + if ((firstByte & 0x40) == 0) + { + *value = (((UInt32)firstByte & 0x3F) << 8) | v; + return SZ_OK; + } + SZ_READ_BYTE(mask); + *value = v | ((UInt32)mask << 8); + mask = 0x20; + for (i = 2; i < 8; i++) + { + Byte b; + if ((firstByte & mask) == 0) + { + UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1); + *value |= (highPart << (8 * i)); + return SZ_OK; + } + SZ_READ_BYTE(b); + *value |= ((UInt64)b << (8 * i)); + mask >>= 1; + } + return SZ_OK; +} + + +static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) +{ + Byte firstByte; + UInt64 value64; + if (sd->Size == 0) + return SZ_ERROR_ARCHIVE; + firstByte = *sd->Data; + if ((firstByte & 0x80) == 0) + { + *value = firstByte; + sd->Data++; + sd->Size--; + return SZ_OK; + } + RINOK(ReadNumber(sd, &value64)); + if (value64 >= (UInt32)0x80000000 - 1) + return SZ_ERROR_UNSUPPORTED; + if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4))) + return SZ_ERROR_UNSUPPORTED; + *value = (UInt32)value64; + return SZ_OK; +} + +#define ReadID(sd, value) ReadNumber(sd, value) + +static SRes SkipData(CSzData *sd) +{ + UInt64 size; + RINOK(ReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA(sd, size); + return SZ_OK; +} + +static SRes WaitId(CSzData *sd, UInt32 id) +{ + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == id) + return SZ_OK; + if (type == k7zIdEnd) + return SZ_ERROR_ARCHIVE; + RINOK(SkipData(sd)); + } +} + +static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v) +{ + UInt32 numBytes = (numItems + 7) >> 3; + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + *v = sd->Data; + SKIP_DATA(sd, numBytes); + return SZ_OK; +} + +static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) +{ + Byte b = 0; + unsigned m = 0; + UInt32 sum = 0; + for (; numItems != 0; numItems--) + { + if (m == 0) + { + b = *bits++; + m = 8; + } + m--; + sum += ((b >> m) & 1); + } + return sum; +} + +static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc) +{ + Byte allAreDefined; + Byte *v2; + UInt32 numBytes = (numItems + 7) >> 3; + *v = NULL; + SZ_READ_BYTE(allAreDefined); + if (numBytes == 0) + return SZ_OK; + if (allAreDefined == 0) + { + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc); + SKIP_DATA(sd, numBytes); + return SZ_OK; + } + MY_ALLOC(Byte, *v, numBytes, alloc); + v2 = *v; + memset(v2, 0xFF, (size_t)numBytes); + { + unsigned numBits = (unsigned)numItems & 7; + if (numBits != 0) + v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); + } + return SZ_OK; +} + +static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) +{ + UInt32 i; + CSzData sd; + UInt32 *vals; + const Byte *defs; + MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc); + sd = *sd2; + defs = crcs->Defs; + vals = crcs->Vals; + for (i = 0; i < numItems; i++) + if (SzBitArray_Check(defs, i)) + { + SZ_READ_32(vals[i]); + } + else + vals[i] = 0; + *sd2 = sd; + return SZ_OK; +} + +static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) +{ + SzBitUi32s_Free(crcs, alloc); + RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)); + return ReadUi32s(sd, numItems, crcs, alloc); +} + +static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) +{ + Byte allAreDefined; + UInt32 numDefined = numItems; + SZ_READ_BYTE(allAreDefined); + if (!allAreDefined) + { + size_t numBytes = (numItems + 7) >> 3; + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + numDefined = CountDefinedBits(sd->Data, numItems); + SKIP_DATA(sd, numBytes); + } + if (numDefined > (sd->Size >> 2)) + return SZ_ERROR_ARCHIVE; + SKIP_DATA(sd, (size_t)numDefined * 4); + return SZ_OK; +} + +static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) +{ + RINOK(SzReadNumber32(sd, &p->NumPackStreams)); + + RINOK(WaitId(sd, k7zIdSize)); + MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc); + { + UInt64 sum = 0; + UInt32 i; + UInt32 numPackStreams = p->NumPackStreams; + for (i = 0; i < numPackStreams; i++) + { + UInt64 packSize; + p->PackPositions[i] = sum; + RINOK(ReadNumber(sd, &packSize)); + sum += packSize; + if (sum < packSize) + return SZ_ERROR_ARCHIVE; + } + p->PackPositions[i] = sum; + } + + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + /* CRC of packed streams is unused now */ + RINOK(SkipBitUi32s(sd, p->NumPackStreams)); + continue; + } + RINOK(SkipData(sd)); + } +} + +/* +static SRes SzReadSwitch(CSzData *sd) +{ + Byte external; + RINOK(SzReadByte(sd, &external)); + return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; +} +*/ + +#define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) + +SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) +{ + UInt32 numCoders, i; + UInt32 numInStreams = 0; + const Byte *dataStart = sd->Data; + + f->NumCoders = 0; + f->NumBonds = 0; + f->NumPackStreams = 0; + f->UnpackStream = 0; + + RINOK(SzReadNumber32(sd, &numCoders)); + if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (i = 0; i < numCoders; i++) + { + Byte mainByte; + CSzCoderInfo *coder = f->Coders + i; + unsigned idSize, j; + UInt64 id; + + SZ_READ_BYTE(mainByte); + if ((mainByte & 0xC0) != 0) + return SZ_ERROR_UNSUPPORTED; + + idSize = (unsigned)(mainByte & 0xF); + if (idSize > sizeof(id)) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd->Size) + return SZ_ERROR_ARCHIVE; + id = 0; + for (j = 0; j < idSize; j++) + { + id = ((id << 8) | *sd->Data); + sd->Data++; + sd->Size--; + } + if (id > (UInt32)0xFFFFFFFF) + return SZ_ERROR_UNSUPPORTED; + coder->MethodID = (UInt32)id; + + coder->NumStreams = 1; + coder->PropsOffset = 0; + coder->PropsSize = 0; + + if ((mainByte & 0x10) != 0) + { + UInt32 numStreams; + + RINOK(SzReadNumber32(sd, &numStreams)); + if (numStreams > k_NumCodersStreams_in_Folder_MAX) + return SZ_ERROR_UNSUPPORTED; + coder->NumStreams = (Byte)numStreams; + + RINOK(SzReadNumber32(sd, &numStreams)); + if (numStreams != 1) + return SZ_ERROR_UNSUPPORTED; + } + + numInStreams += coder->NumStreams; + + if (numInStreams > k_NumCodersStreams_in_Folder_MAX) + return SZ_ERROR_UNSUPPORTED; + + if ((mainByte & 0x20) != 0) + { + UInt32 propsSize = 0; + RINOK(SzReadNumber32(sd, &propsSize)); + if (propsSize > sd->Size) + return SZ_ERROR_ARCHIVE; + if (propsSize >= 0x80) + return SZ_ERROR_UNSUPPORTED; + coder->PropsOffset = sd->Data - dataStart; + coder->PropsSize = (Byte)propsSize; + sd->Data += (size_t)propsSize; + sd->Size -= (size_t)propsSize; + } + } + + /* + if (numInStreams == 1 && numCoders == 1) + { + f->NumPackStreams = 1; + f->PackStreams[0] = 0; + } + else + */ + { + Byte streamUsed[k_NumCodersStreams_in_Folder_MAX]; + UInt32 numBonds, numPackStreams; + + numBonds = numCoders - 1; + if (numInStreams < numBonds) + return SZ_ERROR_ARCHIVE; + if (numBonds > SZ_NUM_BONDS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + f->NumBonds = numBonds; + + numPackStreams = numInStreams - numBonds; + if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + f->NumPackStreams = numPackStreams; + + for (i = 0; i < numInStreams; i++) + streamUsed[i] = False; + + if (numBonds != 0) + { + Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX]; + + for (i = 0; i < numCoders; i++) + coderUsed[i] = False; + + for (i = 0; i < numBonds; i++) + { + CSzBond *bp = f->Bonds + i; + + RINOK(SzReadNumber32(sd, &bp->InIndex)); + if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex]) + return SZ_ERROR_ARCHIVE; + streamUsed[bp->InIndex] = True; + + RINOK(SzReadNumber32(sd, &bp->OutIndex)); + if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex]) + return SZ_ERROR_ARCHIVE; + coderUsed[bp->OutIndex] = True; + } + + for (i = 0; i < numCoders; i++) + if (!coderUsed[i]) + { + f->UnpackStream = i; + break; + } + + if (i == numCoders) + return SZ_ERROR_ARCHIVE; + } + + if (numPackStreams == 1) + { + for (i = 0; i < numInStreams; i++) + if (!streamUsed[i]) + break; + if (i == numInStreams) + return SZ_ERROR_ARCHIVE; + f->PackStreams[0] = i; + } + else + for (i = 0; i < numPackStreams; i++) + { + UInt32 index; + RINOK(SzReadNumber32(sd, &index)); + if (index >= numInStreams || streamUsed[index]) + return SZ_ERROR_ARCHIVE; + streamUsed[index] = True; + f->PackStreams[i] = index; + } + } + + f->NumCoders = numCoders; + + return SZ_OK; +} + + +static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) +{ + CSzData sd; + sd = *sd2; + for (; num != 0; num--) + { + Byte firstByte, mask; + unsigned i; + SZ_READ_BYTE_2(firstByte); + if ((firstByte & 0x80) == 0) + continue; + if ((firstByte & 0x40) == 0) + { + if (sd.Size == 0) + return SZ_ERROR_ARCHIVE; + sd.Size--; + sd.Data++; + continue; + } + mask = 0x20; + for (i = 2; i < 8 && (firstByte & mask) != 0; i++) + mask >>= 1; + if (i > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, i); + } + *sd2 = sd; + return SZ_OK; +} + + +#define k_Scan_NumCoders_MAX 64 +#define k_Scan_NumCodersStreams_in_Folder_MAX 64 + + +static SRes ReadUnpackInfo(CSzAr *p, + CSzData *sd2, + UInt32 numFoldersMax, + const CBuf *tempBufs, UInt32 numTempBufs, + ISzAllocPtr alloc) +{ + CSzData sd; + + UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex; + const Byte *startBufPtr; + Byte external; + + RINOK(WaitId(sd2, k7zIdFolder)); + + RINOK(SzReadNumber32(sd2, &numFolders)); + if (numFolders > numFoldersMax) + return SZ_ERROR_UNSUPPORTED; + p->NumFolders = numFolders; + + SZ_READ_BYTE_SD(sd2, external); + if (external == 0) + sd = *sd2; + else + { + UInt32 index; + RINOK(SzReadNumber32(sd2, &index)); + if (index >= numTempBufs) + return SZ_ERROR_ARCHIVE; + sd.Data = tempBufs[index].data; + sd.Size = tempBufs[index].size; + } + + MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc); + MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc); + MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc); + MY_ALLOC(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc); + + startBufPtr = sd.Data; + + packStreamIndex = 0; + numCodersOutStreams = 0; + + for (fo = 0; fo < numFolders; fo++) + { + UInt32 numCoders, ci, numInStreams = 0; + + p->FoCodersOffsets[fo] = sd.Data - startBufPtr; + + RINOK(SzReadNumber32(&sd, &numCoders)); + if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (ci = 0; ci < numCoders; ci++) + { + Byte mainByte; + unsigned idSize; + UInt32 coderInStreams; + + SZ_READ_BYTE_2(mainByte); + if ((mainByte & 0xC0) != 0) + return SZ_ERROR_UNSUPPORTED; + idSize = (mainByte & 0xF); + if (idSize > 8) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, idSize); + + coderInStreams = 1; + + if ((mainByte & 0x10) != 0) + { + UInt32 coderOutStreams; + RINOK(SzReadNumber32(&sd, &coderInStreams)); + RINOK(SzReadNumber32(&sd, &coderOutStreams)); + if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1) + return SZ_ERROR_UNSUPPORTED; + } + + numInStreams += coderInStreams; + + if ((mainByte & 0x20) != 0) + { + UInt32 propsSize; + RINOK(SzReadNumber32(&sd, &propsSize)); + if (propsSize > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, propsSize); + } + } + + { + UInt32 indexOfMainStream = 0; + UInt32 numPackStreams = 1; + + if (numCoders != 1 || numInStreams != 1) + { + Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX]; + Byte coderUsed[k_Scan_NumCoders_MAX]; + + UInt32 i; + UInt32 numBonds = numCoders - 1; + if (numInStreams < numBonds) + return SZ_ERROR_ARCHIVE; + + if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (i = 0; i < numInStreams; i++) + streamUsed[i] = False; + for (i = 0; i < numCoders; i++) + coderUsed[i] = False; + + for (i = 0; i < numBonds; i++) + { + UInt32 index; + + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numInStreams || streamUsed[index]) + return SZ_ERROR_ARCHIVE; + streamUsed[index] = True; + + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numCoders || coderUsed[index]) + return SZ_ERROR_ARCHIVE; + coderUsed[index] = True; + } + + numPackStreams = numInStreams - numBonds; + + if (numPackStreams != 1) + for (i = 0; i < numPackStreams; i++) + { + UInt32 index; + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numInStreams || streamUsed[index]) + return SZ_ERROR_ARCHIVE; + streamUsed[index] = True; + } + + for (i = 0; i < numCoders; i++) + if (!coderUsed[i]) + { + indexOfMainStream = i; + break; + } + + if (i == numCoders) + return SZ_ERROR_ARCHIVE; + } + + p->FoStartPackStreamIndex[fo] = packStreamIndex; + p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; + p->FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; + numCodersOutStreams += numCoders; + if (numCodersOutStreams < numCoders) + return SZ_ERROR_UNSUPPORTED; + if (numPackStreams > p->NumPackStreams - packStreamIndex) + return SZ_ERROR_ARCHIVE; + packStreamIndex += numPackStreams; + } + } + + p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; + + { + size_t dataSize = sd.Data - startBufPtr; + p->FoStartPackStreamIndex[fo] = packStreamIndex; + p->FoCodersOffsets[fo] = dataSize; + MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc); + } + + if (external != 0) + { + if (sd.Size != 0) + return SZ_ERROR_ARCHIVE; + sd = *sd2; + } + + RINOK(WaitId(&sd, k7zIdCodersUnpackSize)); + + MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc); + { + UInt32 i; + for (i = 0; i < numCodersOutStreams; i++) + { + RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)); + } + } + + for (;;) + { + UInt64 type; + RINOK(ReadID(&sd, &type)); + if (type == k7zIdEnd) + { + *sd2 = sd; + return SZ_OK; + } + if (type == k7zIdCRC) + { + RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)); + continue; + } + RINOK(SkipData(&sd)); + } +} + + +UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex) +{ + return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]]; +} + + +typedef struct +{ + UInt32 NumTotalSubStreams; + UInt32 NumSubDigests; + CSzData sdNumSubStreams; + CSzData sdSizes; + CSzData sdCRCs; +} CSubStreamInfo; + + +static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) +{ + UInt64 type = 0; + UInt32 numSubDigests = 0; + UInt32 numFolders = p->NumFolders; + UInt32 numUnpackStreams = numFolders; + UInt32 numUnpackSizesInData = 0; + + for (;;) + { + RINOK(ReadID(sd, &type)); + if (type == k7zIdNumUnpackStream) + { + UInt32 i; + ssi->sdNumSubStreams.Data = sd->Data; + numUnpackStreams = 0; + numSubDigests = 0; + for (i = 0; i < numFolders; i++) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + if (numUnpackStreams > numUnpackStreams + numStreams) + return SZ_ERROR_UNSUPPORTED; + numUnpackStreams += numStreams; + if (numStreams != 0) + numUnpackSizesInData += (numStreams - 1); + if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) + numSubDigests += numStreams; + } + ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data; + continue; + } + if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + + if (!ssi->sdNumSubStreams.Data) + { + numSubDigests = numFolders; + if (p->FolderCRCs.Defs) + numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); + } + + ssi->NumTotalSubStreams = numUnpackStreams; + ssi->NumSubDigests = numSubDigests; + + if (type == k7zIdSize) + { + ssi->sdSizes.Data = sd->Data; + RINOK(SkipNumbers(sd, numUnpackSizesInData)); + ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data; + RINOK(ReadID(sd, &type)); + } + + for (;;) + { + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + ssi->sdCRCs.Data = sd->Data; + RINOK(SkipBitUi32s(sd, numSubDigests)); + ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data; + } + else + { + RINOK(SkipData(sd)); + } + RINOK(ReadID(sd, &type)); + } +} + +static SRes SzReadStreamsInfo(CSzAr *p, + CSzData *sd, + UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, + UInt64 *dataOffset, + CSubStreamInfo *ssi, + ISzAllocPtr alloc) +{ + UInt64 type; + + SzData_Clear(&ssi->sdSizes); + SzData_Clear(&ssi->sdCRCs); + SzData_Clear(&ssi->sdNumSubStreams); + + *dataOffset = 0; + RINOK(ReadID(sd, &type)); + if (type == k7zIdPackInfo) + { + RINOK(ReadNumber(sd, dataOffset)); + RINOK(ReadPackInfo(p, sd, alloc)); + RINOK(ReadID(sd, &type)); + } + if (type == k7zIdUnpackInfo) + { + RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc)); + RINOK(ReadID(sd, &type)); + } + if (type == k7zIdSubStreamsInfo) + { + RINOK(ReadSubStreamsInfo(p, sd, ssi)); + RINOK(ReadID(sd, &type)); + } + else + { + ssi->NumTotalSubStreams = p->NumFolders; + // ssi->NumSubDigests = 0; + } + + return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED); +} + +static SRes SzReadAndDecodePackedStreams( + ILookInStream *inStream, + CSzData *sd, + CBuf *tempBufs, + UInt32 numFoldersMax, + UInt64 baseOffset, + CSzAr *p, + ISzAllocPtr allocTemp) +{ + UInt64 dataStartPos; + UInt32 fo; + CSubStreamInfo ssi; + + RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)); + + dataStartPos += baseOffset; + if (p->NumFolders == 0) + return SZ_ERROR_ARCHIVE; + + for (fo = 0; fo < p->NumFolders; fo++) + Buf_Init(tempBufs + fo); + + for (fo = 0; fo < p->NumFolders; fo++) + { + CBuf *tempBuf = tempBufs + fo; + UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo); + if ((size_t)unpackSize != unpackSize) + return SZ_ERROR_MEM; + if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp)) + return SZ_ERROR_MEM; + } + + for (fo = 0; fo < p->NumFolders; fo++) + { + const CBuf *tempBuf = tempBufs + fo; + RINOK(LookInStream_SeekTo(inStream, dataStartPos)); + RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)); + } + + return SZ_OK; +} + +static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) +{ + size_t pos = 0; + *offsets++ = 0; + if (numFiles == 0) + return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE; + if (size < 2) + return SZ_ERROR_ARCHIVE; + if (data[size - 2] != 0 || data[size - 1] != 0) + return SZ_ERROR_ARCHIVE; + do + { + const Byte *p; + if (pos == size) + return SZ_ERROR_ARCHIVE; + for (p = data + pos; + #ifdef _WIN32 + *(const UInt16 *)p != 0 + #else + p[0] != 0 || p[1] != 0 + #endif + ; p += 2); + pos = p - data + 2; + *offsets++ = (pos >> 1); + } + while (--numFiles); + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, + CSzData *sd2, + const CBuf *tempBufs, UInt32 numTempBufs, + ISzAllocPtr alloc) +{ + CSzData sd; + UInt32 i; + CNtfsFileTime *vals; + Byte *defs; + Byte external; + + RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)); + + SZ_READ_BYTE_SD(sd2, external); + if (external == 0) + sd = *sd2; + else + { + UInt32 index; + RINOK(SzReadNumber32(sd2, &index)); + if (index >= numTempBufs) + return SZ_ERROR_ARCHIVE; + sd.Data = tempBufs[index].data; + sd.Size = tempBufs[index].size; + } + + MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc); + vals = p->Vals; + defs = p->Defs; + for (i = 0; i < num; i++) + if (SzBitArray_Check(defs, i)) + { + if (sd.Size < 8) + return SZ_ERROR_ARCHIVE; + vals[i].Low = GetUi32(sd.Data); + vals[i].High = GetUi32(sd.Data + 4); + SKIP_DATA2(sd, 8); + } + else + vals[i].High = vals[i].Low = 0; + + if (external == 0) + *sd2 = sd; + + return SZ_OK; +} + + +#define NUM_ADDITIONAL_STREAMS_MAX 8 + + +static SRes SzReadHeader2( + CSzArEx *p, /* allocMain */ + CSzData *sd, + ILookInStream *inStream, + CBuf *tempBufs, UInt32 *numTempBufs, + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp + ) +{ + CSubStreamInfo ssi; + +{ + UInt64 type; + + SzData_Clear(&ssi.sdSizes); + SzData_Clear(&ssi.sdCRCs); + SzData_Clear(&ssi.sdNumSubStreams); + + ssi.NumSubDigests = 0; + ssi.NumTotalSubStreams = 0; + + RINOK(ReadID(sd, &type)); + + if (type == k7zIdArchiveProperties) + { + for (;;) + { + UInt64 type2; + RINOK(ReadID(sd, &type2)); + if (type2 == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdAdditionalStreamsInfo) + { + CSzAr tempAr; + SRes res; + + SzAr_Init(&tempAr); + res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, + p->startPosAfterHeader, &tempAr, allocTemp); + *numTempBufs = tempAr.NumFolders; + SzAr_Free(&tempAr, allocTemp); + + if (res != SZ_OK) + return res; + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdMainStreamsInfo) + { + RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs, + &p->dataPos, &ssi, allocMain)); + p->dataPos += p->startPosAfterHeader; + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdEnd) + { + return SZ_OK; + } + + if (type != k7zIdFilesInfo) + return SZ_ERROR_ARCHIVE; +} + +{ + UInt32 numFiles = 0; + UInt32 numEmptyStreams = 0; + const Byte *emptyStreams = NULL; + const Byte *emptyFiles = NULL; + + RINOK(SzReadNumber32(sd, &numFiles)); + p->NumFiles = numFiles; + + for (;;) + { + UInt64 type; + UInt64 size; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(ReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + + if (type >= ((UInt32)1 << 8)) + { + SKIP_DATA(sd, size); + } + else switch ((unsigned)type) + { + case k7zIdName: + { + size_t namesSize; + const Byte *namesData; + Byte external; + + SZ_READ_BYTE(external); + if (external == 0) + { + namesSize = (size_t)size - 1; + namesData = sd->Data; + } + else + { + UInt32 index; + RINOK(SzReadNumber32(sd, &index)); + if (index >= *numTempBufs) + return SZ_ERROR_ARCHIVE; + namesData = (tempBufs)[index].data; + namesSize = (tempBufs)[index].size; + } + + if ((namesSize & 1) != 0) + return SZ_ERROR_ARCHIVE; + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); + MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain); + RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) + if (external == 0) + { + SKIP_DATA(sd, namesSize); + } + break; + } + case k7zIdEmptyStream: + { + RINOK(RememberBitVector(sd, numFiles, &emptyStreams)); + numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); + emptyFiles = NULL; + break; + } + case k7zIdEmptyFile: + { + RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)); + break; + } + case k7zIdWinAttrib: + { + Byte external; + CSzData sdSwitch; + CSzData *sdPtr; + SzBitUi32s_Free(&p->Attribs, allocMain); + RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)); + + SZ_READ_BYTE(external); + if (external == 0) + sdPtr = sd; + else + { + UInt32 index; + RINOK(SzReadNumber32(sd, &index)); + if (index >= *numTempBufs) + return SZ_ERROR_ARCHIVE; + sdSwitch.Data = (tempBufs)[index].data; + sdSwitch.Size = (tempBufs)[index].size; + sdPtr = &sdSwitch; + } + RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)); + break; + } + /* + case k7zParent: + { + SzBitUi32s_Free(&p->Parents, allocMain); + RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain)); + RINOK(SzReadSwitch(sd)); + RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain)); + break; + } + */ + case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + default: + { + SKIP_DATA(sd, size); + } + } + } + + if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams) + return SZ_ERROR_ARCHIVE; + + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + + { + UInt32 i; + UInt32 emptyFileIndex = 0; + UInt32 folderIndex = 0; + UInt32 remSubStreams = 0; + UInt32 numSubStreams = 0; + UInt64 unpackPos = 0; + const Byte *digestsDefs = NULL; + const Byte *digestsVals = NULL; + UInt32 digestsValsIndex = 0; + UInt32 digestIndex; + Byte allDigestsDefined = 0; + Byte isDirMask = 0; + Byte crcMask = 0; + Byte mask = 0x80; + + MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain); + MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain); + MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain); + MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain); + + RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain)); + + if (ssi.sdCRCs.Size != 0) + { + SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined); + if (allDigestsDefined) + digestsVals = ssi.sdCRCs.Data; + else + { + size_t numBytes = (ssi.NumSubDigests + 7) >> 3; + digestsDefs = ssi.sdCRCs.Data; + digestsVals = digestsDefs + numBytes; + } + } + + digestIndex = 0; + + for (i = 0; i < numFiles; i++, mask >>= 1) + { + if (mask == 0) + { + UInt32 byteIndex = (i - 1) >> 3; + p->IsDirs[byteIndex] = isDirMask; + p->CRCs.Defs[byteIndex] = crcMask; + isDirMask = 0; + crcMask = 0; + mask = 0x80; + } + + p->UnpackPositions[i] = unpackPos; + p->CRCs.Vals[i] = 0; + + if (emptyStreams && SzBitArray_Check(emptyStreams, i)) + { + if (emptyFiles) + { + if (!SzBitArray_Check(emptyFiles, emptyFileIndex)) + isDirMask |= mask; + emptyFileIndex++; + } + else + isDirMask |= mask; + if (remSubStreams == 0) + { + p->FileToFolder[i] = (UInt32)-1; + continue; + } + } + + if (remSubStreams == 0) + { + for (;;) + { + if (folderIndex >= p->db.NumFolders) + return SZ_ERROR_ARCHIVE; + p->FolderToFile[folderIndex] = i; + numSubStreams = 1; + if (ssi.sdNumSubStreams.Data) + { + RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)); + } + remSubStreams = numSubStreams; + if (numSubStreams != 0) + break; + { + UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + unpackPos += folderUnpackSize; + if (unpackPos < folderUnpackSize) + return SZ_ERROR_ARCHIVE; + } + + folderIndex++; + } + } + + p->FileToFolder[i] = folderIndex; + + if (emptyStreams && SzBitArray_Check(emptyStreams, i)) + continue; + + if (--remSubStreams == 0) + { + UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]]; + if (folderUnpackSize < unpackPos - startFolderUnpackPos) + return SZ_ERROR_ARCHIVE; + unpackPos = startFolderUnpackPos + folderUnpackSize; + if (unpackPos < folderUnpackSize) + return SZ_ERROR_ARCHIVE; + + if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i)) + { + p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex]; + crcMask |= mask; + } + else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + { + p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); + digestsValsIndex++; + crcMask |= mask; + } + + folderIndex++; + } + else + { + UInt64 v; + RINOK(ReadNumber(&ssi.sdSizes, &v)); + unpackPos += v; + if (unpackPos < v) + return SZ_ERROR_ARCHIVE; + if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + { + p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); + digestsValsIndex++; + crcMask |= mask; + } + } + } + + if (mask != 0x80) + { + UInt32 byteIndex = (i - 1) >> 3; + p->IsDirs[byteIndex] = isDirMask; + p->CRCs.Defs[byteIndex] = crcMask; + } + + p->UnpackPositions[i] = unpackPos; + + if (remSubStreams != 0) + return SZ_ERROR_ARCHIVE; + + for (;;) + { + p->FolderToFile[folderIndex] = i; + if (folderIndex >= p->db.NumFolders) + break; + if (!ssi.sdNumSubStreams.Data) + return SZ_ERROR_ARCHIVE; + RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)); + if (numSubStreams != 0) + return SZ_ERROR_ARCHIVE; + /* + { + UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + unpackPos += folderUnpackSize; + if (unpackPos < folderUnpackSize) + return SZ_ERROR_ARCHIVE; + } + */ + folderIndex++; + } + + if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0) + return SZ_ERROR_ARCHIVE; + } +} + return SZ_OK; +} + + +static SRes SzReadHeader( + CSzArEx *p, + CSzData *sd, + ILookInStream *inStream, + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp) +{ + UInt32 i; + UInt32 numTempBufs = 0; + SRes res; + CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX]; + + for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) + Buf_Init(tempBufs + i); + + res = SzReadHeader2(p, sd, inStream, + tempBufs, &numTempBufs, + allocMain, allocTemp); + + for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) + Buf_Free(tempBufs + i, allocTemp); + + RINOK(res); + + if (sd->Size != 0) + return SZ_ERROR_FAIL; + + return res; +} + +static SRes SzArEx_Open2( + CSzArEx *p, + ILookInStream *inStream, + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp) +{ + Byte header[k7zStartHeaderSize]; + Int64 startArcPos; + UInt64 nextHeaderOffset, nextHeaderSize; + size_t nextHeaderSizeT; + UInt32 nextHeaderCRC; + CBuf buf; + SRes res; + + startArcPos = 0; + RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR)); + + RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); + + if (!TestSignatureCandidate(header)) + return SZ_ERROR_NO_ARCHIVE; + if (header[6] != k7zMajorVersion) + return SZ_ERROR_UNSUPPORTED; + + nextHeaderOffset = GetUi64(header + 12); + nextHeaderSize = GetUi64(header + 20); + nextHeaderCRC = GetUi32(header + 28); + + p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; + + if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) + return SZ_ERROR_CRC; + + nextHeaderSizeT = (size_t)nextHeaderSize; + if (nextHeaderSizeT != nextHeaderSize) + return SZ_ERROR_MEM; + if (nextHeaderSizeT == 0) + return SZ_OK; + if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || + nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) + return SZ_ERROR_NO_ARCHIVE; + + { + Int64 pos = 0; + RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END)); + if ((UInt64)pos < startArcPos + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + return SZ_ERROR_INPUT_EOF; + } + + RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); + + if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) + return SZ_ERROR_MEM; + + res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT); + + if (res == SZ_OK) + { + res = SZ_ERROR_ARCHIVE; + if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC) + { + CSzData sd; + UInt64 type; + sd.Data = buf.data; + sd.Size = buf.size; + + res = ReadID(&sd, &type); + + if (res == SZ_OK && type == k7zIdEncodedHeader) + { + CSzAr tempAr; + CBuf tempBuf; + Buf_Init(&tempBuf); + + SzAr_Init(&tempAr); + res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp); + SzAr_Free(&tempAr, allocTemp); + + if (res != SZ_OK) + { + Buf_Free(&tempBuf, allocTemp); + } + else + { + Buf_Free(&buf, allocTemp); + buf.data = tempBuf.data; + buf.size = tempBuf.size; + sd.Data = buf.data; + sd.Size = buf.size; + res = ReadID(&sd, &type); + } + } + + if (res == SZ_OK) + { + if (type == k7zIdHeader) + { + /* + CSzData sd2; + unsigned ttt; + for (ttt = 0; ttt < 40000; ttt++) + { + SzArEx_Free(p, allocMain); + sd2 = sd; + res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp); + if (res != SZ_OK) + break; + } + */ + res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp); + } + else + res = SZ_ERROR_UNSUPPORTED; + } + } + } + + Buf_Free(&buf, allocTemp); + return res; +} + + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, + ISzAllocPtr allocMain, ISzAllocPtr allocTemp) +{ + SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); + if (res != SZ_OK) + SzArEx_Free(p, allocMain); + return res; +} + + +SRes SzArEx_Extract( + const CSzArEx *p, + ILookInStream *inStream, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **tempBuf, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp) +{ + UInt32 folderIndex = p->FileToFolder[fileIndex]; + SRes res = SZ_OK; + + *offset = 0; + *outSizeProcessed = 0; + + if (folderIndex == (UInt32)-1) + { + ISzAlloc_Free(allocMain, *tempBuf); + *blockIndex = folderIndex; + *tempBuf = NULL; + *outBufferSize = 0; + return SZ_OK; + } + + if (*tempBuf == NULL || *blockIndex != folderIndex) + { + UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + /* + UInt64 unpackSizeSpec = + p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] - + p->UnpackPositions[p->FolderToFile[folderIndex]]; + */ + size_t unpackSize = (size_t)unpackSizeSpec; + + if (unpackSize != unpackSizeSpec) + return SZ_ERROR_MEM; + *blockIndex = folderIndex; + ISzAlloc_Free(allocMain, *tempBuf); + *tempBuf = NULL; + + if (res == SZ_OK) + { + *outBufferSize = unpackSize; + if (unpackSize != 0) + { + *tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize); + if (*tempBuf == NULL) + res = SZ_ERROR_MEM; + } + + if (res == SZ_OK) + { + res = SzAr_DecodeFolder(&p->db, folderIndex, + inStream, p->dataPos, *tempBuf, unpackSize, allocTemp); + } + } + } + + if (res == SZ_OK) + { + UInt64 unpackPos = p->UnpackPositions[fileIndex]; + *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]); + *outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos); + if (*offset + *outSizeProcessed > *outBufferSize) + return SZ_ERROR_FAIL; + if (SzBitWithVals_Check(&p->CRCs, fileIndex)) + if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex]) + res = SZ_ERROR_CRC; + } + + return res; +} + + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + size_t offs = p->FileNameOffsets[fileIndex]; + size_t len = p->FileNameOffsets[fileIndex + 1] - offs; + if (dest != 0) + { + size_t i; + const Byte *src = p->FileNames + offs * 2; + for (i = 0; i < len; i++) + dest[i] = GetUi16(src + i * 2); + } + return len; +} + +/* +size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex) +{ + size_t len; + if (!p->FileNameOffsets) + return 1; + len = 0; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + if SzBitWithVals_Check(&p->Parents, fileIndex) + parent = p->Parents.Vals[fileIndex]; + if (parent == (UInt32)(Int32)-1) + return len; + fileIndex = parent; + } +} + +UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + Bool needSlash; + if (!p->FileNameOffsets) + { + *(--dest) = 0; + return dest; + } + needSlash = False; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen); + if (needSlash) + *(dest - 1) = '/'; + needSlash = True; + dest -= curLen; + + if SzBitWithVals_Check(&p->Parents, fileIndex) + parent = p->Parents.Vals[fileIndex]; + if (parent == (UInt32)(Int32)-1) + return dest; + fileIndex = parent; + } +} +*/ diff --git a/other-licenses/7zstub/src/C/7zBuf.c b/other-licenses/7zstub/src/C/7zBuf.c new file mode 100644 index 0000000000..438bba68bd --- /dev/null +++ b/other-licenses/7zstub/src/C/7zBuf.c @@ -0,0 +1,36 @@ +/* 7zBuf.c -- Byte Buffer +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zBuf.h" + +void Buf_Init(CBuf *p) +{ + p->data = 0; + p->size = 0; +} + +int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc) +{ + p->size = 0; + if (size == 0) + { + p->data = 0; + return 1; + } + p->data = (Byte *)ISzAlloc_Alloc(alloc, size); + if (p->data) + { + p->size = size; + return 1; + } + return 0; +} + +void Buf_Free(CBuf *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->data); + p->data = 0; + p->size = 0; +} diff --git a/other-licenses/7zstub/src/C/7zBuf.h b/other-licenses/7zstub/src/C/7zBuf.h new file mode 100644 index 0000000000..5942d6e623 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zBuf.h @@ -0,0 +1,35 @@ +/* 7zBuf.h -- Byte Buffer +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_BUF_H +#define __7Z_BUF_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef struct +{ + Byte *data; + size_t size; +} CBuf; + +void Buf_Init(CBuf *p); +int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc); +void Buf_Free(CBuf *p, ISzAllocPtr alloc); + +typedef struct +{ + Byte *data; + size_t size; + size_t pos; +} CDynBuf; + +void DynBuf_Construct(CDynBuf *p); +void DynBuf_SeekToBeg(CDynBuf *p); +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc); +void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/7zBuf2.c b/other-licenses/7zstub/src/C/7zBuf2.c new file mode 100644 index 0000000000..49b4343b67 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zBuf2.c @@ -0,0 +1,52 @@ +/* 7zBuf2.c -- Byte Buffer +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zBuf.h" + +void DynBuf_Construct(CDynBuf *p) +{ + p->data = 0; + p->size = 0; + p->pos = 0; +} + +void DynBuf_SeekToBeg(CDynBuf *p) +{ + p->pos = 0; +} + +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc) +{ + if (size > p->size - p->pos) + { + size_t newSize = p->pos + size; + Byte *data; + newSize += newSize / 4; + data = (Byte *)ISzAlloc_Alloc(alloc, newSize); + if (!data) + return 0; + p->size = newSize; + if (p->pos != 0) + memcpy(data, p->data, p->pos); + ISzAlloc_Free(alloc, p->data); + p->data = data; + } + if (size != 0) + { + memcpy(p->data + p->pos, buf, size); + p->pos += size; + } + return 1; +} + +void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->data); + p->data = 0; + p->size = 0; + p->pos = 0; +} diff --git a/other-licenses/7zstub/src/C/7zCrc.c b/other-licenses/7zstub/src/C/7zCrc.c new file mode 100644 index 0000000000..40ab75952a --- /dev/null +++ b/other-licenses/7zstub/src/C/7zCrc.c @@ -0,0 +1,128 @@ +/* 7zCrc.c -- CRC32 init +2017-06-06 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zCrc.h" +#include "CpuArch.h" + +#define kCrcPoly 0xEDB88320 + +#ifdef MY_CPU_LE + #define CRC_NUM_TABLES 8 +#else + #define CRC_NUM_TABLES 9 + + #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + + UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); + UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); + UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +CRC_FUNC g_CrcUpdateT4; +CRC_FUNC g_CrcUpdateT8; +CRC_FUNC g_CrcUpdate; + +UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) +{ + return g_CrcUpdate(v, data, size, g_CrcTable); +} + +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) +{ + return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; +} + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + const Byte *pEnd = p + size; + for (; p != pEnd; p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +void MY_FAST_CALL CrcGenerateTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt32 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); + g_CrcTable[i] = r; + } + for (i = 256; i < 256 * CRC_NUM_TABLES; i++) + { + UInt32 r = g_CrcTable[(size_t)i - 256]; + g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); + } + + #if CRC_NUM_TABLES < 4 + + g_CrcUpdate = CrcUpdateT1; + + #else + + #ifdef MY_CPU_LE + + g_CrcUpdateT4 = CrcUpdateT4; + g_CrcUpdate = CrcUpdateT4; + + #if CRC_NUM_TABLES >= 8 + g_CrcUpdateT8 = CrcUpdateT8; + + #ifdef MY_CPU_X86_OR_AMD64 + if (!CPU_Is_InOrder()) + #endif + g_CrcUpdate = CrcUpdateT8; + #endif + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 0x01020304; + const Byte *p = (const Byte *)&k; + if (p[0] == 4 && p[1] == 3) + { + g_CrcUpdateT4 = CrcUpdateT4; + g_CrcUpdate = CrcUpdateT4; + #if CRC_NUM_TABLES >= 8 + g_CrcUpdateT8 = CrcUpdateT8; + g_CrcUpdate = CrcUpdateT8; + #endif + } + else if (p[0] != 1 || p[1] != 2) + g_CrcUpdate = CrcUpdateT1; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt32 x = g_CrcTable[(size_t)i - 256]; + g_CrcTable[i] = CRC_UINT32_SWAP(x); + } + g_CrcUpdateT4 = CrcUpdateT1_BeT4; + g_CrcUpdate = CrcUpdateT1_BeT4; + #if CRC_NUM_TABLES >= 8 + g_CrcUpdateT8 = CrcUpdateT1_BeT8; + g_CrcUpdate = CrcUpdateT1_BeT8; + #endif + } + } + #endif + + #endif +} diff --git a/other-licenses/7zstub/src/C/7zCrc.h b/other-licenses/7zstub/src/C/7zCrc.h new file mode 100644 index 0000000000..3b0459402b --- /dev/null +++ b/other-licenses/7zstub/src/C/7zCrc.h @@ -0,0 +1,25 @@ +/* 7zCrc.h -- CRC32 calculation +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __7Z_CRC_H +#define __7Z_CRC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +extern UInt32 g_CrcTable[]; + +/* Call CrcGenerateTable one time before other CRC functions */ +void MY_FAST_CALL CrcGenerateTable(void); + +#define CRC_INIT_VAL 0xFFFFFFFF +#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) +#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/7zCrcOpt.c b/other-licenses/7zstub/src/C/7zCrcOpt.c new file mode 100644 index 0000000000..2ee0de8459 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zCrcOpt.c @@ -0,0 +1,115 @@ +/* 7zCrcOpt.c -- CRC32 calculation +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifndef MY_CPU_BE + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + (table + 0x300)[((v ) & 0xFF)] + ^ (table + 0x200)[((v >> 8) & 0xFF)] + ^ (table + 0x100)[((v >> 16) & 0xFF)] + ^ (table + 0x000)[((v >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 8; size -= 8, p += 8) + { + UInt32 d; + v ^= *(const UInt32 *)p; + v = + (table + 0x700)[((v ) & 0xFF)] + ^ (table + 0x600)[((v >> 8) & 0xFF)] + ^ (table + 0x500)[((v >> 16) & 0xFF)] + ^ (table + 0x400)[((v >> 24))]; + d = *((const UInt32 *)p + 1); + v ^= + (table + 0x300)[((d ) & 0xFF)] + ^ (table + 0x200)[((d >> 8) & 0xFF)] + ^ (table + 0x100)[((d >> 16) & 0xFF)] + ^ (table + 0x000)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + +#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8)) + +UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + table += 0x100; + v = CRC_UINT32_SWAP(v); + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2_BE(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + (table + 0x000)[((v ) & 0xFF)] + ^ (table + 0x100)[((v >> 8) & 0xFF)] + ^ (table + 0x200)[((v >> 16) & 0xFF)] + ^ (table + 0x300)[((v >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2_BE(v, *p); + return CRC_UINT32_SWAP(v); +} + +UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + table += 0x100; + v = CRC_UINT32_SWAP(v); + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2_BE(v, *p); + for (; size >= 8; size -= 8, p += 8) + { + UInt32 d; + v ^= *(const UInt32 *)p; + v = + (table + 0x400)[((v ) & 0xFF)] + ^ (table + 0x500)[((v >> 8) & 0xFF)] + ^ (table + 0x600)[((v >> 16) & 0xFF)] + ^ (table + 0x700)[((v >> 24))]; + d = *((const UInt32 *)p + 1); + v ^= + (table + 0x000)[((d ) & 0xFF)] + ^ (table + 0x100)[((d >> 8) & 0xFF)] + ^ (table + 0x200)[((d >> 16) & 0xFF)] + ^ (table + 0x300)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2_BE(v, *p); + return CRC_UINT32_SWAP(v); +} + +#endif diff --git a/other-licenses/7zstub/src/C/7zDec.c b/other-licenses/7zstub/src/C/7zDec.c new file mode 100644 index 0000000000..9c986950c8 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zDec.c @@ -0,0 +1,591 @@ +/* 7zDec.c -- Decoding from 7z folder +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define _7ZIP_PPMD_SUPPPORT */ + +#include "7z.h" +#include "7zCrc.h" + +#include "Bcj2.h" +#include "Bra.h" +#include "CpuArch.h" +#include "Delta.h" +#include "LzmaDec.h" +#include "Lzma2Dec.h" +#ifdef _7ZIP_PPMD_SUPPPORT +#include "Ppmd7.h" +#endif + +#define k_Copy 0 +#define k_Delta 3 +#define k_LZMA2 0x21 +#define k_LZMA 0x30101 +#define k_BCJ 0x3030103 +#define k_BCJ2 0x303011B +#define k_PPC 0x3030205 +#define k_IA64 0x3030401 +#define k_ARM 0x3030501 +#define k_ARMT 0x3030701 +#define k_SPARC 0x3030805 + + +#ifdef _7ZIP_PPMD_SUPPPORT + +#define k_PPMD 0x30401 + +typedef struct +{ + IByteIn vt; + const Byte *cur; + const Byte *end; + const Byte *begin; + UInt64 processed; + Bool extra; + SRes res; + const ILookInStream *inStream; +} CByteInToLook; + +static Byte ReadByte(const IByteIn *pp) +{ + CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt); + if (p->cur != p->end) + return *p->cur++; + if (p->res == SZ_OK) + { + size_t size = p->cur - p->begin; + p->processed += size; + p->res = ILookInStream_Skip(p->inStream, size); + size = (1 << 25); + p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size); + p->cur = p->begin; + p->end = p->begin + size; + if (size != 0) + return *p->cur++;; + } + p->extra = True; + return 0; +} + +static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) +{ + CPpmd7 ppmd; + CByteInToLook s; + SRes res = SZ_OK; + + s.vt.Read = ReadByte; + s.inStream = inStream; + s.begin = s.end = s.cur = NULL; + s.extra = False; + s.res = SZ_OK; + s.processed = 0; + + if (propsSize != 5) + return SZ_ERROR_UNSUPPORTED; + + { + unsigned 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 SZ_ERROR_UNSUPPORTED; + Ppmd7_Construct(&ppmd); + if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) + return SZ_ERROR_MEM; + Ppmd7_Init(&ppmd, order); + } + { + CPpmd7z_RangeDec rc; + Ppmd7z_RangeDec_CreateVTable(&rc); + rc.Stream = &s.vt; + if (!Ppmd7z_RangeDec_Init(&rc)) + res = SZ_ERROR_DATA; + else if (s.extra) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else + { + SizeT i; + for (i = 0; i < outSize; i++) + { + int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt); + if (s.extra || sym < 0) + break; + outBuffer[i] = (Byte)sym; + } + if (i != outSize) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) + res = SZ_ERROR_DATA; + } + } + Ppmd7_Free(&ppmd, allocMain); + return res; +} + +#endif + + +static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) +{ + CLzmaDec state; + SRes res = SZ_OK; + + LzmaDec_Construct(&state); + RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); + state.dic = outBuffer; + state.dicBufSize = outSize; + LzmaDec_Init(&state); + + for (;;) + { + const void *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = ILookInStream_Look(inStream, &inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; + ELzmaStatus status; + res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (outSize != state.dicPos || inSize != 0) + res = SZ_ERROR_DATA; + break; + } + + if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + break; + + if (inProcessed == 0 && dicPos == state.dicPos) + { + res = SZ_ERROR_DATA; + break; + } + + res = ILookInStream_Skip(inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + LzmaDec_FreeProbs(&state, allocMain); + return res; +} + + +#ifndef _7Z_NO_METHOD_LZMA2 + +static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) +{ + CLzma2Dec state; + SRes res = SZ_OK; + + Lzma2Dec_Construct(&state); + if (propsSize != 1) + return SZ_ERROR_DATA; + RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); + state.decoder.dic = outBuffer; + state.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&state); + + for (;;) + { + const void *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = ILookInStream_Look(inStream, &inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; + ELzmaStatus status; + res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (outSize != state.decoder.dicPos || inSize != 0) + res = SZ_ERROR_DATA; + break; + } + + if (inProcessed == 0 && dicPos == state.decoder.dicPos) + { + res = SZ_ERROR_DATA; + break; + } + + res = ILookInStream_Skip(inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + Lzma2Dec_FreeProbs(&state, allocMain); + return res; +} + +#endif + + +static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) +{ + while (inSize > 0) + { + const void *inBuf; + size_t curSize = (1 << 18); + if (curSize > inSize) + curSize = (size_t)inSize; + RINOK(ILookInStream_Look(inStream, &inBuf, &curSize)); + if (curSize == 0) + return SZ_ERROR_INPUT_EOF; + memcpy(outBuffer, inBuf, curSize); + outBuffer += curSize; + inSize -= curSize; + RINOK(ILookInStream_Skip(inStream, curSize)); + } + return SZ_OK; +} + +static Bool IS_MAIN_METHOD(UInt32 m) +{ + switch (m) + { + case k_Copy: + case k_LZMA: + #ifndef _7Z_NO_METHOD_LZMA2 + case k_LZMA2: + #endif + #ifdef _7ZIP_PPMD_SUPPPORT + case k_PPMD: + #endif + return True; + } + return False; +} + +static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) +{ + return + c->NumStreams == 1 + /* && c->MethodID <= (UInt32)0xFFFFFFFF */ + && IS_MAIN_METHOD((UInt32)c->MethodID); +} + +#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4) + +static SRes CheckSupportedFolder(const CSzFolder *f) +{ + if (f->NumCoders < 1 || f->NumCoders > 4) + return SZ_ERROR_UNSUPPORTED; + if (!IS_SUPPORTED_CODER(&f->Coders[0])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumCoders == 1) + { + if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + + + #ifndef _7Z_NO_METHODS_FILTERS + + if (f->NumCoders == 2) + { + const CSzCoderInfo *c = &f->Coders[1]; + if ( + /* c->MethodID > (UInt32)0xFFFFFFFF || */ + c->NumStreams != 1 + || f->NumPackStreams != 1 + || f->PackStreams[0] != 0 + || f->NumBonds != 1 + || f->Bonds[0].InIndex != 1 + || f->Bonds[0].OutIndex != 0) + return SZ_ERROR_UNSUPPORTED; + switch ((UInt32)c->MethodID) + { + case k_Delta: + case k_BCJ: + case k_PPC: + case k_IA64: + case k_SPARC: + case k_ARM: + case k_ARMT: + break; + default: + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; + } + + #endif + + + if (f->NumCoders == 4) + { + if (!IS_SUPPORTED_CODER(&f->Coders[1]) + || !IS_SUPPORTED_CODER(&f->Coders[2]) + || !IS_BCJ2(&f->Coders[3])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumPackStreams != 4 + || f->PackStreams[0] != 2 + || f->PackStreams[1] != 6 + || f->PackStreams[2] != 1 + || f->PackStreams[3] != 0 + || f->NumBonds != 3 + || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0 + || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1 + || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + + return SZ_ERROR_UNSUPPORTED; +} + +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; + +static SRes SzFolder_Decode2(const CSzFolder *folder, + const Byte *propsData, + const UInt64 *unpackSizes, + const UInt64 *packPositions, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain, + Byte *tempBuf[]) +{ + UInt32 ci; + SizeT tempSizes[3] = { 0, 0, 0}; + SizeT tempSize3 = 0; + Byte *tempBuf3 = 0; + + RINOK(CheckSupportedFolder(folder)); + + for (ci = 0; ci < folder->NumCoders; ci++) + { + const CSzCoderInfo *coder = &folder->Coders[ci]; + + if (IS_MAIN_METHOD((UInt32)coder->MethodID)) + { + UInt32 si = 0; + UInt64 offset; + UInt64 inSize; + Byte *outBufCur = outBuffer; + SizeT outSizeCur = outSize; + if (folder->NumCoders == 4) + { + UInt32 indices[] = { 3, 2, 0 }; + UInt64 unpackSize = unpackSizes[ci]; + si = indices[ci]; + if (ci < 2) + { + Byte *temp; + outSizeCur = (SizeT)unpackSize; + if (outSizeCur != unpackSize) + return SZ_ERROR_MEM; + temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur); + if (!temp && outSizeCur != 0) + return SZ_ERROR_MEM; + outBufCur = tempBuf[1 - ci] = temp; + tempSizes[1 - ci] = outSizeCur; + } + else if (ci == 2) + { + if (unpackSize > outSize) /* check it */ + return SZ_ERROR_PARAM; + tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); + tempSize3 = outSizeCur = (SizeT)unpackSize; + } + else + return SZ_ERROR_UNSUPPORTED; + } + offset = packPositions[si]; + inSize = packPositions[(size_t)si + 1] - offset; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + + if (coder->MethodID == k_Copy) + { + if (inSize != outSizeCur) /* check it */ + return SZ_ERROR_DATA; + RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); + } + else if (coder->MethodID == k_LZMA) + { + RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + #ifndef _7Z_NO_METHOD_LZMA2 + else if (coder->MethodID == k_LZMA2) + { + RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + #endif + #ifdef _7ZIP_PPMD_SUPPPORT + else if (coder->MethodID == k_PPMD) + { + RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + #endif + else + return SZ_ERROR_UNSUPPORTED; + } + else if (coder->MethodID == k_BCJ2) + { + UInt64 offset = packPositions[1]; + UInt64 s3Size = packPositions[2] - offset; + + if (ci != 3) + return SZ_ERROR_UNSUPPORTED; + + tempSizes[2] = (SizeT)s3Size; + if (tempSizes[2] != s3Size) + return SZ_ERROR_MEM; + tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]); + if (!tempBuf[2] && tempSizes[2] != 0) + return SZ_ERROR_MEM; + + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])); + + if ((tempSizes[0] & 3) != 0 || + (tempSizes[1] & 3) != 0 || + tempSize3 + tempSizes[0] + tempSizes[1] != outSize) + return SZ_ERROR_DATA; + + { + CBcj2Dec p; + + p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3; + p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0]; + p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1]; + p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2]; + + p.dest = outBuffer; + p.destLim = outBuffer + outSize; + + Bcj2Dec_Init(&p); + RINOK(Bcj2Dec_Decode(&p)); + + { + unsigned i; + for (i = 0; i < 4; i++) + if (p.bufs[i] != p.lims[i]) + return SZ_ERROR_DATA; + + if (!Bcj2Dec_IsFinished(&p)) + return SZ_ERROR_DATA; + + if (p.dest != p.destLim + || p.state != BCJ2_STREAM_MAIN) + return SZ_ERROR_DATA; + } + } + } + #ifndef _7Z_NO_METHODS_FILTERS + else if (ci == 1) + { + if (coder->MethodID == k_Delta) + { + if (coder->PropsSize != 1) + return SZ_ERROR_UNSUPPORTED; + { + Byte state[DELTA_STATE_SIZE]; + Delta_Init(state); + Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize); + } + } + else + { + if (coder->PropsSize != 0) + return SZ_ERROR_UNSUPPORTED; + switch (coder->MethodID) + { + case k_BCJ: + { + UInt32 state; + x86_Convert_Init(state); + x86_Convert(outBuffer, outSize, 0, &state, 0); + break; + } + CASE_BRA_CONV(PPC) + CASE_BRA_CONV(IA64) + CASE_BRA_CONV(SPARC) + CASE_BRA_CONV(ARM) + CASE_BRA_CONV(ARMT) + default: + return SZ_ERROR_UNSUPPORTED; + } + } + } + #endif + else + return SZ_ERROR_UNSUPPORTED; + } + + return SZ_OK; +} + + +SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, size_t outSize, + ISzAllocPtr allocMain) +{ + SRes res; + CSzFolder folder; + CSzData sd; + + const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; + sd.Data = data; + sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex]; + + res = SzGetNextFolderItem(&folder, &sd); + + if (res != SZ_OK) + return res; + + if (sd.Size != 0 + || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex] + || outSize != SzAr_GetFolderUnpackSize(p, folderIndex)) + return SZ_ERROR_FAIL; + { + unsigned i; + Byte *tempBuf[3] = { 0, 0, 0}; + + res = SzFolder_Decode2(&folder, data, + &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]], + p->PackPositions + p->FoStartPackStreamIndex[folderIndex], + inStream, startPos, + outBuffer, (SizeT)outSize, allocMain, tempBuf); + + for (i = 0; i < 3; i++) + ISzAlloc_Free(allocMain, tempBuf[i]); + + if (res == SZ_OK) + if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex)) + if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex]) + res = SZ_ERROR_CRC; + + return res; + } +} diff --git a/other-licenses/7zstub/src/C/7zFile.c b/other-licenses/7zstub/src/C/7zFile.c new file mode 100644 index 0000000000..e486901e30 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zFile.c @@ -0,0 +1,286 @@ +/* 7zFile.c -- File IO +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zFile.h" + +#ifndef USE_WINDOWS_FILE + +#ifndef UNDER_CE +#include +#endif + +#else + +/* + ReadFile and WriteFile functions in Windows have BUG: + If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) + from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES + (Insufficient system resources exist to complete the requested service). + Probably in some version of Windows there are problems with other sizes: + for 32 MB (maybe also for 16 MB). + And message can be "Network connection was lost" +*/ + +#define kChunkSizeMax (1 << 22) + +#endif + +void File_Construct(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + p->handle = INVALID_HANDLE_VALUE; + #else + p->file = NULL; + #endif +} + +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +static WRes File_Open(CSzFile *p, const char *name, int writeMode) +{ + #ifdef USE_WINDOWS_FILE + p->handle = CreateFileA(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); + #else + p->file = fopen(name, writeMode ? "wb+" : "rb"); + return (p->file != 0) ? 0 : + #ifdef UNDER_CE + 2; /* ENOENT */ + #else + errno; + #endif + #endif +} + +WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } +WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } +#endif + +#ifdef USE_WINDOWS_FILE +static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) +{ + p->handle = CreateFileW(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); +} +WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } +#endif + +WRes File_Close(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + if (p->handle != INVALID_HANDLE_VALUE) + { + if (!CloseHandle(p->handle)) + return GetLastError(); + p->handle = INVALID_HANDLE_VALUE; + } + #else + if (p->file != NULL) + { + int res = fclose(p->file); + if (res != 0) + return res; + p->file = NULL; + } + #endif + return 0; +} + +WRes File_Read(CSzFile *p, void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fread(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Write(CSzFile *p, const void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fwrite(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) +{ + #ifdef USE_WINDOWS_FILE + + LARGE_INTEGER value; + DWORD moveMethod; + value.LowPart = (DWORD)*pos; + value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ + switch (origin) + { + case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; + case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; + case SZ_SEEK_END: moveMethod = FILE_END; break; + default: return ERROR_INVALID_PARAMETER; + } + value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); + if (value.LowPart == 0xFFFFFFFF) + { + WRes res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *pos = ((Int64)value.HighPart << 32) | value.LowPart; + return 0; + + #else + + int moveMethod; + int res; + switch (origin) + { + case SZ_SEEK_SET: moveMethod = SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = SEEK_END; break; + default: return 1; + } + res = fseek(p->file, (long)*pos, moveMethod); + *pos = ftell(p->file); + return res; + + #endif +} + +WRes File_GetLength(CSzFile *p, UInt64 *length) +{ + #ifdef USE_WINDOWS_FILE + + DWORD sizeHigh; + DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + { + DWORD res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *length = (((UInt64)sizeHigh) << 32) + sizeLow; + return 0; + + #else + + long pos = ftell(p->file); + int res = fseek(p->file, 0, SEEK_END); + *length = ftell(p->file); + fseek(p->file, pos, SEEK_SET); + return res; + + #endif +} + + +/* ---------- FileSeqInStream ---------- */ + +static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt); + return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; +} + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p) +{ + p->vt.Read = FileSeqInStream_Read; +} + + +/* ---------- FileInStream ---------- */ + +static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size) +{ + CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt); + return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin) +{ + CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt); + return File_Seek(&p->file, pos, origin); +} + +void FileInStream_CreateVTable(CFileInStream *p) +{ + p->vt.Read = FileInStream_Read; + p->vt.Seek = FileInStream_Seek; +} + + +/* ---------- FileOutStream ---------- */ + +static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size) +{ + CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt); + File_Write(&p->file, data, &size); + return size; +} + +void FileOutStream_CreateVTable(CFileOutStream *p) +{ + p->vt.Write = FileOutStream_Write; +} diff --git a/other-licenses/7zstub/src/C/7zFile.h b/other-licenses/7zstub/src/C/7zFile.h new file mode 100644 index 0000000000..7e263bea1b --- /dev/null +++ b/other-licenses/7zstub/src/C/7zFile.h @@ -0,0 +1,83 @@ +/* 7zFile.h -- File IO +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_FILE_H +#define __7Z_FILE_H + +#ifdef _WIN32 +#define USE_WINDOWS_FILE +#endif + +#ifdef USE_WINDOWS_FILE +#include +#else +#include +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* ---------- File ---------- */ + +typedef struct +{ + #ifdef USE_WINDOWS_FILE + HANDLE handle; + #else + FILE *file; + #endif +} CSzFile; + +void File_Construct(CSzFile *p); +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +WRes InFile_Open(CSzFile *p, const char *name); +WRes OutFile_Open(CSzFile *p, const char *name); +#endif +#ifdef USE_WINDOWS_FILE +WRes InFile_OpenW(CSzFile *p, const WCHAR *name); +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); +#endif +WRes File_Close(CSzFile *p); + +/* reads max(*size, remain file's size) bytes */ +WRes File_Read(CSzFile *p, void *data, size_t *size); + +/* writes *size bytes */ +WRes File_Write(CSzFile *p, const void *data, size_t *size); + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); +WRes File_GetLength(CSzFile *p, UInt64 *length); + + +/* ---------- FileInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + CSzFile file; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream vt; + CSzFile file; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream vt; + CSzFile file; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/7zStream.c b/other-licenses/7zstub/src/C/7zStream.c new file mode 100644 index 0000000000..579741fadc --- /dev/null +++ b/other-licenses/7zstub/src/C/7zStream.c @@ -0,0 +1,176 @@ +/* 7zStream.c -- 7z Stream functions +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zTypes.h" + +SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(ISeqInStream_Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size) +{ + return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf) +{ + size_t processed = 1; + RINOK(ISeqInStream_Read(stream, buf, &processed)); + return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; +} + + + +SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset) +{ + Int64 t = offset; + return ILookInStream_Seek(stream, &t, SZ_SEEK_SET); +} + +SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size) +{ + const void *lookBuf; + if (*size == 0) + return SZ_OK; + RINOK(ILookInStream_Look(stream, &lookBuf, size)); + memcpy(buf, lookBuf, *size); + return ILookInStream_Skip(stream, *size); +} + +SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(ILookInStream_Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size) +{ + return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + + + +#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt); + +static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + GET_LookToRead2 + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size != 0) + { + p->pos = 0; + p->size = 0; + size2 = p->bufSize; + res = ISeekInStream_Read(p->realStream, p->buf, &size2); + p->size = size2; + } + if (*size > size2) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + GET_LookToRead2 + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size != 0) + { + p->pos = 0; + p->size = 0; + if (*size > p->bufSize) + *size = p->bufSize; + res = ISeekInStream_Read(p->realStream, p->buf, size); + size2 = p->size = *size; + } + if (*size > size2) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset) +{ + GET_LookToRead2 + p->pos += offset; + return SZ_OK; +} + +static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size) +{ + GET_LookToRead2 + size_t rem = p->size - p->pos; + if (rem == 0) + return ISeekInStream_Read(p->realStream, buf, size); + if (rem > *size) + rem = *size; + memcpy(buf, p->buf + p->pos, rem); + p->pos += rem; + *size = rem; + return SZ_OK; +} + +static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin) +{ + GET_LookToRead2 + p->pos = p->size = 0; + return ISeekInStream_Seek(p->realStream, pos, origin); +} + +void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead) +{ + p->vt.Look = lookahead ? + LookToRead2_Look_Lookahead : + LookToRead2_Look_Exact; + p->vt.Skip = LookToRead2_Skip; + p->vt.Read = LookToRead2_Read; + p->vt.Seek = LookToRead2_Seek; +} + + + +static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt); + return LookInStream_LookRead(p->realStream, buf, size); +} + +void SecToLook_CreateVTable(CSecToLook *p) +{ + p->vt.Read = SecToLook_Read; +} + +static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt); + return ILookInStream_Read(p->realStream, buf, size); +} + +void SecToRead_CreateVTable(CSecToRead *p) +{ + p->vt.Read = SecToRead_Read; +} diff --git a/other-licenses/7zstub/src/C/7zTypes.h b/other-licenses/7zstub/src/C/7zTypes.h new file mode 100644 index 0000000000..4977cdaa66 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zTypes.h @@ -0,0 +1,374 @@ +/* 7zTypes.h -- Basic types +2017-07-17 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#ifdef _WIN32 +/* #include */ +#endif + +#include + +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + + +#ifdef _WIN32 + +/* typedef DWORD WRes; */ +typedef unsigned WRes; +#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) + +#else + +typedef int WRes; +#define MY__FACILITY_WIN32 7 +#define MY__FACILITY__WRes MY__FACILITY_WIN32 +#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000))) + +#endif + + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_FORCE_INLINE __forceinline + +#define MY_CDECL __cdecl +#define MY_FAST_CALL __fastcall + +#else + +#define MY_NO_INLINE +#define MY_FORCE_INLINE +#define MY_CDECL +#define MY_FAST_CALL + +/* inline keyword : for C++ / C99 */ + +/* GCC, clang: */ +/* +#if defined (__GNUC__) && (__GNUC__ >= 4) +#define MY_FORCE_INLINE __attribute__((always_inline)) +#define MY_NO_INLINE __attribute__((noinline)) +#endif +*/ + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct IByteIn IByteIn; +struct IByteIn +{ + Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */ +}; +#define IByteIn_Read(p) (p)->Read(p) + + +typedef struct IByteOut IByteOut; +struct IByteOut +{ + void (*Write)(const IByteOut *p, Byte b); +}; +#define IByteOut_Write(p, b) (p)->Write(p, b) + + +typedef struct ISeqInStream ISeqInStream; +struct ISeqInStream +{ + SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +}; +#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size) + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf); + + +typedef struct ISeqOutStream ISeqOutStream; +struct ISeqOutStream +{ + size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +}; +#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size) + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + + +typedef struct ISeekInStream ISeekInStream; +struct ISeekInStream +{ + SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin); +}; +#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size) +#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) + + +typedef struct ILookInStream ILookInStream; +struct ILookInStream +{ + SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(const ILookInStream *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(const ILookInStream *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin); +}; + +#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size) +#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset) +#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size) +#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) + + +SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size); + + + +typedef struct +{ + ILookInStream vt; + const ISeekInStream *realStream; + + size_t pos; + size_t size; /* it's data size */ + + /* the following variables must be set outside */ + Byte *buf; + size_t bufSize; +} CLookToRead2; + +void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead); + +#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; } + + +typedef struct +{ + ISeqInStream vt; + const ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + + + +typedef struct +{ + ISeqInStream vt; + const ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + + +typedef struct ICompressProgress ICompressProgress; + +struct ICompressProgress +{ + SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +}; +#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize) + + + +typedef struct ISzAlloc ISzAlloc; +typedef const ISzAlloc * ISzAllocPtr; + +struct ISzAlloc +{ + void *(*Alloc)(ISzAllocPtr p, size_t size); + void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */ +}; + +#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size) +#define ISzAlloc_Free(p, a) (p)->Free(p, a) + +/* deprecated */ +#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size) +#define IAlloc_Free(p, a) ISzAlloc_Free(p, a) + + + + + +#ifndef MY_offsetof + #ifdef offsetof + #define MY_offsetof(type, m) offsetof(type, m) + /* + #define MY_offsetof(type, m) FIELD_OFFSET(type, m) + */ + #else + #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m)) + #endif +#endif + + + +#ifndef MY_container_of + +/* +#define MY_container_of(ptr, type, m) container_of(ptr, type, m) +#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m) +#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m))) +#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m)))) +*/ + +/* + GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly" + GCC 3.4.4 : classes with constructor + GCC 4.8.1 : classes with non-public variable members" +*/ + +#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) + + +#endif + +#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr)) + +/* +#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +*/ +#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m) + +#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +/* +#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m) +*/ + + + +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/7zVersion.h b/other-licenses/7zstub/src/C/7zVersion.h new file mode 100644 index 0000000000..ed3aa94270 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zVersion.h @@ -0,0 +1,27 @@ +#define MY_VER_MAJOR 18 +#define MY_VER_MINOR 05 +#define MY_VER_BUILD 0 +#define MY_VERSION_NUMBERS "18.05" +#define MY_VERSION MY_VERSION_NUMBERS + +#ifdef MY_CPU_NAME + #define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")" +#else + #define MY_VERSION_CPU MY_VERSION +#endif + +#define MY_DATE "2018-04-30" +#undef MY_COPYRIGHT +#undef MY_VERSION_COPYRIGHT_DATE +#define MY_AUTHOR_NAME "Igor Pavlov" +#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" +#define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov" + +#ifdef USE_COPYRIGHT_CR + #define MY_COPYRIGHT MY_COPYRIGHT_CR +#else + #define MY_COPYRIGHT MY_COPYRIGHT_PD +#endif + +#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE diff --git a/other-licenses/7zstub/src/C/7zVersion.rc b/other-licenses/7zstub/src/C/7zVersion.rc new file mode 100644 index 0000000000..6ed26de744 --- /dev/null +++ b/other-licenses/7zstub/src/C/7zVersion.rc @@ -0,0 +1,55 @@ +#define MY_VS_FFI_FILEFLAGSMASK 0x0000003FL +#define MY_VOS_NT_WINDOWS32 0x00040004L +#define MY_VOS_CE_WINDOWS32 0x00050004L + +#define MY_VFT_APP 0x00000001L +#define MY_VFT_DLL 0x00000002L + +// #include + +#ifndef MY_VERSION +#include "7zVersion.h" +#endif + +#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 + +#ifdef DEBUG +#define DBG_FL VS_FF_DEBUG +#else +#define DBG_FL 0 +#endif + +#define MY_VERSION_INFO(fileType, descr, intName, origName) \ +LANGUAGE 9, 1 \ +1 VERSIONINFO \ + FILEVERSION MY_VER \ + PRODUCTVERSION MY_VER \ + FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \ + FILEFLAGS DBG_FL \ + FILEOS MY_VOS_NT_WINDOWS32 \ + FILETYPE fileType \ + FILESUBTYPE 0x0L \ +BEGIN \ + BLOCK "StringFileInfo" \ + BEGIN \ + BLOCK "040904b0" \ + BEGIN \ + VALUE "CompanyName", "Igor Pavlov" \ + VALUE "FileDescription", descr \ + VALUE "FileVersion", MY_VERSION \ + VALUE "InternalName", intName \ + VALUE "LegalCopyright", MY_COPYRIGHT \ + VALUE "OriginalFilename", origName \ + VALUE "ProductName", "7-Zip" \ + VALUE "ProductVersion", MY_VERSION \ + END \ + END \ + BLOCK "VarFileInfo" \ + BEGIN \ + VALUE "Translation", 0x409, 1200 \ + END \ +END + +#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe") + +#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll") diff --git a/other-licenses/7zstub/src/C/Aes.c b/other-licenses/7zstub/src/C/Aes.c new file mode 100644 index 0000000000..8f7d50ea24 --- /dev/null +++ b/other-licenses/7zstub/src/C/Aes.c @@ -0,0 +1,306 @@ +/* Aes.c -- AES encryption / decryption +2017-01-24 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Aes.h" +#include "CpuArch.h" + +static UInt32 T[256 * 4]; +static const Byte Sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; + +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); + +AES_CODE_FUNC g_AesCbc_Encode; +AES_CODE_FUNC g_AesCbc_Decode; +AES_CODE_FUNC g_AesCtr_Code; + +static UInt32 D[256 * 4]; +static Byte InvS[256]; + +static const Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; + +#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF) + +#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24)) + +#define gb0(x) ( (x) & 0xFF) +#define gb1(x) (((x) >> ( 8)) & 0xFF) +#define gb2(x) (((x) >> (16)) & 0xFF) +#define gb3(x) (((x) >> (24))) + +#define gb(n, x) gb ## n(x) + +#define TT(x) (T + (x << 8)) +#define DD(x) (D + (x << 8)) + + +void AesGenTables(void) +{ + unsigned i; + for (i = 0; i < 256; i++) + InvS[Sbox[i]] = (Byte)i; + + for (i = 0; i < 256; i++) + { + { + UInt32 a1 = Sbox[i]; + UInt32 a2 = xtime(a1); + UInt32 a3 = a2 ^ a1; + TT(0)[i] = Ui32(a2, a1, a1, a3); + TT(1)[i] = Ui32(a3, a2, a1, a1); + TT(2)[i] = Ui32(a1, a3, a2, a1); + TT(3)[i] = Ui32(a1, a1, a3, a2); + } + { + UInt32 a1 = InvS[i]; + UInt32 a2 = xtime(a1); + UInt32 a4 = xtime(a2); + UInt32 a8 = xtime(a4); + UInt32 a9 = a8 ^ a1; + UInt32 aB = a8 ^ a2 ^ a1; + UInt32 aD = a8 ^ a4 ^ a1; + UInt32 aE = a8 ^ a4 ^ a2; + DD(0)[i] = Ui32(aE, a9, aD, aB); + DD(1)[i] = Ui32(aB, aE, a9, aD); + DD(2)[i] = Ui32(aD, aB, aE, a9); + DD(3)[i] = Ui32(a9, aD, aB, aE); + } + } + + g_AesCbc_Encode = AesCbc_Encode; + g_AesCbc_Decode = AesCbc_Decode; + g_AesCtr_Code = AesCtr_Code; + + #ifdef MY_CPU_X86_OR_AMD64 + if (CPU_Is_Aes_Supported()) + { + g_AesCbc_Encode = AesCbc_Encode_Intel; + g_AesCbc_Decode = AesCbc_Decode_Intel; + g_AesCtr_Code = AesCtr_Code_Intel; + } + #endif +} + + +#define HT(i, x, s) TT(x)[gb(x, s[(i + x) & 3])] + +#define HT4(m, i, s, p) m[i] = \ + HT(i, 0, s) ^ \ + HT(i, 1, s) ^ \ + HT(i, 2, s) ^ \ + HT(i, 3, s) ^ w[p + i] + +#define HT16(m, s, p) \ + HT4(m, 0, s, p); \ + HT4(m, 1, s, p); \ + HT4(m, 2, s, p); \ + HT4(m, 3, s, p); \ + +#define FT(i, x) Sbox[gb(x, m[(i + x) & 3])] +#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i]; + + +#define HD(i, x, s) DD(x)[gb(x, s[(i - x) & 3])] + +#define HD4(m, i, s, p) m[i] = \ + HD(i, 0, s) ^ \ + HD(i, 1, s) ^ \ + HD(i, 2, s) ^ \ + HD(i, 3, s) ^ w[p + i]; + +#define HD16(m, s, p) \ + HD4(m, 0, s, p); \ + HD4(m, 1, s, p); \ + HD4(m, 2, s, p); \ + HD4(m, 3, s, p); \ + +#define FD(i, x) InvS[gb(x, m[(i - x) & 3])] +#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i]; + +void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize) +{ + unsigned i, wSize; + wSize = keySize + 28; + keySize /= 4; + w[0] = ((UInt32)keySize / 2) + 3; + w += 4; + + for (i = 0; i < keySize; i++, key += 4) + w[i] = GetUi32(key); + + for (; i < wSize; i++) + { + UInt32 t = w[(size_t)i - 1]; + unsigned rem = i % keySize; + if (rem == 0) + t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]); + else if (keySize > 6 && rem == 4) + t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]); + w[i] = w[i - keySize] ^ t; + } +} + +void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize) +{ + unsigned i, num; + Aes_SetKey_Enc(w, key, keySize); + num = keySize + 20; + w += 8; + for (i = 0; i < num; i++) + { + UInt32 r = w[i]; + w[i] = + DD(0)[Sbox[gb0(r)]] ^ + DD(1)[Sbox[gb1(r)]] ^ + DD(2)[Sbox[gb2(r)]] ^ + DD(3)[Sbox[gb3(r)]]; + } +} + +/* Aes_Encode and Aes_Decode functions work with little-endian words. + src and dest are pointers to 4 UInt32 words. + src and dest can point to same block */ + +static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src) +{ + UInt32 s[4]; + UInt32 m[4]; + UInt32 numRounds2 = w[0]; + w += 4; + s[0] = src[0] ^ w[0]; + s[1] = src[1] ^ w[1]; + s[2] = src[2] ^ w[2]; + s[3] = src[3] ^ w[3]; + w += 4; + for (;;) + { + HT16(m, s, 0); + if (--numRounds2 == 0) + break; + HT16(s, m, 4); + w += 8; + } + w += 4; + FT4(0); FT4(1); FT4(2); FT4(3); +} + +static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src) +{ + UInt32 s[4]; + UInt32 m[4]; + UInt32 numRounds2 = w[0]; + w += 4 + numRounds2 * 8; + s[0] = src[0] ^ w[0]; + s[1] = src[1] ^ w[1]; + s[2] = src[2] ^ w[2]; + s[3] = src[3] ^ w[3]; + for (;;) + { + w -= 8; + HD16(m, s, 4); + if (--numRounds2 == 0) + break; + HD16(s, m, 0); + } + FD4(0); FD4(1); FD4(2); FD4(3); +} + +void AesCbc_Init(UInt32 *p, const Byte *iv) +{ + unsigned i; + for (i = 0; i < 4; i++) + p[i] = GetUi32(iv + i * 4); +} + +void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks) +{ + for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) + { + p[0] ^= GetUi32(data); + p[1] ^= GetUi32(data + 4); + p[2] ^= GetUi32(data + 8); + p[3] ^= GetUi32(data + 12); + + Aes_Encode(p + 4, p, p); + + SetUi32(data, p[0]); + SetUi32(data + 4, p[1]); + SetUi32(data + 8, p[2]); + SetUi32(data + 12, p[3]); + } +} + +void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks) +{ + UInt32 in[4], out[4]; + for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) + { + in[0] = GetUi32(data); + in[1] = GetUi32(data + 4); + in[2] = GetUi32(data + 8); + in[3] = GetUi32(data + 12); + + Aes_Decode(p + 4, out, in); + + SetUi32(data, p[0] ^ out[0]); + SetUi32(data + 4, p[1] ^ out[1]); + SetUi32(data + 8, p[2] ^ out[2]); + SetUi32(data + 12, p[3] ^ out[3]); + + p[0] = in[0]; + p[1] = in[1]; + p[2] = in[2]; + p[3] = in[3]; + } +} + +void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks) +{ + for (; numBlocks != 0; numBlocks--) + { + UInt32 temp[4]; + unsigned i; + + if (++p[0] == 0) + p[1]++; + + Aes_Encode(p + 4, temp, p); + + for (i = 0; i < 4; i++, data += 4) + { + UInt32 t = temp[i]; + + #ifdef MY_CPU_LE_UNALIGN + *((UInt32 *)data) ^= t; + #else + data[0] ^= (t & 0xFF); + data[1] ^= ((t >> 8) & 0xFF); + data[2] ^= ((t >> 16) & 0xFF); + data[3] ^= ((t >> 24)); + #endif + } + } +} diff --git a/other-licenses/7zstub/src/C/Aes.h b/other-licenses/7zstub/src/C/Aes.h new file mode 100644 index 0000000000..381e979d1b --- /dev/null +++ b/other-licenses/7zstub/src/C/Aes.h @@ -0,0 +1,38 @@ +/* Aes.h -- AES encryption / decryption +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __AES_H +#define __AES_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define AES_BLOCK_SIZE 16 + +/* Call AesGenTables one time before other AES functions */ +void AesGenTables(void); + +/* UInt32 pointers must be 16-byte aligned */ + +/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */ +#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4) + +/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */ +/* keySize = 16 or 24 or 32 (bytes) */ +typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize); +void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize); +void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize); + +/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */ +void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */ +/* data - 16-byte aligned pointer to data */ +/* numBlocks - the number of 16-byte blocks in data array */ +typedef void (MY_FAST_CALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks); +extern AES_CODE_FUNC g_AesCbc_Encode; +extern AES_CODE_FUNC g_AesCbc_Decode; +extern AES_CODE_FUNC g_AesCtr_Code; + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/AesOpt.c b/other-licenses/7zstub/src/C/AesOpt.c new file mode 100644 index 0000000000..0e7f49a1b0 --- /dev/null +++ b/other-licenses/7zstub/src/C/AesOpt.c @@ -0,0 +1,184 @@ +/* AesOpt.c -- Intel's AES +2017-06-08 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 +#if (_MSC_VER > 1500) || (_MSC_FULL_VER >= 150030729) +#define USE_INTEL_AES +#endif +#endif + +#ifdef USE_INTEL_AES + +#include + +void MY_FAST_CALL AesCbc_Encode_Intel(__m128i *p, __m128i *data, size_t numBlocks) +{ + __m128i m = *p; + for (; numBlocks != 0; numBlocks--, data++) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; + const __m128i *w = p + 3; + m = _mm_xor_si128(m, *data); + m = _mm_xor_si128(m, p[2]); + do + { + m = _mm_aesenc_si128(m, w[0]); + m = _mm_aesenc_si128(m, w[1]); + w += 2; + } + while (--numRounds2 != 0); + m = _mm_aesenc_si128(m, w[0]); + m = _mm_aesenclast_si128(m, w[1]); + *data = m; + } + *p = m; +} + +#define NUM_WAYS 3 + +#define AES_OP_W(op, n) { \ + const __m128i t = w[n]; \ + m0 = op(m0, t); \ + m1 = op(m1, t); \ + m2 = op(m2, t); \ + } + +#define AES_DEC(n) AES_OP_W(_mm_aesdec_si128, n) +#define AES_DEC_LAST(n) AES_OP_W(_mm_aesdeclast_si128, n) +#define AES_ENC(n) AES_OP_W(_mm_aesenc_si128, n) +#define AES_ENC_LAST(n) AES_OP_W(_mm_aesenclast_si128, n) + +void MY_FAST_CALL AesCbc_Decode_Intel(__m128i *p, __m128i *data, size_t numBlocks) +{ + __m128i iv = *p; + for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1); + const __m128i *w = p + numRounds2 * 2; + __m128i m0, m1, m2; + { + const __m128i t = w[2]; + m0 = _mm_xor_si128(t, data[0]); + m1 = _mm_xor_si128(t, data[1]); + m2 = _mm_xor_si128(t, data[2]); + } + numRounds2--; + do + { + AES_DEC(1) + AES_DEC(0) + w -= 2; + } + while (--numRounds2 != 0); + AES_DEC(1) + AES_DEC_LAST(0) + + { + __m128i t; + t = _mm_xor_si128(m0, iv); iv = data[0]; data[0] = t; + t = _mm_xor_si128(m1, iv); iv = data[1]; data[1] = t; + t = _mm_xor_si128(m2, iv); iv = data[2]; data[2] = t; + } + } + for (; numBlocks != 0; numBlocks--, data++) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1); + const __m128i *w = p + numRounds2 * 2; + __m128i m = _mm_xor_si128(w[2], *data); + numRounds2--; + do + { + m = _mm_aesdec_si128(m, w[1]); + m = _mm_aesdec_si128(m, w[0]); + w -= 2; + } + while (--numRounds2 != 0); + m = _mm_aesdec_si128(m, w[1]); + m = _mm_aesdeclast_si128(m, w[0]); + + m = _mm_xor_si128(m, iv); + iv = *data; + *data = m; + } + *p = iv; +} + +void MY_FAST_CALL AesCtr_Code_Intel(__m128i *p, __m128i *data, size_t numBlocks) +{ + __m128i ctr = *p; + __m128i one; + one.m128i_u64[0] = 1; + one.m128i_u64[1] = 0; + for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; + const __m128i *w = p; + __m128i m0, m1, m2; + { + const __m128i t = w[2]; + ctr = _mm_add_epi64(ctr, one); m0 = _mm_xor_si128(ctr, t); + ctr = _mm_add_epi64(ctr, one); m1 = _mm_xor_si128(ctr, t); + ctr = _mm_add_epi64(ctr, one); m2 = _mm_xor_si128(ctr, t); + } + w += 3; + do + { + AES_ENC(0) + AES_ENC(1) + w += 2; + } + while (--numRounds2 != 0); + AES_ENC(0) + AES_ENC_LAST(1) + data[0] = _mm_xor_si128(data[0], m0); + data[1] = _mm_xor_si128(data[1], m1); + data[2] = _mm_xor_si128(data[2], m2); + } + for (; numBlocks != 0; numBlocks--, data++) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; + const __m128i *w = p; + __m128i m; + ctr = _mm_add_epi64(ctr, one); + m = _mm_xor_si128(ctr, p[2]); + w += 3; + do + { + m = _mm_aesenc_si128(m, w[0]); + m = _mm_aesenc_si128(m, w[1]); + w += 2; + } + while (--numRounds2 != 0); + m = _mm_aesenc_si128(m, w[0]); + m = _mm_aesenclast_si128(m, w[1]); + *data = _mm_xor_si128(*data, m); + } + *p = ctr; +} + +#else + +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 *p, Byte *data, size_t numBlocks) +{ + AesCbc_Encode(p, data, numBlocks); +} + +void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *p, Byte *data, size_t numBlocks) +{ + AesCbc_Decode(p, data, numBlocks); +} + +void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *p, Byte *data, size_t numBlocks) +{ + AesCtr_Code(p, data, numBlocks); +} + +#endif diff --git a/other-licenses/7zstub/src/C/Alloc.c b/other-licenses/7zstub/src/C/Alloc.c new file mode 100644 index 0000000000..30b499e5ff --- /dev/null +++ b/other-licenses/7zstub/src/C/Alloc.c @@ -0,0 +1,455 @@ +/* Alloc.c -- Memory allocation functions +2018-04-27 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#ifdef _WIN32 +#include +#endif +#include + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ + +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG + +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; + + +#define CONVERT_INT_TO_STR(charType, tempSize) \ + unsigned char temp[tempSize]; unsigned i = 0; \ + while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ + *s++ = (charType)('0' + (unsigned)val); \ + while (i != 0) { i--; *s++ = temp[i]; } \ + *s = 0; + +static void ConvertUInt64ToString(UInt64 val, char *s) +{ + CONVERT_INT_TO_STR(char, 24); +} + +#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + +static void ConvertUInt64ToHex(UInt64 val, char *s) +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0xF); + val >>= 4; + s[--i] = GET_HEX_CHAR(t); + } + while (i); +} + +#define DEBUG_OUT_STREAM stderr + +static void Print(const char *s) +{ + fputs(s, DEBUG_OUT_STREAM); +} + +static void PrintAligned(const char *s, size_t align) +{ + size_t len = strlen(s); + for(;;) + { + fputc(' ', DEBUG_OUT_STREAM); + if (len >= align) + break; + ++len; + } + Print(s); +} + +static void PrintLn() +{ + Print("\n"); +} + +static void PrintHex(UInt64 v, size_t align) +{ + char s[32]; + ConvertUInt64ToHex(v, s); + PrintAligned(s, align); +} + +static void PrintDec(UInt64 v, size_t align) +{ + char s[32]; + ConvertUInt64ToString(v, s); + PrintAligned(s, align); +} + +static void PrintAddr(void *p) +{ + PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12); +} + + +#define PRINT_ALLOC(name, cnt, size, ptr) \ + Print(name " "); \ + PrintDec(cnt++, 10); \ + PrintHex(size, 10); \ + PrintAddr(ptr); \ + PrintLn(); + +#define PRINT_FREE(name, cnt, ptr) if (ptr) { \ + Print(name " "); \ + PrintDec(--cnt, 10); \ + PrintAddr(ptr); \ + PrintLn(); } + +#else + +#define PRINT_ALLOC(name, cnt, size, ptr) +#define PRINT_FREE(name, cnt, ptr) +#define Print(s) +#define PrintLn() +#define PrintHex(v, align) +#define PrintDec(v, align) +#define PrintAddr(p) + +#endif + + + +void *MyAlloc(size_t size) +{ + if (size == 0) + return NULL; + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + PRINT_ALLOC("Alloc ", g_allocCount, size, p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + PRINT_FREE("Free ", g_allocCount, address); + + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return NULL; + + PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL); + + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + PRINT_FREE("Free-Mid", g_allocCountMid, address); + + if (!address) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifndef MEM_LARGE_PAGES +#undef _7ZIP_LARGE_PAGES +#endif + +#ifdef _7ZIP_LARGE_PAGES +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); +#endif + +void SetLargePageSize() +{ + #ifdef _7ZIP_LARGE_PAGES + SIZE_T size; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (!largePageMinimum) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return NULL; + + PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL); + + #ifdef _7ZIP_LARGE_PAGES + { + SIZE_T ps = g_LargePageSize; + if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) + { + size_t size2; + ps--; + size2 = (size + ps) & ~ps; + if (size2 >= size) + { + void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res) + return res; + } + } + } + #endif + + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + PRINT_FREE("Free-Big", g_allocCountBig, address); + + if (!address) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif + + +static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); } +static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); } +const ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); } +static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); } +const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; + +static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); } +static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); } +const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + + +/* + uintptr_t : C99 (optional) + : unsupported in VS6 +*/ + +#ifdef _WIN32 + typedef UINT_PTR UIntPtr; +#else + /* + typedef uintptr_t UIntPtr; + */ + typedef ptrdiff_t UIntPtr; +#endif + + +#define ADJUST_ALLOC_SIZE 0 +/* +#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1) +*/ +/* + Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if + MyAlloc() can return address that is NOT multiple of sizeof(void *). +*/ + + +/* +#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1)))) +*/ +#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1)))) + +#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align) + + +#if (_POSIX_C_SOURCE >= 200112L) && !defined(_WIN32) + #define USE_posix_memalign +#endif + +/* + This posix_memalign() is for test purposes only. + We also need special Free() function instead of free(), + if this posix_memalign() is used. +*/ + +/* +static int posix_memalign(void **ptr, size_t align, size_t size) +{ + size_t newSize = size + align; + void *p; + void *pAligned; + *ptr = NULL; + if (newSize < size) + return 12; // ENOMEM + p = MyAlloc(newSize); + if (!p) + return 12; // ENOMEM + pAligned = MY_ALIGN_PTR_UP_PLUS(p, align); + ((void **)pAligned)[-1] = p; + *ptr = pAligned; + return 0; +} +*/ + +/* + ALLOC_ALIGN_SIZE >= sizeof(void *) + ALLOC_ALIGN_SIZE >= cache_line_size +*/ + +#define ALLOC_ALIGN_SIZE ((size_t)1 << 7) + +static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) +{ + #ifndef USE_posix_memalign + + void *p; + void *pAligned; + size_t newSize; + UNUSED_VAR(pp); + + /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned + block to prevent cache line sharing with another allocated blocks */ + + newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE; + if (newSize < size) + return NULL; + + p = MyAlloc(newSize); + + if (!p) + return NULL; + pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE); + + Print(" size="); PrintHex(size, 8); + Print(" a_size="); PrintHex(newSize, 8); + Print(" ptr="); PrintAddr(p); + Print(" a_ptr="); PrintAddr(pAligned); + PrintLn(); + + ((void **)pAligned)[-1] = p; + + return pAligned; + + #else + + void *p; + UNUSED_VAR(pp); + if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) + return NULL; + + Print(" posix_memalign="); PrintAddr(p); + PrintLn(); + + return p; + + #endif +} + + +static void SzAlignedFree(ISzAllocPtr pp, void *address) +{ + UNUSED_VAR(pp); + #ifndef USE_posix_memalign + if (address) + MyFree(((void **)address)[-1]); + #else + free(address); + #endif +} + + +const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree }; + + + +#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *)) + +/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ +#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] +/* +#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1] +*/ + +static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) +{ + CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt); + void *adr; + void *pAligned; + size_t newSize; + size_t extra; + size_t alignSize = (size_t)1 << p->numAlignBits; + + if (alignSize < sizeof(void *)) + alignSize = sizeof(void *); + + if (p->offset >= alignSize) + return NULL; + + /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned + block to prevent cache line sharing with another allocated blocks */ + extra = p->offset & (sizeof(void *) - 1); + newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE; + if (newSize < size) + return NULL; + + adr = ISzAlloc_Alloc(p->baseAlloc, newSize); + + if (!adr) + return NULL; + + pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + + alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; + + PrintLn(); + Print("- Aligned: "); + Print(" size="); PrintHex(size, 8); + Print(" a_size="); PrintHex(newSize, 8); + Print(" ptr="); PrintAddr(adr); + Print(" a_ptr="); PrintAddr(pAligned); + PrintLn(); + + REAL_BLOCK_PTR_VAR(pAligned) = adr; + + return pAligned; +} + + +static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) +{ + if (address) + { + CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt); + PrintLn(); + Print("- Aligned Free: "); + PrintLn(); + ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); + } +} + + +void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p) +{ + p->vt.Alloc = AlignOffsetAlloc_Alloc; + p->vt.Free = AlignOffsetAlloc_Free; +} diff --git a/other-licenses/7zstub/src/C/Alloc.h b/other-licenses/7zstub/src/C/Alloc.h new file mode 100644 index 0000000000..3d796e5eee --- /dev/null +++ b/other-licenses/7zstub/src/C/Alloc.h @@ -0,0 +1,51 @@ +/* Alloc.h -- Memory allocation functions +2018-02-19 : Igor Pavlov : Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void *MyAlloc(size_t size); +void MyFree(void *address); + +#ifdef _WIN32 + +void SetLargePageSize(); + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +extern const ISzAlloc g_Alloc; +extern const ISzAlloc g_BigAlloc; +extern const ISzAlloc g_MidAlloc; +extern const ISzAlloc g_AlignedAlloc; + + +typedef struct +{ + ISzAlloc vt; + ISzAllocPtr baseAlloc; + unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */ + size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */ +} CAlignOffsetAlloc; + +void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p); + + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Bcj2.c b/other-licenses/7zstub/src/C/Bcj2.c new file mode 100644 index 0000000000..da93985cf6 --- /dev/null +++ b/other-licenses/7zstub/src/C/Bcj2.c @@ -0,0 +1,257 @@ +/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) +2018-04-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bcj2.h" +#include "CpuArch.h" + +#define CProb UInt16 + +#define kTopValue ((UInt32)1 << 24) +#define kNumModelBits 11 +#define kBitModelTotal (1 << kNumModelBits) +#define kNumMoveBits 5 + +#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound) +#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits)); + +void Bcj2Dec_Init(CBcj2Dec *p) +{ + unsigned i; + + p->state = BCJ2_DEC_STATE_OK; + p->ip = 0; + p->temp[3] = 0; + p->range = 0; + p->code = 0; + for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) + p->probs[i] = kBitModelTotal >> 1; +} + +SRes Bcj2Dec_Decode(CBcj2Dec *p) +{ + if (p->range <= 5) + { + p->state = BCJ2_DEC_STATE_OK; + for (; p->range != 5; p->range++) + { + if (p->range == 1 && p->code != 0) + return SZ_ERROR_DATA; + + if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) + { + p->state = BCJ2_STREAM_RC; + return SZ_OK; + } + + p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; + } + + if (p->code == 0xFFFFFFFF) + return SZ_ERROR_DATA; + + p->range = 0xFFFFFFFF; + } + else if (p->state >= BCJ2_DEC_STATE_ORIG_0) + { + while (p->state <= BCJ2_DEC_STATE_ORIG_3) + { + Byte *dest = p->dest; + if (dest == p->destLim) + return SZ_OK; + *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0]; + p->state++; + p->dest = dest + 1; + } + } + + /* + if (BCJ2_IS_32BIT_STREAM(p->state)) + { + const Byte *cur = p->bufs[p->state]; + if (cur == p->lims[p->state]) + return SZ_OK; + p->bufs[p->state] = cur + 4; + + { + UInt32 val; + Byte *dest; + SizeT rem; + + p->ip += 4; + val = GetBe32(cur) - p->ip; + dest = p->dest; + rem = p->destLim - dest; + if (rem < 4) + { + SizeT i; + SetUi32(p->temp, val); + for (i = 0; i < rem; i++) + dest[i] = p->temp[i]; + p->dest = dest + rem; + p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; + return SZ_OK; + } + SetUi32(dest, val); + p->temp[3] = (Byte)(val >> 24); + p->dest = dest + 4; + p->state = BCJ2_DEC_STATE_OK; + } + } + */ + + for (;;) + { + if (BCJ2_IS_32BIT_STREAM(p->state)) + p->state = BCJ2_DEC_STATE_OK; + else + { + if (p->range < kTopValue) + { + if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) + { + p->state = BCJ2_STREAM_RC; + return SZ_OK; + } + p->range <<= 8; + p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; + } + + { + const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; + const Byte *srcLim; + Byte *dest; + SizeT num = p->lims[BCJ2_STREAM_MAIN] - src; + + if (num == 0) + { + p->state = BCJ2_STREAM_MAIN; + return SZ_OK; + } + + dest = p->dest; + if (num > (SizeT)(p->destLim - dest)) + { + num = p->destLim - dest; + if (num == 0) + { + p->state = BCJ2_DEC_STATE_ORIG; + return SZ_OK; + } + } + + srcLim = src + num; + + if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80) + *dest = src[0]; + else for (;;) + { + Byte b = *src; + *dest = b; + if (b != 0x0F) + { + if ((b & 0xFE) == 0xE8) + break; + dest++; + if (++src != srcLim) + continue; + break; + } + dest++; + if (++src == srcLim) + break; + if ((*src & 0xF0) != 0x80) + continue; + *dest = *src; + break; + } + + num = src - p->bufs[BCJ2_STREAM_MAIN]; + + if (src == srcLim) + { + p->temp[3] = src[-1]; + p->bufs[BCJ2_STREAM_MAIN] = src; + p->ip += (UInt32)num; + p->dest += num; + p->state = + p->bufs[BCJ2_STREAM_MAIN] == + p->lims[BCJ2_STREAM_MAIN] ? + (unsigned)BCJ2_STREAM_MAIN : + (unsigned)BCJ2_DEC_STATE_ORIG; + return SZ_OK; + } + + { + UInt32 bound, ttt; + CProb *prob; + Byte b = src[0]; + Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]); + + p->temp[3] = b; + p->bufs[BCJ2_STREAM_MAIN] = src + 1; + num++; + p->ip += (UInt32)num; + p->dest += num; + + prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0)); + + _IF_BIT_0 + { + _UPDATE_0 + continue; + } + _UPDATE_1 + + } + } + } + + { + UInt32 val; + unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; + const Byte *cur = p->bufs[cj]; + Byte *dest; + SizeT rem; + + if (cur == p->lims[cj]) + { + p->state = cj; + break; + } + + val = GetBe32(cur); + p->bufs[cj] = cur + 4; + + p->ip += 4; + val -= p->ip; + dest = p->dest; + rem = p->destLim - dest; + + if (rem < 4) + { + p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8; + p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8; + p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8; + p->temp[3] = (Byte)val; + p->dest = dest + rem; + p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; + break; + } + + SetUi32(dest, val); + p->temp[3] = (Byte)(val >> 24); + p->dest = dest + 4; + } + } + + if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC]) + { + p->range <<= 8; + p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; + } + + return SZ_OK; +} diff --git a/other-licenses/7zstub/src/C/Bcj2.h b/other-licenses/7zstub/src/C/Bcj2.h new file mode 100644 index 0000000000..68893d2d12 --- /dev/null +++ b/other-licenses/7zstub/src/C/Bcj2.h @@ -0,0 +1,146 @@ +/* Bcj2.h -- BCJ2 Converter for x86 code +2014-11-10 : Igor Pavlov : Public domain */ + +#ifndef __BCJ2_H +#define __BCJ2_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define BCJ2_NUM_STREAMS 4 + +enum +{ + BCJ2_STREAM_MAIN, + BCJ2_STREAM_CALL, + BCJ2_STREAM_JUMP, + BCJ2_STREAM_RC +}; + +enum +{ + BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS, + BCJ2_DEC_STATE_ORIG_1, + BCJ2_DEC_STATE_ORIG_2, + BCJ2_DEC_STATE_ORIG_3, + + BCJ2_DEC_STATE_ORIG, + BCJ2_DEC_STATE_OK +}; + +enum +{ + BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS, + BCJ2_ENC_STATE_OK +}; + + +#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) + +/* +CBcj2Dec / CBcj2Enc +bufs sizes: + BUF_SIZE(n) = lims[n] - bufs[n] +bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4: + (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0 + (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0 +*/ + +/* +CBcj2Dec: +dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: + bufs[BCJ2_STREAM_MAIN] >= dest && + bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv + + BUF_SIZE(BCJ2_STREAM_CALL) + + BUF_SIZE(BCJ2_STREAM_JUMP) + tempReserv = 0 : for first call of Bcj2Dec_Decode + tempReserv = 4 : for any other calls of Bcj2Dec_Decode + overlap with offset = 1 is not allowed +*/ + +typedef struct +{ + const Byte *bufs[BCJ2_NUM_STREAMS]; + const Byte *lims[BCJ2_NUM_STREAMS]; + Byte *dest; + const Byte *destLim; + + unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ + + UInt32 ip; + Byte temp[4]; + UInt32 range; + UInt32 code; + UInt16 probs[2 + 256]; +} CBcj2Dec; + +void Bcj2Dec_Init(CBcj2Dec *p); + +/* Returns: SZ_OK or SZ_ERROR_DATA */ +SRes Bcj2Dec_Decode(CBcj2Dec *p); + +#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0) + + + +typedef enum +{ + BCJ2_ENC_FINISH_MODE_CONTINUE, + BCJ2_ENC_FINISH_MODE_END_BLOCK, + BCJ2_ENC_FINISH_MODE_END_STREAM +} EBcj2Enc_FinishMode; + +typedef struct +{ + Byte *bufs[BCJ2_NUM_STREAMS]; + const Byte *lims[BCJ2_NUM_STREAMS]; + const Byte *src; + const Byte *srcLim; + + unsigned state; + EBcj2Enc_FinishMode finishMode; + + Byte prevByte; + + Byte cache; + UInt32 range; + UInt64 low; + UInt64 cacheSize; + + UInt32 ip; + + /* 32-bit ralative offset in JUMP/CALL commands is + - (mod 4 GB) in 32-bit mode + - signed Int32 in 64-bit mode + We use (mod 4 GB) check for fileSize. + Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */ + UInt32 fileIp; + UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */ + UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */ + + UInt32 tempTarget; + unsigned tempPos; + Byte temp[4 * 2]; + + unsigned flushPos; + + UInt16 probs[2 + 256]; +} CBcj2Enc; + +void Bcj2Enc_Init(CBcj2Enc *p); +void Bcj2Enc_Encode(CBcj2Enc *p); + +#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos) +#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5) + + +#define BCJ2_RELAT_LIMIT_NUM_BITS 26 +#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS) + +/* limit for CBcj2Enc::fileSize variable */ +#define BCJ2_FileSize_MAX ((UInt32)1 << 31) + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Bcj2Enc.c b/other-licenses/7zstub/src/C/Bcj2Enc.c new file mode 100644 index 0000000000..b0bc7593db --- /dev/null +++ b/other-licenses/7zstub/src/C/Bcj2Enc.c @@ -0,0 +1,311 @@ +/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code) +2017-04-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +/* #define SHOW_STAT */ + +#ifdef SHOW_STAT +#include +#define PRF(x) x +#else +#define PRF(x) +#endif + +#include + +#include "Bcj2.h" +#include "CpuArch.h" + +#define CProb UInt16 + +#define kTopValue ((UInt32)1 << 24) +#define kNumModelBits 11 +#define kBitModelTotal (1 << kNumModelBits) +#define kNumMoveBits 5 + +void Bcj2Enc_Init(CBcj2Enc *p) +{ + unsigned i; + + p->state = BCJ2_ENC_STATE_OK; + p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + + p->prevByte = 0; + + p->cache = 0; + p->range = 0xFFFFFFFF; + p->low = 0; + p->cacheSize = 1; + + p->ip = 0; + + p->fileIp = 0; + p->fileSize = 0; + p->relatLimit = BCJ2_RELAT_LIMIT; + + p->tempPos = 0; + + p->flushPos = 0; + + for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) + p->probs[i] = kBitModelTotal >> 1; +} + +static Bool MY_FAST_CALL RangeEnc_ShiftLow(CBcj2Enc *p) +{ + if ((UInt32)p->low < (UInt32)0xFF000000 || (UInt32)(p->low >> 32) != 0) + { + Byte *buf = p->bufs[BCJ2_STREAM_RC]; + do + { + if (buf == p->lims[BCJ2_STREAM_RC]) + { + p->state = BCJ2_STREAM_RC; + p->bufs[BCJ2_STREAM_RC] = buf; + return True; + } + *buf++ = (Byte)(p->cache + (Byte)(p->low >> 32)); + p->cache = 0xFF; + } + while (--p->cacheSize); + p->bufs[BCJ2_STREAM_RC] = buf; + p->cache = (Byte)((UInt32)p->low >> 24); + } + p->cacheSize++; + p->low = (UInt32)p->low << 8; + return False; +} + +static void Bcj2Enc_Encode_2(CBcj2Enc *p) +{ + if (BCJ2_IS_32BIT_STREAM(p->state)) + { + Byte *cur = p->bufs[p->state]; + if (cur == p->lims[p->state]) + return; + SetBe32(cur, p->tempTarget); + p->bufs[p->state] = cur + 4; + } + + p->state = BCJ2_ENC_STATE_ORIG; + + for (;;) + { + if (p->range < kTopValue) + { + if (RangeEnc_ShiftLow(p)) + return; + p->range <<= 8; + } + + { + { + const Byte *src = p->src; + const Byte *srcLim; + Byte *dest; + SizeT num = p->srcLim - src; + + if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE) + { + if (num <= 4) + return; + num -= 4; + } + else if (num == 0) + break; + + dest = p->bufs[BCJ2_STREAM_MAIN]; + if (num > (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest)) + { + num = p->lims[BCJ2_STREAM_MAIN] - dest; + if (num == 0) + { + p->state = BCJ2_STREAM_MAIN; + return; + } + } + + srcLim = src + num; + + if (p->prevByte == 0x0F && (src[0] & 0xF0) == 0x80) + *dest = src[0]; + else for (;;) + { + Byte b = *src; + *dest = b; + if (b != 0x0F) + { + if ((b & 0xFE) == 0xE8) + break; + dest++; + if (++src != srcLim) + continue; + break; + } + dest++; + if (++src == srcLim) + break; + if ((*src & 0xF0) != 0x80) + continue; + *dest = *src; + break; + } + + num = src - p->src; + + if (src == srcLim) + { + p->prevByte = src[-1]; + p->bufs[BCJ2_STREAM_MAIN] = dest; + p->src = src; + p->ip += (UInt32)num; + continue; + } + + { + Byte context = (Byte)(num == 0 ? p->prevByte : src[-1]); + Bool needConvert; + + p->bufs[BCJ2_STREAM_MAIN] = dest + 1; + p->ip += (UInt32)num + 1; + src++; + + needConvert = False; + + if ((SizeT)(p->srcLim - src) >= 4) + { + UInt32 relatVal = GetUi32(src); + if ((p->fileSize == 0 || (UInt32)(p->ip + 4 + relatVal - p->fileIp) < p->fileSize) + && ((relatVal + p->relatLimit) >> 1) < p->relatLimit) + needConvert = True; + } + + { + UInt32 bound; + unsigned ttt; + Byte b = src[-1]; + CProb *prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)context : (b == 0xE9 ? 1 : 0)); + + ttt = *prob; + bound = (p->range >> kNumModelBits) * ttt; + + if (!needConvert) + { + p->range = bound; + *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); + p->src = src; + p->prevByte = b; + continue; + } + + p->low += bound; + p->range -= bound; + *prob = (CProb)(ttt - (ttt >> kNumMoveBits)); + + { + UInt32 relatVal = GetUi32(src); + UInt32 absVal; + p->ip += 4; + absVal = p->ip + relatVal; + p->prevByte = src[3]; + src += 4; + p->src = src; + { + unsigned cj = (b == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; + Byte *cur = p->bufs[cj]; + if (cur == p->lims[cj]) + { + p->state = cj; + p->tempTarget = absVal; + return; + } + SetBe32(cur, absVal); + p->bufs[cj] = cur + 4; + } + } + } + } + } + } + } + + if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM) + return; + + for (; p->flushPos < 5; p->flushPos++) + if (RangeEnc_ShiftLow(p)) + return; + p->state = BCJ2_ENC_STATE_OK; +} + + +void Bcj2Enc_Encode(CBcj2Enc *p) +{ + PRF(printf("\n")); + PRF(printf("---- ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src)); + + if (p->tempPos != 0) + { + unsigned extra = 0; + + for (;;) + { + const Byte *src = p->src; + const Byte *srcLim = p->srcLim; + unsigned finishMode = p->finishMode; + + p->src = p->temp; + p->srcLim = p->temp + p->tempPos; + if (src != srcLim) + p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + + PRF(printf(" ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src)); + + Bcj2Enc_Encode_2(p); + + { + unsigned num = (unsigned)(p->src - p->temp); + unsigned tempPos = p->tempPos - num; + unsigned i; + p->tempPos = tempPos; + for (i = 0; i < tempPos; i++) + p->temp[i] = p->temp[(size_t)i + num]; + + p->src = src; + p->srcLim = srcLim; + p->finishMode = finishMode; + + if (p->state != BCJ2_ENC_STATE_ORIG || src == srcLim) + return; + + if (extra >= tempPos) + { + p->src = src - tempPos; + p->tempPos = 0; + break; + } + + p->temp[tempPos] = src[0]; + p->tempPos = tempPos + 1; + p->src = src + 1; + extra++; + } + } + } + + PRF(printf("++++ ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src)); + + Bcj2Enc_Encode_2(p); + + if (p->state == BCJ2_ENC_STATE_ORIG) + { + const Byte *src = p->src; + unsigned rem = (unsigned)(p->srcLim - src); + unsigned i; + for (i = 0; i < rem; i++) + p->temp[i] = src[i]; + p->tempPos = rem; + p->src = src + rem; + } +} diff --git a/other-licenses/7zstub/src/C/Bra.c b/other-licenses/7zstub/src/C/Bra.c new file mode 100644 index 0000000000..cbdcb290df --- /dev/null +++ b/other-licenses/7zstub/src/C/Bra.c @@ -0,0 +1,230 @@ +/* Bra.c -- Converters for RISC code +2017-04-04 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" +#include "Bra.h" + +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + Byte *p; + const Byte *lim; + size &= ~(size_t)3; + ip += 4; + p = data; + lim = data + size; + + if (encoding) + + for (;;) + { + for (;;) + { + if (p >= lim) + return p - data; + p += 4; + if (p[-1] == 0xEB) + break; + } + { + UInt32 v = GetUi32(p - 4); + v <<= 2; + v += ip + (UInt32)(p - data); + v >>= 2; + v &= 0x00FFFFFF; + v |= 0xEB000000; + SetUi32(p - 4, v); + } + } + + for (;;) + { + for (;;) + { + if (p >= lim) + return p - data; + p += 4; + if (p[-1] == 0xEB) + break; + } + { + UInt32 v = GetUi32(p - 4); + v <<= 2; + v -= ip + (UInt32)(p - data); + v >>= 2; + v &= 0x00FFFFFF; + v |= 0xEB000000; + SetUi32(p - 4, v); + } + } +} + + +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + Byte *p; + const Byte *lim; + size &= ~(size_t)1; + p = data; + lim = data + size - 4; + + if (encoding) + + for (;;) + { + UInt32 b1; + for (;;) + { + UInt32 b3; + if (p > lim) + return p - data; + b1 = p[1]; + b3 = p[3]; + p += 2; + b1 ^= 8; + if ((b3 & b1) >= 0xF8) + break; + } + { + UInt32 v = + ((UInt32)b1 << 19) + + (((UInt32)p[1] & 0x7) << 8) + + (((UInt32)p[-2] << 11)) + + (p[0]); + + p += 2; + { + UInt32 cur = (ip + (UInt32)(p - data)) >> 1; + v += cur; + } + + p[-4] = (Byte)(v >> 11); + p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7)); + p[-2] = (Byte)v; + p[-1] = (Byte)(0xF8 | (v >> 8)); + } + } + + for (;;) + { + UInt32 b1; + for (;;) + { + UInt32 b3; + if (p > lim) + return p - data; + b1 = p[1]; + b3 = p[3]; + p += 2; + b1 ^= 8; + if ((b3 & b1) >= 0xF8) + break; + } + { + UInt32 v = + ((UInt32)b1 << 19) + + (((UInt32)p[1] & 0x7) << 8) + + (((UInt32)p[-2] << 11)) + + (p[0]); + + p += 2; + { + UInt32 cur = (ip + (UInt32)(p - data)) >> 1; + v -= cur; + } + + /* + SetUi16(p - 4, (UInt16)(((v >> 11) & 0x7FF) | 0xF000)); + SetUi16(p - 2, (UInt16)(v | 0xF800)); + */ + + p[-4] = (Byte)(v >> 11); + p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7)); + p[-2] = (Byte)v; + p[-1] = (Byte)(0xF8 | (v >> 8)); + } + } +} + + +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + Byte *p; + const Byte *lim; + size &= ~(size_t)3; + ip -= 4; + p = data; + lim = data + size; + + for (;;) + { + for (;;) + { + if (p >= lim) + return p - data; + p += 4; + /* if ((v & 0xFC000003) == 0x48000001) */ + if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) + break; + } + { + UInt32 v = GetBe32(p - 4); + if (encoding) + v += ip + (UInt32)(p - data); + else + v -= ip + (UInt32)(p - data); + v &= 0x03FFFFFF; + v |= 0x48000000; + SetBe32(p - 4, v); + } + } +} + + +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + Byte *p; + const Byte *lim; + size &= ~(size_t)3; + ip -= 4; + p = data; + lim = data + size; + + for (;;) + { + for (;;) + { + if (p >= lim) + return p - data; + /* + v = GetBe32(p); + p += 4; + m = v + ((UInt32)5 << 29); + m ^= (UInt32)7 << 29; + m += (UInt32)1 << 22; + if ((m & ((UInt32)0x1FF << 23)) == 0) + break; + */ + p += 4; + if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) || + (p[-4] == 0x7F && (p[-3] >= 0xC0))) + break; + } + { + UInt32 v = GetBe32(p - 4); + v <<= 2; + if (encoding) + v += ip + (UInt32)(p - data); + else + v -= ip + (UInt32)(p - data); + + v &= 0x01FFFFFF; + v -= (UInt32)1 << 24; + v ^= 0xFF000000; + v >>= 2; + v |= 0x40000000; + SetBe32(p - 4, v); + } + } +} diff --git a/other-licenses/7zstub/src/C/Bra.h b/other-licenses/7zstub/src/C/Bra.h new file mode 100644 index 0000000000..aba8dce14f --- /dev/null +++ b/other-licenses/7zstub/src/C/Bra.h @@ -0,0 +1,64 @@ +/* Bra.h -- Branch converters for executables +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +These functions convert relative addresses to absolute addresses +in CALL instructions to increase the compression ratio. + + In: + data - data buffer + size - size of data + ip - current virtual Instruction Pinter (IP) value + state - state variable for x86 converter + encoding - 0 (for decoding), 1 (for encoding) + + Out: + state - state variable for x86 converter + + Returns: + The number of processed bytes. If you call these functions with multiple calls, + you must start next call with first byte after block of processed bytes. + + Type Endian Alignment LookAhead + + x86 little 1 4 + ARMT little 2 2 + ARM little 4 0 + PPC big 4 0 + SPARC big 4 0 + IA64 little 16 0 + + size must be >= Alignment + LookAhead, if it's not last block. + If (size < Alignment + LookAhead), converter returns 0. + + Example: + + UInt32 ip = 0; + for () + { + ; size must be >= Alignment + LookAhead, if it's not last block + SizeT processed = Convert(data, size, ip, 1); + data += processed; + size -= processed; + ip += processed; + } +*/ + +#define x86_Convert_Init(state) { state = 0; } +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Bra86.c b/other-licenses/7zstub/src/C/Bra86.c new file mode 100644 index 0000000000..a6463c63ba --- /dev/null +++ b/other-licenses/7zstub/src/C/Bra86.c @@ -0,0 +1,82 @@ +/* Bra86.c -- Converter for x86 code (BCJ) +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bra.h" + +#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) + +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +{ + SizeT pos = 0; + UInt32 mask = *state & 7; + if (size < 5) + return 0; + size -= 4; + ip += 5; + + for (;;) + { + Byte *p = data + pos; + const Byte *limit = data + size; + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + + { + SizeT d = (SizeT)(p - data - pos); + pos = (SizeT)(p - data); + if (p >= limit) + { + *state = (d > 2 ? 0 : mask >> (unsigned)d); + return pos; + } + if (d > 2) + mask = 0; + else + { + mask >>= (unsigned)d; + if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1]))) + { + mask = (mask >> 1) | 4; + pos++; + continue; + } + } + } + + if (Test86MSByte(p[4])) + { + UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 cur = ip + (UInt32)pos; + pos += 5; + if (encoding) + v += cur; + else + v -= cur; + if (mask != 0) + { + unsigned sh = (mask & 6) << 2; + if (Test86MSByte((Byte)(v >> sh))) + { + v ^= (((UInt32)0x100 << sh) - 1); + if (encoding) + v += cur; + else + v -= cur; + } + mask = 0; + } + p[1] = (Byte)v; + p[2] = (Byte)(v >> 8); + p[3] = (Byte)(v >> 16); + p[4] = (Byte)(0 - ((v >> 24) & 1)); + } + else + { + mask = (mask >> 1) | 4; + pos++; + } + } +} diff --git a/other-licenses/7zstub/src/C/BraIA64.c b/other-licenses/7zstub/src/C/BraIA64.c new file mode 100644 index 0000000000..2656907a0b --- /dev/null +++ b/other-licenses/7zstub/src/C/BraIA64.c @@ -0,0 +1,53 @@ +/* BraIA64.c -- Converter for IA-64 code +2017-01-26 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" +#include "Bra.h" + +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 16) + return 0; + size -= 16; + i = 0; + do + { + unsigned m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3; + if (m) + { + m++; + do + { + Byte *p = data + (i + (size_t)m * 5 - 8); + if (((p[3] >> m) & 15) == 5 + && (((p[-1] | ((UInt32)p[0] << 8)) >> m) & 0x70) == 0) + { + unsigned raw = GetUi32(p); + unsigned v = raw >> m; + v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3); + + v <<= 4; + if (encoding) + v += ip + (UInt32)i; + else + v -= ip + (UInt32)i; + v >>= 4; + + v &= 0x1FFFFF; + v += 0x700000; + v &= 0x8FFFFF; + raw &= ~((UInt32)0x8FFFFF << m); + raw |= (v << m); + SetUi32(p, raw); + } + } + while (++m <= 4); + } + i += 16; + } + while (i <= size); + return i; +} diff --git a/other-licenses/7zstub/src/C/Compiler.h b/other-licenses/7zstub/src/C/Compiler.h new file mode 100644 index 0000000000..c788648cd2 --- /dev/null +++ b/other-licenses/7zstub/src/C/Compiler.h @@ -0,0 +1,33 @@ +/* Compiler.h +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_COMPILER_H +#define __7Z_COMPILER_H + +#ifdef _MSC_VER + + #ifdef UNDER_CE + #define RPC_NO_WINDOWS_H + /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ + #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union + #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int + #endif + + #if _MSC_VER >= 1300 + #pragma warning(disable : 4996) // This function or variable may be unsafe + #else + #pragma warning(disable : 4511) // copy constructor could not be generated + #pragma warning(disable : 4512) // assignment operator could not be generated + #pragma warning(disable : 4514) // unreferenced inline function has been removed + #pragma warning(disable : 4702) // unreachable code + #pragma warning(disable : 4710) // not inlined + #pragma warning(disable : 4714) // function marked as __forceinline not inlined + #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information + #endif + +#endif + +#define UNUSED_VAR(x) (void)x; +/* #define UNUSED_VAR(x) x=x; */ + +#endif diff --git a/other-licenses/7zstub/src/C/CpuArch.c b/other-licenses/7zstub/src/C/CpuArch.c new file mode 100644 index 0000000000..f835c2b7bf --- /dev/null +++ b/other-licenses/7zstub/src/C/CpuArch.c @@ -0,0 +1,200 @@ +/* CpuArch.c -- CPU specific code +2016-02-25: Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 + +#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) +#define USE_ASM +#endif + +#if !defined(USE_ASM) && _MSC_VER >= 1500 +#include +#endif + +#if defined(USE_ASM) && !defined(MY_CPU_AMD64) +static UInt32 CheckFlag(UInt32 flag) +{ + #ifdef _MSC_VER + __asm pushfd; + __asm pop EAX; + __asm mov EDX, EAX; + __asm xor EAX, flag; + __asm push EAX; + __asm popfd; + __asm pushfd; + __asm pop EAX; + __asm xor EAX, EDX; + __asm push EDX; + __asm popfd; + __asm and flag, EAX; + #else + __asm__ __volatile__ ( + "pushf\n\t" + "pop %%EAX\n\t" + "movl %%EAX,%%EDX\n\t" + "xorl %0,%%EAX\n\t" + "push %%EAX\n\t" + "popf\n\t" + "pushf\n\t" + "pop %%EAX\n\t" + "xorl %%EDX,%%EAX\n\t" + "push %%EDX\n\t" + "popf\n\t" + "andl %%EAX, %0\n\t": + "=c" (flag) : "c" (flag) : + "%eax", "%edx"); + #endif + return flag; +} +#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; +#else +#define CHECK_CPUID_IS_SUPPORTED +#endif + +void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) +{ + #ifdef USE_ASM + + #ifdef _MSC_VER + + UInt32 a2, b2, c2, d2; + __asm xor EBX, EBX; + __asm xor ECX, ECX; + __asm xor EDX, EDX; + __asm mov EAX, function; + __asm cpuid; + __asm mov a2, EAX; + __asm mov b2, EBX; + __asm mov c2, ECX; + __asm mov d2, EDX; + + *a = a2; + *b = b2; + *c = c2; + *d = d2; + + #else + + __asm__ __volatile__ ( + #if defined(MY_CPU_AMD64) && defined(__PIC__) + "mov %%rbx, %%rdi;" + "cpuid;" + "xchg %%rbx, %%rdi;" + : "=a" (*a) , + "=D" (*b) , + #elif defined(MY_CPU_X86) && defined(__PIC__) + "mov %%ebx, %%edi;" + "cpuid;" + "xchgl %%ebx, %%edi;" + : "=a" (*a) , + "=D" (*b) , + #else + "cpuid" + : "=a" (*a) , + "=b" (*b) , + #endif + "=c" (*c) , + "=d" (*d) + : "0" (function)) ; + + #endif + + #else + + int CPUInfo[4]; + __cpuid(CPUInfo, function); + *a = CPUInfo[0]; + *b = CPUInfo[1]; + *c = CPUInfo[2]; + *d = CPUInfo[3]; + + #endif +} + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p) +{ + CHECK_CPUID_IS_SUPPORTED + MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); + MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); + return True; +} + +static const UInt32 kVendors[][3] = +{ + { 0x756E6547, 0x49656E69, 0x6C65746E}, + { 0x68747541, 0x69746E65, 0x444D4163}, + { 0x746E6543, 0x48727561, 0x736C7561} +}; + +int x86cpuid_GetFirm(const Cx86cpuid *p) +{ + unsigned i; + for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) + { + const UInt32 *v = kVendors[i]; + if (v[0] == p->vendor[0] && + v[1] == p->vendor[1] && + v[2] == p->vendor[2]) + return (int)i; + } + return -1; +} + +Bool CPU_Is_InOrder() +{ + Cx86cpuid p; + int firm; + UInt32 family, model; + if (!x86cpuid_CheckAndRead(&p)) + return True; + + family = x86cpuid_GetFamily(p.ver); + model = x86cpuid_GetModel(p.ver); + + firm = x86cpuid_GetFirm(&p); + + switch (firm) + { + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( + /* In-Order Atom CPU */ + model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ + || model == 0x26 /* 45 nm, Z6xx */ + || model == 0x27 /* 32 nm, Z2460 */ + || model == 0x35 /* 32 nm, Z2760 */ + || model == 0x36 /* 32 nm, N2xxx, D2xxx */ + ))); + case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); + case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); + } + return True; +} + +#if !defined(MY_CPU_AMD64) && defined(_WIN32) +#include +static Bool CPU_Sys_Is_SSE_Supported() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionEx(&vi)) + return False; + return (vi.dwMajorVersion >= 5); +} +#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; +#else +#define CHECK_SYS_SSE_SUPPORT +#endif + +Bool CPU_Is_Aes_Supported() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return False; + return (p.c >> 25) & 1; +} + +#endif diff --git a/other-licenses/7zstub/src/C/CpuArch.h b/other-licenses/7zstub/src/C/CpuArch.h new file mode 100644 index 0000000000..7fb27282c7 --- /dev/null +++ b/other-licenses/7zstub/src/C/CpuArch.h @@ -0,0 +1,335 @@ +/* CpuArch.h -- CPU specific code +2017-09-04 : Igor Pavlov : Public domain */ + +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +MY_CPU_LE means that CPU is LITTLE ENDIAN. +MY_CPU_BE means that CPU is BIG ENDIAN. +If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform. + +MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. +*/ + +#if defined(_M_X64) \ + || defined(_M_AMD64) \ + || defined(__x86_64__) \ + || defined(__AMD64__) \ + || defined(__amd64__) + #define MY_CPU_AMD64 + #ifdef __ILP32__ + #define MY_CPU_NAME "x32" + #else + #define MY_CPU_NAME "x64" + #endif + #define MY_CPU_64BIT +#endif + + +#if defined(_M_IX86) \ + || defined(__i386__) + #define MY_CPU_X86 + #define MY_CPU_NAME "x86" + #define MY_CPU_32BIT +#endif + + +#if defined(_M_ARM64) \ + || defined(__AARCH64EL__) \ + || defined(__AARCH64EB__) \ + || defined(__aarch64__) + #define MY_CPU_ARM64 + #define MY_CPU_NAME "arm64" + #define MY_CPU_64BIT +#endif + + +#if defined(_M_ARM) \ + || defined(_M_ARM_NT) \ + || defined(_M_ARMT) \ + || defined(__arm__) \ + || defined(__thumb__) \ + || defined(__ARMEL__) \ + || defined(__ARMEB__) \ + || defined(__THUMBEL__) \ + || defined(__THUMBEB__) + #define MY_CPU_ARM + #define MY_CPU_NAME "arm" + #define MY_CPU_32BIT +#endif + + +#if defined(_M_IA64) \ + || defined(__ia64__) + #define MY_CPU_IA64 + #define MY_CPU_NAME "ia64" + #define MY_CPU_64BIT +#endif + + +#if defined(__mips64) \ + || defined(__mips64__) \ + || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3)) + #define MY_CPU_NAME "mips64" + #define MY_CPU_64BIT +#elif defined(__mips__) + #define MY_CPU_NAME "mips" + /* #define MY_CPU_32BIT */ +#endif + + +#if defined(__ppc64__) \ + || defined(__powerpc64__) + #ifdef __ILP32__ + #define MY_CPU_NAME "ppc64-32" + #else + #define MY_CPU_NAME "ppc64" + #endif + #define MY_CPU_64BIT +#elif defined(__ppc__) \ + || defined(__powerpc__) + #define MY_CPU_NAME "ppc" + #define MY_CPU_32BIT +#endif + + +#if defined(__sparc64__) + #define MY_CPU_NAME "sparc64" + #define MY_CPU_64BIT +#elif defined(__sparc__) + #define MY_CPU_NAME "sparc" + /* #define MY_CPU_32BIT */ +#endif + + +#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) +#define MY_CPU_X86_OR_AMD64 +#endif + + +#ifdef _WIN32 + + #ifdef MY_CPU_ARM + #define MY_CPU_ARM_LE + #endif + + #ifdef MY_CPU_ARM64 + #define MY_CPU_ARM64_LE + #endif + + #ifdef _M_IA64 + #define MY_CPU_IA64_LE + #endif + +#endif + + +#if defined(MY_CPU_X86_OR_AMD64) \ + || defined(MY_CPU_ARM_LE) \ + || defined(MY_CPU_ARM64_LE) \ + || defined(MY_CPU_IA64_LE) \ + || defined(__LITTLE_ENDIAN__) \ + || defined(__ARMEL__) \ + || defined(__THUMBEL__) \ + || defined(__AARCH64EL__) \ + || defined(__MIPSEL__) \ + || defined(__MIPSEL) \ + || defined(_MIPSEL) \ + || defined(__BFIN__) \ + || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + #define MY_CPU_LE +#endif + +#if defined(__BIG_ENDIAN__) \ + || defined(__ARMEB__) \ + || defined(__THUMBEB__) \ + || defined(__AARCH64EB__) \ + || defined(__MIPSEB__) \ + || defined(__MIPSEB) \ + || defined(_MIPSEB) \ + || defined(__m68k__) \ + || defined(__s390__) \ + || defined(__s390x__) \ + || defined(__zarch__) \ + || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + #define MY_CPU_BE +#endif + + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) + #error Stop_Compiling_Bad_Endian +#endif + + +#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT) + #error Stop_Compiling_Bad_32_64_BIT +#endif + + +#ifndef MY_CPU_NAME + #ifdef MY_CPU_LE + #define MY_CPU_NAME "LE" + #elif defined(MY_CPU_BE) + #define MY_CPU_NAME "BE" + #else + /* + #define MY_CPU_NAME "" + */ + #endif +#endif + + + + + +#ifdef MY_CPU_LE + #if defined(MY_CPU_X86_OR_AMD64) \ + || defined(MY_CPU_ARM64) \ + || defined(__ARM_FEATURE_UNALIGNED) + #define MY_CPU_LE_UNALIGN + #endif +#endif + + +#ifdef MY_CPU_LE_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(const void *)(p)) +#define GetUi32(p) (*(const UInt32 *)(const void *)(p)) +#define GetUi64(p) (*(const UInt64 *)(const void *)(p)) + +#define SetUi16(p, v) { *(UInt16 *)(p) = (v); } +#define SetUi32(p, v) { *(UInt32 *)(p) = (v); } +#define SetUi64(p, v) { *(UInt64 *)(p) = (v); } + +#else + +#define GetUi16(p) ( (UInt16) ( \ + ((const Byte *)(p))[0] | \ + ((UInt16)((const Byte *)(p))[1] << 8) )) + +#define GetUi32(p) ( \ + ((const Byte *)(p))[0] | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((UInt32)((const Byte *)(p))[2] << 16) | \ + ((UInt32)((const Byte *)(p))[3] << 24)) + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + +#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)_vvv_; \ + _ppp_[1] = (Byte)(_vvv_ >> 8); } + +#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)_vvv_; \ + _ppp_[1] = (Byte)(_vvv_ >> 8); \ + _ppp_[2] = (Byte)(_vvv_ >> 16); \ + _ppp_[3] = (Byte)(_vvv_ >> 24); } + +#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ + SetUi32(_ppp2_ , (UInt32)_vvv2_); \ + SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } + +#endif + +#ifdef __has_builtin + #define MY__has_builtin(x) __has_builtin(x) +#else + #define MY__has_builtin(x) 0 +#endif + +#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) + +/* Note: we use bswap instruction, that is unsupported in 386 cpu */ + +#include + +#pragma intrinsic(_byteswap_ushort) +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) + +/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */ +#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) + +#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) + +#elif defined(MY_CPU_LE_UNALIGN) && ( \ + (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ + || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) ) + +/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */ +#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p)) + +#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v) + +#else + +#define GetBe32(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 24) | \ + ((UInt32)((const Byte *)(p))[1] << 16) | \ + ((UInt32)((const Byte *)(p))[2] << 8) | \ + ((const Byte *)(p))[3] ) + +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) + +#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)(_vvv_ >> 24); \ + _ppp_[1] = (Byte)(_vvv_ >> 16); \ + _ppp_[2] = (Byte)(_vvv_ >> 8); \ + _ppp_[3] = (Byte)_vvv_; } + +#endif + + +#ifndef GetBe16 + +#define GetBe16(p) ( (UInt16) ( \ + ((UInt16)((const Byte *)(p))[0] << 8) | \ + ((const Byte *)(p))[1] )) + +#endif + + + +#ifdef MY_CPU_X86_OR_AMD64 + +typedef struct +{ + UInt32 maxFunc; + UInt32 vendor[3]; + UInt32 ver; + UInt32 b; + UInt32 c; + UInt32 d; +} Cx86cpuid; + +enum +{ + CPU_FIRM_INTEL, + CPU_FIRM_AMD, + CPU_FIRM_VIA +}; + +void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d); + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p); +int x86cpuid_GetFirm(const Cx86cpuid *p); + +#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF)) +#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) +#define x86cpuid_GetStepping(ver) (ver & 0xF) + +Bool CPU_Is_InOrder(); +Bool CPU_Is_Aes_Supported(); + +#endif + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Delta.c b/other-licenses/7zstub/src/C/Delta.c new file mode 100644 index 0000000000..6cbbe46012 --- /dev/null +++ b/other-licenses/7zstub/src/C/Delta.c @@ -0,0 +1,64 @@ +/* Delta.c -- Delta converter +2009-05-26 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Delta.h" + +void Delta_Init(Byte *state) +{ + unsigned i; + for (i = 0; i < DELTA_STATE_SIZE; i++) + state[i] = 0; +} + +static void MyMemCpy(Byte *dest, const Byte *src, unsigned size) +{ + unsigned i; + for (i = 0; i < size; i++) + dest[i] = src[i]; +} + +void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size) +{ + Byte buf[DELTA_STATE_SIZE]; + unsigned j = 0; + MyMemCpy(buf, state, delta); + { + SizeT i; + for (i = 0; i < size;) + { + for (j = 0; j < delta && i < size; i++, j++) + { + Byte b = data[i]; + data[i] = (Byte)(b - buf[j]); + buf[j] = b; + } + } + } + if (j == delta) + j = 0; + MyMemCpy(state, buf + j, delta - j); + MyMemCpy(state + delta - j, buf, j); +} + +void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size) +{ + Byte buf[DELTA_STATE_SIZE]; + unsigned j = 0; + MyMemCpy(buf, state, delta); + { + SizeT i; + for (i = 0; i < size;) + { + for (j = 0; j < delta && i < size; i++, j++) + { + buf[j] = data[i] = (Byte)(buf[j] + data[i]); + } + } + } + if (j == delta) + j = 0; + MyMemCpy(state, buf + j, delta - j); + MyMemCpy(state + delta - j, buf, j); +} diff --git a/other-licenses/7zstub/src/C/Delta.h b/other-licenses/7zstub/src/C/Delta.h new file mode 100644 index 0000000000..e59d5a252b --- /dev/null +++ b/other-licenses/7zstub/src/C/Delta.h @@ -0,0 +1,19 @@ +/* Delta.h -- Delta converter +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __DELTA_H +#define __DELTA_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define DELTA_STATE_SIZE 256 + +void Delta_Init(Byte *state); +void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size); +void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/DllSecur.c b/other-licenses/7zstub/src/C/DllSecur.c new file mode 100644 index 0000000000..8745421aca --- /dev/null +++ b/other-licenses/7zstub/src/C/DllSecur.c @@ -0,0 +1,87 @@ +/* DllSecur.c -- DLL loading security +2016-10-04 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifdef _WIN32 + +#include + +#include "DllSecur.h" + +#ifndef UNDER_CE + +typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags); + +#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400 +#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32 0x800 + +static const char * const g_Dlls = + #ifndef _CONSOLE + "UXTHEME\0" + #endif + "USERENV\0" + "SETUPAPI\0" + "APPHELP\0" + "PROPSYS\0" + "DWMAPI\0" + "CRYPTBASE\0" + "OLEACC\0" + "CLBCATQ\0" + ; + +#endif + +void LoadSecurityDlls() +{ + #ifndef UNDER_CE + + wchar_t buf[MAX_PATH + 100]; + + { + // at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ??? + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0) + { + Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories"); + if (setDllDirs) + if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) + return; + } + } + + { + unsigned len = GetSystemDirectoryW(buf, MAX_PATH + 2); + if (len == 0 || len > MAX_PATH) + return; + } + { + const char *dll; + unsigned pos = (unsigned)lstrlenW(buf); + + if (buf[pos - 1] != '\\') + buf[pos++] = '\\'; + + for (dll = g_Dlls; dll[0] != 0;) + { + unsigned k = 0; + for (;;) + { + char c = *dll++; + buf[pos + k] = c; + k++; + if (c == 0) + break; + } + + lstrcatW(buf, L".dll"); + LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + } + } + + #endif +} + +#endif diff --git a/other-licenses/7zstub/src/C/DllSecur.h b/other-licenses/7zstub/src/C/DllSecur.h new file mode 100644 index 0000000000..023c509602 --- /dev/null +++ b/other-licenses/7zstub/src/C/DllSecur.h @@ -0,0 +1,19 @@ +/* DllSecur.h -- DLL loading for security +2016-06-08 : Igor Pavlov : Public domain */ + +#ifndef __DLL_SECUR_H +#define __DLL_SECUR_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#ifdef _WIN32 + +void LoadSecurityDlls(); + +#endif + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/LzFind.c b/other-licenses/7zstub/src/C/LzFind.c new file mode 100644 index 0000000000..6ea82a9b53 --- /dev/null +++ b/other-licenses/7zstub/src/C/LzFind.c @@ -0,0 +1,1069 @@ +/* LzFind.c -- Match finder for LZ algorithms +2017-06-10 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "LzFind.h" +#include "LzHash.h" + +#define kEmptyHashValue 0 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ +#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)7 << 29) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) +{ + if (!p->directInput) + { + ISzAlloc_Free(alloc, p->bufferBase); + p->bufferBase = NULL; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (!p->bufferBase || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != NULL); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } + +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +{ + p->posLimit -= subValue; + p->pos -= subValue; + p->streamPos -= subValue; +} + +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + + /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */ + + if (p->directInput) + { + UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos); + if (curSize > p->directInputRem) + curSize = (UInt32)p->directInputRem; + p->directInputRem -= curSize; + p->streamPos += curSize; + if (p->directInputRem == 0) + p->streamEndWasReached = 1; + return; + } + + for (;;) + { + Byte *dest = p->buffer + (p->streamPos - p->pos); + size_t size = (p->bufferBase + p->blockSize - dest); + if (size == 0) + return; + + p->result = ISeqInStream_Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (p->streamPos - p->pos > p->keepSizeAfter) + return; + } +} + +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, + (size_t)(p->streamPos - p->pos) + p->keepSizeBefore); + p->buffer = p->bufferBase + p->keepSizeBefore; +} + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + if (p->directInput) + return 0; + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->streamEndWasReached) + return; + if (p->keepSizeAfter >= p->streamPos - p->pos) + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +{ + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + UInt32 i; + p->bufferBase = NULL; + p->directInput = 0; + p->hash = NULL; + p->expectedDataSize = (UInt64)(Int64)-1; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->hash); + p->hash = NULL; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return NULL; + return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAllocPtr alloc) +{ + UInt32 sizeReserv; + + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + + sizeReserv = historySize >> 1; + if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3; + else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2; + + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); + + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; + + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ + + if (LzInWindow_Create(p, sizeReserv, alloc)) + { + UInt32 newCyclicBufferSize = historySize + 1; + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + p->fixedHashSize = 0; + if (p->numHashBytes == 2) + hs = (1 << 16) - 1; + else + { + hs = historySize; + if (hs > p->expectedDataSize) + hs = (UInt32)p->expectedDataSize; + if (hs != 0) + hs--; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ + if (hs > (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ + } + } + p->hashMask = hs; + hs++; + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + hs += p->fixedHashSize; + } + + { + size_t newSize; + size_t numSons; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + + numSons = newCyclicBufferSize; + if (p->btMode) + numSons <<= 1; + newSize = hs + numSons; + + if (p->hash && p->numRefs == newSize) + return 1; + + MatchFinder_FreeThisClassMemory(p, alloc); + p->numRefs = newSize; + p->hash = AllocRefs(newSize, alloc); + + if (p->hash) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + + MatchFinder_Free(p, alloc); + return 0; +} + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 limit = kMaxValForNormalize - p->pos; + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + + if (limit2 < limit) + limit = limit2; + limit2 = p->streamPos - p->pos; + + if (limit2 <= p->keepSizeAfter) + { + if (limit2 > 0) + limit2 = 1; + } + else + limit2 -= p->keepSizeAfter; + + if (limit2 < limit) + limit = limit2; + + { + UInt32 lenLimit = p->streamPos - p->pos; + if (lenLimit > p->matchMaxLen) + lenLimit = p->matchMaxLen; + p->lenLimit = lenLimit; + } + p->posLimit = p->pos + limit; +} + + +void MatchFinder_Init_LowHash(CMatchFinder *p) +{ + size_t i; + CLzRef *items = p->hash; + size_t numItems = p->fixedHashSize; + for (i = 0; i < numItems; i++) + items[i] = kEmptyHashValue; +} + + +void MatchFinder_Init_HighHash(CMatchFinder *p) +{ + size_t i; + CLzRef *items = p->hash + p->fixedHashSize; + size_t numItems = (size_t)p->hashMask + 1; + for (i = 0; i < numItems; i++) + items[i] = kEmptyHashValue; +} + + +void MatchFinder_Init_3(CMatchFinder *p, int readData) +{ + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = + p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + + if (readData) + MatchFinder_ReadBlock(p); + + MatchFinder_SetLimits(p); +} + + +void MatchFinder_Init(CMatchFinder *p) +{ + MatchFinder_Init_HighHash(p); + MatchFinder_Init_LowHash(p); + MatchFinder_Init_3(p, True); +} + + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) +{ + size_t i; + for (i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } +} + +static void MatchFinder_Normalize(CMatchFinder *p) +{ + UInt32 subValue = MatchFinder_GetSubValue(p); + MatchFinder_Normalize3(subValue, p->hash, p->numRefs); + MatchFinder_ReduceOffsets(p, subValue); +} + +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (p->pos == kMaxValForNormalize) + MatchFinder_Normalize(p); + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) + MatchFinder_CheckAndMoveAndRead(p); + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); +} + +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return distances; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + return distances; + } + } + } + } +} + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return distances; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return distances; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +#define MOVE_POS_RET MOVE_POS return offset; + +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \ + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define GET_MATCHES_FOOTER(offset, maxLen) \ + offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ + distances + offset, maxLen) - distances); MOVE_POS_RET; + +#define SKIP_FOOTER \ + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; + +#define UPDATE_maxLen { \ + ptrdiff_t diff = (ptrdiff_t)0 - d2; \ + const Byte *c = cur + maxLen; \ + const Byte *lim = cur + lenLimit; \ + for (; c != lim; c++) if (*(c + diff) != *c) break; \ + maxLen = (UInt32)(c - cur); } + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 1) +} + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, d2, maxLen, offset, pos; + UInt32 *hash; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash[h2]; + + curMatch = (hash + kFix3HashSize)[hv]; + + hash[h2] = pos; + (hash + kFix3HashSize)[hv] = pos; + + maxLen = 2; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + UPDATE_maxLen + distances[0] = maxLen; + distances[1] = d2 - 1; + offset = 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, h3, d2, d3, maxLen, offset, pos; + UInt32 *hash; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash[ h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + + curMatch = (hash + kFix4HashSize)[hv]; + + hash[ h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[hv] = pos; + + maxLen = 0; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = d2 - 1; + offset = 2; + } + + if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + maxLen = 3; + distances[(size_t)offset + 1] = d3 - 1; + offset += 2; + d2 = d3; + } + + if (offset != 0) + { + UPDATE_maxLen + distances[(size_t)offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + + if (maxLen < 3) + maxLen = 3; + + GET_MATCHES_FOOTER(offset, maxLen) +} + +/* +static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos; + UInt32 *hash; + GET_MATCHES_HEADER(5) + + HASH5_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash[ h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + d4 = pos - (hash + kFix4HashSize)[h4]; + + curMatch = (hash + kFix5HashSize)[hv]; + + hash[ h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[h4] = pos; + (hash + kFix5HashSize)[hv] = pos; + + maxLen = 0; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = d2 - 1; + offset = 2; + if (*(cur - d2 + 2) == cur[2]) + distances[0] = maxLen = 3; + else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + distances[2] = maxLen = 3; + distances[3] = d3 - 1; + offset = 4; + d2 = d3; + } + } + else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + distances[0] = maxLen = 3; + distances[1] = d3 - 1; + offset = 2; + d2 = d3; + } + + if (d2 != d4 && d4 < p->cyclicBufferSize + && *(cur - d4) == *cur + && *(cur - d4 + 3) == *(cur + 3)) + { + maxLen = 4; + distances[(size_t)offset + 1] = d4 - 1; + offset += 2; + d2 = d4; + } + + if (offset != 0) + { + UPDATE_maxLen + distances[(size_t)offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + + if (maxLen < 4) + maxLen = 4; + + GET_MATCHES_FOOTER(offset, maxLen) +} +*/ + +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, h3, d2, d3, maxLen, offset, pos; + UInt32 *hash; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash[ h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + + curMatch = (hash + kFix4HashSize)[hv]; + + hash[ h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[hv] = pos; + + maxLen = 0; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = d2 - 1; + offset = 2; + } + + if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + maxLen = 3; + distances[(size_t)offset + 1] = d3 - 1; + offset += 2; + d2 = d3; + } + + if (offset != 0) + { + UPDATE_maxLen + distances[(size_t)offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + + if (maxLen < 3) + maxLen = 3; + + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} + +/* +static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos + UInt32 *hash; + GET_MATCHES_HEADER(5) + + HASH5_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash[ h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + d4 = pos - (hash + kFix4HashSize)[h4]; + + curMatch = (hash + kFix5HashSize)[hv]; + + hash[ h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[h4] = pos; + (hash + kFix5HashSize)[hv] = pos; + + maxLen = 0; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = d2 - 1; + offset = 2; + if (*(cur - d2 + 2) == cur[2]) + distances[0] = maxLen = 3; + else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + distances[2] = maxLen = 3; + distances[3] = d3 - 1; + offset = 4; + d2 = d3; + } + } + else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + distances[0] = maxLen = 3; + distances[1] = d3 - 1; + offset = 2; + d2 = d3; + } + + if (d2 != d4 && d4 < p->cyclicBufferSize + && *(cur - d4) == *cur + && *(cur - d4 + 3) == *(cur + 3)) + { + maxLen = 4; + distances[(size_t)offset + 1] = d4 - 1; + offset += 2; + d2 = d4; + } + + if (offset != 0) + { + UPDATE_maxLen + distances[(size_t)offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + + if (maxLen < 4) + maxLen = 4; + + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} +*/ + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances, 2) - (distances)); + MOVE_POS_RET +} + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2; + UInt32 *hash; + SKIP_HEADER(3) + HASH3_CALC; + hash = p->hash; + curMatch = (hash + kFix3HashSize)[hv]; + hash[h2] = + (hash + kFix3HashSize)[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2, h3; + UInt32 *hash; + SKIP_HEADER(4) + HASH4_CALC; + hash = p->hash; + curMatch = (hash + kFix4HashSize)[hv]; + hash[ h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +/* +static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2, h3, h4; + UInt32 *hash; + SKIP_HEADER(5) + HASH5_CALC; + hash = p->hash; + curMatch = (hash + kFix5HashSize)[hv]; + hash[ h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[h4] = + (hash + kFix5HashSize)[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} +*/ + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2, h3; + UInt32 *hash; + SKIP_HEADER(4) + HASH4_CALC; + hash = p->hash; + curMatch = (hash + kFix4HashSize)[hv]; + hash[ h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[hv] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +/* +static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2, h3, h4; + UInt32 *hash; + SKIP_HEADER(5) + HASH5_CALC; + hash = p->hash; + curMatch = hash + kFix5HashSize)[hv]; + hash[ h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[h4] = + (hash + kFix5HashSize)[hv] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} +*/ + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + /* if (p->numHashBytes <= 4) */ + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + /* + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip; + } + */ + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else /* if (p->numHashBytes == 4) */ + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } + /* + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip; + } + */ +} diff --git a/other-licenses/7zstub/src/C/LzFind.h b/other-licenses/7zstub/src/C/LzFind.h new file mode 100644 index 0000000000..c77added7b --- /dev/null +++ b/other-licenses/7zstub/src/C/LzFind.h @@ -0,0 +1,121 @@ +/* LzFind.h -- Match finder for LZ algorithms +2017-06-10 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_H +#define __LZ_FIND_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef UInt32 CLzRef; + +typedef struct _CMatchFinder +{ + Byte *buffer; + UInt32 pos; + UInt32 posLimit; + UInt32 streamPos; + UInt32 lenLimit; + + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + + Byte streamEndWasReached; + Byte btMode; + Byte bigHash; + Byte directInput; + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + size_t directInputRem; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + SRes result; + UInt32 crc[256]; + size_t numRefs; + + UInt64 expectedDataSize; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +#define Inline_MatchFinder_IsFinishedOK(p) \ + ((p)->streamEndWasReached \ + && (p)->streamPos == (p)->pos \ + && (!(p)->directInput || (p)->directInputRem == 0)) + +int MatchFinder_NeedMove(CMatchFinder *p); +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +void MatchFinder_MoveBlock(CMatchFinder *p); +void MatchFinder_ReadIfRequired(CMatchFinder *p); + +void MatchFinder_Construct(CMatchFinder *p); + +/* Conditions: + historySize <= 3 GB + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +*/ +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAllocPtr alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems); +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 maxLen); + +/* +Conditions: + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +*/ + +typedef void (*Mf_Init_Func)(void *object); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +void MatchFinder_Init_LowHash(CMatchFinder *p); +void MatchFinder_Init_HighHash(CMatchFinder *p); +void MatchFinder_Init_3(CMatchFinder *p, int readData); +void MatchFinder_Init(CMatchFinder *p); + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/LzFindMt.c b/other-licenses/7zstub/src/C/LzFindMt.c new file mode 100644 index 0000000000..2563824fcd --- /dev/null +++ b/other-licenses/7zstub/src/C/LzFindMt.c @@ -0,0 +1,820 @@ +/* LzFindMt.c -- multithreaded Match finder for LZ algorithms +2017-06-10 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "LzHash.h" + +#include "LzFindMt.h" + +static void MtSync_Construct(CMtSync *p) +{ + p->wasCreated = False; + p->csWasInitialized = False; + p->csWasEntered = False; + Thread_Construct(&p->thread); + Event_Construct(&p->canStart); + Event_Construct(&p->wasStarted); + Event_Construct(&p->wasStopped); + Semaphore_Construct(&p->freeSemaphore); + Semaphore_Construct(&p->filledSemaphore); +} + +static void MtSync_GetNextBlock(CMtSync *p) +{ + if (p->needStart) + { + p->numProcessedBlocks = 1; + p->needStart = False; + p->stopWriting = False; + p->exit = False; + Event_Reset(&p->wasStarted); + Event_Reset(&p->wasStopped); + + Event_Set(&p->canStart); + Event_Wait(&p->wasStarted); + + // if (mt) MatchFinder_Init_LowHash(mt->MatchFinder); + } + else + { + CriticalSection_Leave(&p->cs); + p->csWasEntered = False; + p->numProcessedBlocks++; + Semaphore_Release1(&p->freeSemaphore); + } + Semaphore_Wait(&p->filledSemaphore); + CriticalSection_Enter(&p->cs); + p->csWasEntered = True; +} + +/* MtSync_StopWriting must be called if Writing was started */ + +static void MtSync_StopWriting(CMtSync *p) +{ + UInt32 myNumBlocks = p->numProcessedBlocks; + if (!Thread_WasCreated(&p->thread) || p->needStart) + return; + p->stopWriting = True; + if (p->csWasEntered) + { + CriticalSection_Leave(&p->cs); + p->csWasEntered = False; + } + Semaphore_Release1(&p->freeSemaphore); + + Event_Wait(&p->wasStopped); + + while (myNumBlocks++ != p->numProcessedBlocks) + { + Semaphore_Wait(&p->filledSemaphore); + Semaphore_Release1(&p->freeSemaphore); + } + p->needStart = True; +} + +static void MtSync_Destruct(CMtSync *p) +{ + if (Thread_WasCreated(&p->thread)) + { + MtSync_StopWriting(p); + p->exit = True; + if (p->needStart) + Event_Set(&p->canStart); + Thread_Wait(&p->thread); + Thread_Close(&p->thread); + } + if (p->csWasInitialized) + { + CriticalSection_Delete(&p->cs); + p->csWasInitialized = False; + } + + Event_Close(&p->canStart); + Event_Close(&p->wasStarted); + Event_Close(&p->wasStopped); + Semaphore_Close(&p->freeSemaphore); + Semaphore_Close(&p->filledSemaphore); + + p->wasCreated = False; +} + +#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } + +static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) +{ + if (p->wasCreated) + return SZ_OK; + + RINOK_THREAD(CriticalSection_Init(&p->cs)); + p->csWasInitialized = True; + + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); + + RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); + RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); + + p->needStart = True; + + RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); + p->wasCreated = True; + return SZ_OK; +} + +static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) +{ + SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); + if (res != SZ_OK) + MtSync_Destruct(p); + return res; +} + +void MtSync_Init(CMtSync *p) { p->needStart = True; } + +#define kMtMaxValForNormalize 0xFFFFFFFF + +#define DEF_GetHeads2(name, v, action) \ + static void GetHeads ## name(const Byte *p, UInt32 pos, \ + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ + { action; for (; numHeads != 0; numHeads--) { \ + const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } + +#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) + +DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) +DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) +DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) +DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) +/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */ + +static void HashThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->hashSync; + for (;;) + { + UInt32 numProcessedBlocks = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + + MatchFinder_Init_HighHash(mt->MatchFinder); + + for (;;) + { + if (p->exit) + return; + if (p->stopWriting) + { + p->numProcessedBlocks = numProcessedBlocks; + Event_Set(&p->wasStopped); + break; + } + + { + CMatchFinder *mf = mt->MatchFinder; + if (MatchFinder_NeedMove(mf)) + { + CriticalSection_Enter(&mt->btSync.cs); + CriticalSection_Enter(&mt->hashSync.cs); + { + const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf); + ptrdiff_t offset; + MatchFinder_MoveBlock(mf); + offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf); + mt->pointerToCurPos -= offset; + mt->buffer -= offset; + } + CriticalSection_Leave(&mt->btSync.cs); + CriticalSection_Leave(&mt->hashSync.cs); + continue; + } + + Semaphore_Wait(&p->freeSemaphore); + + MatchFinder_ReadIfRequired(mf); + if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) + { + UInt32 subValue = (mf->pos - mf->historySize - 1); + MatchFinder_ReduceOffsets(mf, subValue); + MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); + } + { + UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; + UInt32 num = mf->streamPos - mf->pos; + heads[0] = 2; + heads[1] = num; + if (num >= mf->numHashBytes) + { + num = num - mf->numHashBytes + 1; + if (num > kMtHashBlockSize - 2) + num = kMtHashBlockSize - 2; + mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); + heads[0] = 2 + num; + } + mf->pos += num; + mf->buffer += num; + } + } + + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) +{ + MtSync_GetNextBlock(&p->hashSync); + p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; + p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; + p->hashNumAvail = p->hashBuf[p->hashBufPos++]; +} + +#define kEmptyHashValue 0 + +/* #define MFMT_GM_INLINE */ + +#ifdef MFMT_GM_INLINE + +#define NO_INLINE MY_FAST_CALL + +static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) +{ + do + { + UInt32 *distances = _distances + 1; + UInt32 curMatch = pos - *hash++; + + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + UInt32 cutValue = _cutValue; + UInt32 maxLen = _maxLen; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + break; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + break; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } + pos++; + _cyclicBufferPos++; + cur++; + { + UInt32 num = (UInt32)(distances - _distances); + *_distances = num - 1; + _distances += num; + limit -= num; + } + } + while (limit > 0 && --size != 0); + *posRes = pos; + return limit; +} + +#endif + +static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + UInt32 numProcessed = 0; + UInt32 curPos = 2; + UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); + + distances[1] = p->hashNumAvail; + + while (curPos < limit) + { + if (p->hashBufPos == p->hashBufPosLimit) + { + MatchFinderMt_GetNextBlock_Hash(p); + distances[1] = numProcessed + p->hashNumAvail; + if (p->hashNumAvail >= p->numHashBytes) + continue; + distances[0] = curPos + p->hashNumAvail; + distances += curPos; + for (; p->hashNumAvail != 0; p->hashNumAvail--) + *distances++ = 0; + return; + } + { + UInt32 size = p->hashBufPosLimit - p->hashBufPos; + UInt32 lenLimit = p->matchMaxLen; + UInt32 pos = p->pos; + UInt32 cyclicBufferPos = p->cyclicBufferPos; + if (lenLimit >= p->hashNumAvail) + lenLimit = p->hashNumAvail; + { + UInt32 size2 = p->hashNumAvail - lenLimit + 1; + if (size2 < size) + size = size2; + size2 = p->cyclicBufferSize - cyclicBufferPos; + if (size2 < size) + size = size2; + } + + #ifndef MFMT_GM_INLINE + while (curPos < limit && size-- != 0) + { + UInt32 *startDistances = distances + curPos; + UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], + pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + startDistances + 1, p->numHashBytes - 1) - startDistances); + *startDistances = num - 1; + curPos += num; + cyclicBufferPos++; + pos++; + p->buffer++; + } + #else + { + UInt32 posRes; + curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos), size, &posRes); + p->hashBufPos += posRes - pos; + cyclicBufferPos += posRes - pos; + p->buffer += posRes - pos; + pos = posRes; + } + #endif + + numProcessed += pos - p->pos; + p->hashNumAvail -= pos - p->pos; + p->pos = pos; + if (cyclicBufferPos == p->cyclicBufferSize) + cyclicBufferPos = 0; + p->cyclicBufferPos = cyclicBufferPos; + } + } + + distances[0] = curPos; +} + +static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) +{ + CMtSync *sync = &p->hashSync; + if (!sync->needStart) + { + CriticalSection_Enter(&sync->cs); + sync->csWasEntered = True; + } + + BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); + + if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) + { + UInt32 subValue = p->pos - p->cyclicBufferSize; + MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2); + p->pos -= subValue; + } + + if (!sync->needStart) + { + CriticalSection_Leave(&sync->cs); + sync->csWasEntered = False; + } +} + +void BtThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->btSync; + for (;;) + { + UInt32 blockIndex = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + for (;;) + { + if (p->exit) + return; + if (p->stopWriting) + { + p->numProcessedBlocks = blockIndex; + MtSync_StopWriting(&mt->hashSync); + Event_Set(&p->wasStopped); + break; + } + Semaphore_Wait(&p->freeSemaphore); + BtFillBlock(mt, blockIndex++); + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +void MatchFinderMt_Construct(CMatchFinderMt *p) +{ + p->hashBuf = NULL; + MtSync_Construct(&p->hashSync); + MtSync_Construct(&p->btSync); +} + +static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->hashBuf); + p->hashBuf = NULL; +} + +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc) +{ + MtSync_Destruct(&p->hashSync); + MtSync_Destruct(&p->btSync); + MatchFinderMt_FreeMem(p, alloc); +} + +#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) +#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) +{ + Byte allocaDummy[0x180]; + unsigned i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)0; + if (allocaDummy[0] == 0) + BtThreadFunc((CMatchFinderMt *)p); + return 0; +} + +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) +{ + CMatchFinder *mf = p->MatchFinder; + p->historySize = historySize; + if (kMtBtBlockSize <= matchMaxLen * 4) + return SZ_ERROR_PARAM; + if (!p->hashBuf) + { + p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); + if (!p->hashBuf) + return SZ_ERROR_MEM; + p->btBuf = p->hashBuf + kHashBufferSize; + } + keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); + keepAddBufferAfter += kMtHashBlockSize; + if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) + return SZ_ERROR_MEM; + + RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); + RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); + return SZ_OK; +} + +/* Call it after ReleaseStream / SetStream */ +static void MatchFinderMt_Init(CMatchFinderMt *p) +{ + CMatchFinder *mf = p->MatchFinder; + + p->btBufPos = + p->btBufPosLimit = 0; + p->hashBufPos = + p->hashBufPosLimit = 0; + + /* Init without data reading. We don't want to read data in this thread */ + MatchFinder_Init_3(mf, False); + MatchFinder_Init_LowHash(mf); + + p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf); + p->btNumAvailBytes = 0; + p->lzPos = p->historySize + 1; + + p->hash = mf->hash; + p->fixedHashSize = mf->fixedHashSize; + p->crc = mf->crc; + + p->son = mf->son; + p->matchMaxLen = mf->matchMaxLen; + p->numHashBytes = mf->numHashBytes; + p->pos = mf->pos; + p->buffer = mf->buffer; + p->cyclicBufferPos = mf->cyclicBufferPos; + p->cyclicBufferSize = mf->cyclicBufferSize; + p->cutValue = mf->cutValue; +} + +/* ReleaseStream is required to finish multithreading */ +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) +{ + MtSync_StopWriting(&p->btSync); + /* p->MatchFinder->ReleaseStream(); */ +} + +static void MatchFinderMt_Normalize(CMatchFinderMt *p) +{ + MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); + p->lzPos = p->historySize + 1; +} + +static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) +{ + UInt32 blockIndex; + MtSync_GetNextBlock(&p->btSync); + blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); + p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; + p->btBufPosLimit += p->btBuf[p->btBufPos++]; + p->btNumAvailBytes = p->btBuf[p->btBufPos++]; + if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) + MatchFinderMt_Normalize(p); +} + +static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) +{ + return p->pointerToCurPos; +} + +#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); + +static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) +{ + GET_NEXT_BLOCK_IF_REQUIRED; + return p->btNumAvailBytes; +} + +static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 h2, curMatch2; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH2_CALC + + curMatch2 = hash[h2]; + hash[h2] = lzPos; + + if (curMatch2 >= matchMinPos) + if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + *distances++ = 2; + *distances++ = lzPos - curMatch2 - 1; + } + + return distances; +} + +static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 h2, h3, curMatch2, curMatch3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH3_CALC + + curMatch2 = hash[ h2]; + curMatch3 = (hash + kFix3HashSize)[h3]; + + hash[ h2] = lzPos; + (hash + kFix3HashSize)[h3] = lzPos; + + if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch2 - 1; + if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + { + distances[0] = 3; + return distances + 2; + } + distances[0] = 2; + distances += 2; + } + + if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + { + *distances++ = 3; + *distances++ = lzPos - curMatch3 - 1; + } + + return distances; +} + +/* +static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH4_CALC + + curMatch2 = hash[ h2]; + curMatch3 = (hash + kFix3HashSize)[h3]; + curMatch4 = (hash + kFix4HashSize)[h4]; + + hash[ h2] = lzPos; + (hash + kFix3HashSize)[h3] = lzPos; + (hash + kFix4HashSize)[h4] = lzPos; + + if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch2 - 1; + if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + { + distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; + return distances + 2; + } + distances[0] = 2; + distances += 2; + } + + if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch3 - 1; + if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) + { + distances[0] = 4; + return distances + 2; + } + distances[0] = 3; + distances += 2; + } + + if (curMatch4 >= matchMinPos) + if ( + cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && + cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] + ) + { + *distances++ = 4; + *distances++ = lzPos - curMatch4 - 1; + } + + return distances; +} +*/ + +#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; + +static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + p->btNumAvailBytes--; + { + UInt32 i; + for (i = 0; i < len; i += 2) + { + UInt32 v0 = btBuf[0]; + UInt32 v1 = btBuf[1]; + btBuf += 2; + distances[0] = v0; + distances[1] = v1; + distances += 2; + } + } + INCREASE_LZ_POS + return len; +} + +static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + + if (len == 0) + { + /* change for bt5 ! */ + if (p->btNumAvailBytes-- >= 4) + len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); + } + else + { + /* Condition: there are matches in btBuf with length < p->numHashBytes */ + UInt32 *distances2; + p->btNumAvailBytes--; + distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); + do + { + UInt32 v0 = btBuf[0]; + UInt32 v1 = btBuf[1]; + btBuf += 2; + distances2[0] = v0; + distances2[1] = v1; + distances2 += 2; + } + while ((len -= 2) != 0); + len = (UInt32)(distances2 - (distances)); + } + INCREASE_LZ_POS + return len; +} + +#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED +#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; +#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); + +static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER2_MT { p->btNumAvailBytes--; + SKIP_FOOTER_MT +} + +static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(2) + UInt32 h2; + MT_HASH2_CALC + hash[h2] = p->lzPos; + SKIP_FOOTER_MT +} + +static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(3) + UInt32 h2, h3; + MT_HASH3_CALC + (hash + kFix3HashSize)[h3] = + hash[ h2] = + p->lzPos; + SKIP_FOOTER_MT +} + +/* +static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(4) + UInt32 h2, h3, h4; + MT_HASH4_CALC + (hash + kFix4HashSize)[h4] = + (hash + kFix3HashSize)[h3] = + hash[ h2] = + p->lzPos; + SKIP_FOOTER_MT +} +*/ + +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; + + switch (p->MatchFinder->numHashBytes) + { + case 2: + p->GetHeadsFunc = GetHeads2; + p->MixMatchesFunc = (Mf_Mix_Matches)NULL; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; + break; + case 3: + p->GetHeadsFunc = GetHeads3; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; + break; + default: + /* case 4: */ + p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; + break; + /* + default: + p->GetHeadsFunc = GetHeads5; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; + break; + */ + } +} diff --git a/other-licenses/7zstub/src/C/LzFindMt.h b/other-licenses/7zstub/src/C/LzFindMt.h new file mode 100644 index 0000000000..3d86c788f3 --- /dev/null +++ b/other-licenses/7zstub/src/C/LzFindMt.h @@ -0,0 +1,101 @@ +/* LzFindMt.h -- multithreaded Match finder for LZ algorithms +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_MT_H +#define __LZ_FIND_MT_H + +#include "LzFind.h" +#include "Threads.h" + +EXTERN_C_BEGIN + +#define kMtHashBlockSize (1 << 13) +#define kMtHashNumBlocks (1 << 3) +#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) + +#define kMtBtBlockSize (1 << 14) +#define kMtBtNumBlocks (1 << 6) +#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) + +typedef struct _CMtSync +{ + Bool wasCreated; + Bool needStart; + Bool exit; + Bool stopWriting; + + CThread thread; + CAutoResetEvent canStart; + CAutoResetEvent wasStarted; + CAutoResetEvent wasStopped; + CSemaphore freeSemaphore; + CSemaphore filledSemaphore; + Bool csWasInitialized; + Bool csWasEntered; + CCriticalSection cs; + UInt32 numProcessedBlocks; +} CMtSync; + +typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); + +/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ +#define kMtCacheLineDummy 128 + +typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); + +typedef struct _CMatchFinderMt +{ + /* LZ */ + const Byte *pointerToCurPos; + UInt32 *btBuf; + UInt32 btBufPos; + UInt32 btBufPosLimit; + UInt32 lzPos; + UInt32 btNumAvailBytes; + + UInt32 *hash; + UInt32 fixedHashSize; + UInt32 historySize; + const UInt32 *crc; + + Mf_Mix_Matches MixMatchesFunc; + + /* LZ + BT */ + CMtSync btSync; + Byte btDummy[kMtCacheLineDummy]; + + /* BT */ + UInt32 *hashBuf; + UInt32 hashBufPos; + UInt32 hashBufPosLimit; + UInt32 hashNumAvail; + + CLzRef *son; + UInt32 matchMaxLen; + UInt32 numHashBytes; + UInt32 pos; + const Byte *buffer; + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be historySize + 1 */ + UInt32 cutValue; + + /* BT + Hash */ + CMtSync hashSync; + /* Byte hashDummy[kMtCacheLineDummy]; */ + + /* Hash */ + Mf_GetHeads GetHeadsFunc; + CMatchFinder *MatchFinder; +} CMatchFinderMt; + +void MatchFinderMt_Construct(CMatchFinderMt *p); +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc); +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/LzHash.h b/other-licenses/7zstub/src/C/LzHash.h new file mode 100644 index 0000000000..2191444072 --- /dev/null +++ b/other-licenses/7zstub/src/C/LzHash.h @@ -0,0 +1,57 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2015-04-12 : Igor Pavlov : Public domain */ + +#ifndef __LZ_HASH_H +#define __LZ_HASH_H + +#define kHash2Size (1 << 10) +#define kHash3Size (1 << 16) +#define kHash4Size (1 << 20) + +#define kFix3HashSize (kHash2Size) +#define kFix4HashSize (kHash2Size + kHash3Size) +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) + +#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8); + +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + temp ^= (p->crc[cur[3]] << 5); \ + h4 = temp & (kHash4Size - 1); \ + hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; } + +/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +#define MT_HASH2_CALC \ + h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } + +#endif diff --git a/other-licenses/7zstub/src/C/Lzma2Dec.c b/other-licenses/7zstub/src/C/Lzma2Dec.c new file mode 100644 index 0000000000..57e7f346e1 --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma2Dec.c @@ -0,0 +1,488 @@ +/* Lzma2Dec.c -- LZMA2 Decoder +2018-02-19 : Igor Pavlov : Public domain */ + +/* #define SHOW_DEBUG_INFO */ + +#include "Precomp.h" + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include + +#include "Lzma2Dec.h" + +/* +00000000 - End of data +00000001 U U - Uncompressed, reset dic, need reset state and set new prop +00000010 U U - Uncompressed, no reset +100uuuuu U U P P - LZMA, no reset +101uuuuu U U P P - LZMA, reset state +110uuuuu U U P P S - LZMA, reset state + set new prop +111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic + + u, U - Unpack Size + P - Pack Size + S - Props +*/ + +#define LZMA2_CONTROL_COPY_RESET_DIC 1 + +#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0) + +#define LZMA2_LCLP_MAX 4 +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +typedef enum +{ + LZMA2_STATE_CONTROL, + LZMA2_STATE_UNPACK0, + LZMA2_STATE_UNPACK1, + LZMA2_STATE_PACK0, + LZMA2_STATE_PACK1, + LZMA2_STATE_PROP, + LZMA2_STATE_DATA, + LZMA2_STATE_DATA_CONT, + LZMA2_STATE_FINISHED, + LZMA2_STATE_ERROR +} ELzma2State; + +static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) +{ + UInt32 dicSize; + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); + props[0] = (Byte)LZMA2_LCLP_MAX; + props[1] = (Byte)(dicSize); + props[2] = (Byte)(dicSize >> 8); + props[3] = (Byte)(dicSize >> 16); + props[4] = (Byte)(dicSize >> 24); + return SZ_OK; +} + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +void Lzma2Dec_Init(CLzma2Dec *p) +{ + p->state = LZMA2_STATE_CONTROL; + p->needInitLevel = 0xE0; + p->isExtraMode = False; + p->unpackSize = 0; + + // p->decoder.dicPos = 0; // we can use it instead of full init + LzmaDec_Init(&p->decoder); +} + +static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) +{ + switch (p->state) + { + case LZMA2_STATE_CONTROL: + p->isExtraMode = False; + p->control = b; + PRF(printf("\n %8X", (unsigned)p->decoder.dicPos)); + PRF(printf(" %02X", (unsigned)b)); + if (b == 0) + return LZMA2_STATE_FINISHED; + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (b == LZMA2_CONTROL_COPY_RESET_DIC) + p->needInitLevel = 0xC0; + else if (b > 2 || p->needInitLevel == 0xE0) + return LZMA2_STATE_ERROR; + } + else + { + if (b < p->needInitLevel) + return LZMA2_STATE_ERROR; + p->needInitLevel = 0; + p->unpackSize = (UInt32)(b & 0x1F) << 16; + } + return LZMA2_STATE_UNPACK0; + + case LZMA2_STATE_UNPACK0: + p->unpackSize |= (UInt32)b << 8; + return LZMA2_STATE_UNPACK1; + + case LZMA2_STATE_UNPACK1: + p->unpackSize |= (UInt32)b; + p->unpackSize++; + PRF(printf(" %7u", (unsigned)p->unpackSize)); + return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; + + case LZMA2_STATE_PACK0: + p->packSize = (UInt32)b << 8; + return LZMA2_STATE_PACK1; + + case LZMA2_STATE_PACK1: + p->packSize |= (UInt32)b; + p->packSize++; + // if (p->packSize < 5) return LZMA2_STATE_ERROR; + PRF(printf(" %5u", (unsigned)p->packSize)); + return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA; + + case LZMA2_STATE_PROP: + { + unsigned lc, lp; + if (b >= (9 * 5 * 5)) + return LZMA2_STATE_ERROR; + lc = b % 9; + b /= 9; + p->decoder.prop.pb = (Byte)(b / 5); + lp = b % 5; + if (lc + lp > LZMA2_LCLP_MAX) + return LZMA2_STATE_ERROR; + p->decoder.prop.lc = (Byte)lc; + p->decoder.prop.lp = (Byte)lp; + return LZMA2_STATE_DATA; + } + } + return LZMA2_STATE_ERROR; +} + +static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) +{ + memcpy(p->dic + p->dicPos, src, size); + p->dicPos += size; + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) + p->checkDicSize = p->prop.dicSize; + p->processedPos += (UInt32)size; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState); + + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->state != LZMA2_STATE_ERROR) + { + SizeT dicPos; + + if (p->state == LZMA2_STATE_FINISHED) + { + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + } + + dicPos = p->decoder.dicPos; + + if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + + if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->state = Lzma2Dec_UpdateState(p, *src++); + if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED) + break; + continue; + } + + { + SizeT inCur = inSize - *srcLen; + SizeT outCur = dicLimit - dicPos; + ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; + + if (outCur >= p->unpackSize) + { + outCur = (SizeT)p->unpackSize; + curFinishMode = LZMA_FINISH_END; + } + + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (inCur == 0) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + if (p->state == LZMA2_STATE_DATA) + { + Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); + LzmaDec_InitDicAndState(&p->decoder, initDic, False); + } + + if (inCur > outCur) + inCur = outCur; + if (inCur == 0) + break; + + LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur); + + src += inCur; + *srcLen += inCur; + p->unpackSize -= (UInt32)inCur; + p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; + } + else + { + SRes res; + + if (p->state == LZMA2_STATE_DATA) + { + Bool initDic = (p->control >= 0xE0); + Bool initState = (p->control >= 0xA0); + LzmaDec_InitDicAndState(&p->decoder, initDic, initState); + p->state = LZMA2_STATE_DATA_CONT; + } + + if (inCur > p->packSize) + inCur = (SizeT)p->packSize; + + res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status); + + src += inCur; + *srcLen += inCur; + p->packSize -= (UInt32)inCur; + outCur = p->decoder.dicPos - dicPos; + p->unpackSize -= (UInt32)outCur; + + if (res != 0) + break; + + if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (p->packSize == 0) + break; + return SZ_OK; + } + + if (inCur == 0 && outCur == 0) + { + if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + || p->unpackSize != 0 + || p->packSize != 0) + break; + p->state = LZMA2_STATE_CONTROL; + } + + *status = LZMA_STATUS_NOT_SPECIFIED; + } + } + } + + *status = LZMA_STATUS_NOT_SPECIFIED; + p->state = LZMA2_STATE_ERROR; + return SZ_ERROR_DATA; +} + + + + +ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, + SizeT outSize, + const Byte *src, SizeT *srcLen, + int checkFinishBlock) +{ + SizeT inSize = *srcLen; + *srcLen = 0; + + while (p->state != LZMA2_STATE_ERROR) + { + if (p->state == LZMA2_STATE_FINISHED) + return LZMA_STATUS_FINISHED_WITH_MARK; + + if (outSize == 0 && !checkFinishBlock) + return LZMA_STATUS_NOT_FINISHED; + + if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) + { + if (*srcLen == inSize) + return LZMA_STATUS_NEEDS_MORE_INPUT; + (*srcLen)++; + + p->state = Lzma2Dec_UpdateState(p, *src++); + + if (p->state == LZMA2_STATE_UNPACK0) + { + // if (p->decoder.dicPos != 0) + if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0) + return LZMA2_PARSE_STATUS_NEW_BLOCK; + // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED; + } + + // The following code can be commented. + // It's not big problem, if we read additional input bytes. + // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state. + + if (outSize == 0 && p->state != LZMA2_STATE_FINISHED) + { + // checkFinishBlock is true. So we expect that block must be finished, + // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here + // break; + return LZMA_STATUS_NOT_FINISHED; + } + + if (p->state == LZMA2_STATE_DATA) + return LZMA2_PARSE_STATUS_NEW_CHUNK; + + continue; + } + + if (outSize == 0) + return LZMA_STATUS_NOT_FINISHED; + + { + SizeT inCur = inSize - *srcLen; + + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (inCur == 0) + return LZMA_STATUS_NEEDS_MORE_INPUT; + if (inCur > p->unpackSize) + inCur = p->unpackSize; + if (inCur > outSize) + inCur = outSize; + p->decoder.dicPos += inCur; + src += inCur; + *srcLen += inCur; + outSize -= inCur; + p->unpackSize -= (UInt32)inCur; + p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; + } + else + { + p->isExtraMode = True; + + if (inCur == 0) + { + if (p->packSize != 0) + return LZMA_STATUS_NEEDS_MORE_INPUT; + } + else if (p->state == LZMA2_STATE_DATA) + { + p->state = LZMA2_STATE_DATA_CONT; + if (*src != 0) + { + // first byte of lzma chunk must be Zero + *srcLen += 1; + p->packSize--; + break; + } + } + + if (inCur > p->packSize) + inCur = (SizeT)p->packSize; + + src += inCur; + *srcLen += inCur; + p->packSize -= (UInt32)inCur; + + if (p->packSize == 0) + { + SizeT rem = outSize; + if (rem > p->unpackSize) + rem = p->unpackSize; + p->decoder.dicPos += rem; + p->unpackSize -= (UInt32)rem; + outSize -= rem; + if (p->unpackSize == 0) + p->state = LZMA2_STATE_CONTROL; + } + } + } + } + + p->state = LZMA2_STATE_ERROR; + return LZMA_STATUS_NOT_SPECIFIED; +} + + + + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen, inSize = *srcLen; + *srcLen = *destLen = 0; + + for (;;) + { + SizeT inCur = inSize, outCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + + if (p->decoder.dicPos == p->decoder.dicBufSize) + p->decoder.dicPos = 0; + dicPos = p->decoder.dicPos; + curFinishMode = LZMA_FINISH_ANY; + outCur = p->decoder.dicBufSize - dicPos; + + if (outCur >= outSize) + { + outCur = outSize; + curFinishMode = finishMode; + } + + res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status); + + src += inCur; + inSize -= inCur; + *srcLen += inCur; + outCur = p->decoder.dicPos - dicPos; + memcpy(dest, p->decoder.dic + dicPos, outCur); + dest += outCur; + outSize -= outCur; + *destLen += outCur; + if (res != 0) + return res; + if (outCur == 0 || outSize == 0) + return SZ_OK; + } +} + + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc) +{ + CLzma2Dec p; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + Lzma2Dec_Construct(&p); + RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); + p.decoder.dic = dest; + p.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&p); + *srcLen = inSize; + res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.decoder.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + Lzma2Dec_FreeProbs(&p, alloc); + return res; +} diff --git a/other-licenses/7zstub/src/C/Lzma2Dec.h b/other-licenses/7zstub/src/C/Lzma2Dec.h new file mode 100644 index 0000000000..da50387250 --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma2Dec.h @@ -0,0 +1,120 @@ +/* Lzma2Dec.h -- LZMA2 Decoder +2018-02-19 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_DEC_H +#define __LZMA2_DEC_H + +#include "LzmaDec.h" + +EXTERN_C_BEGIN + +/* ---------- State Interface ---------- */ + +typedef struct +{ + unsigned state; + Byte control; + Byte needInitLevel; + Byte isExtraMode; + Byte _pad_; + UInt32 packSize; + UInt32 unpackSize; + CLzmaDec decoder; +} CLzma2Dec; + +#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) +#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc) +#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc) + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); +void Lzma2Dec_Init(CLzma2Dec *p); + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen or dicLimit). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + SZ_ERROR_DATA - Data error +*/ + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- LZMA2 block and chunk parsing ---------- */ + +/* +Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data. +It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code: + - LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input. + - LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read. + CLzma2Dec::unpackSize contains unpack size of that chunk +*/ + +typedef enum +{ +/* + LZMA_STATUS_NOT_SPECIFIED // data error + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED // + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused +*/ + LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1, + LZMA2_PARSE_STATUS_NEW_CHUNK +} ELzma2ParseStatus; + +ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, + SizeT outSize, // output size + const Byte *src, SizeT *srcLen, + int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position. + ); + +/* +LZMA2 parser doesn't decode LZMA chunks, so we must read + full input LZMA chunk to decode some part of LZMA chunk. + +Lzma2Dec_GetUnpackExtra() returns the value that shows + max possible number of output bytes that can be output by decoder + at current input positon. +*/ + +#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0); + + +/* ---------- One Call Interface ---------- */ + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Lzma2DecMt.c b/other-licenses/7zstub/src/C/Lzma2DecMt.c new file mode 100644 index 0000000000..be698cbeb2 --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma2DecMt.c @@ -0,0 +1,1082 @@ +/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread +2018-03-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#define PRF_STR(s) PRF(printf("\n" s "\n")) +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) +#define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2)) + +// #define _7ZIP_ST + +#include "Alloc.h" + +#include "Lzma2Dec.h" +#include "Lzma2DecMt.h" + +#ifndef _7ZIP_ST +#include "MtDec.h" +#endif + + +#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28) + +void Lzma2DecMtProps_Init(CLzma2DecMtProps *p) +{ + p->inBufSize_ST = 1 << 20; + p->outStep_ST = 1 << 20; + + #ifndef _7ZIP_ST + p->numThreads = 1; + p->inBufSize_MT = 1 << 18; + p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT; + p->inBlockMax = p->outBlockMax + p->outBlockMax / 16; + #endif +} + + + +#ifndef _7ZIP_ST + +/* ---------- CLzma2DecMtThread ---------- */ + +typedef struct +{ + CLzma2Dec dec; + Byte dec_created; + Byte needInit; + + Byte *outBuf; + size_t outBufSize; + + EMtDecParseState state; + ELzma2ParseStatus parseStatus; + + size_t inPreSize; + size_t outPreSize; + + size_t inCodeSize; + size_t outCodeSize; + SRes codeRes; + + CAlignOffsetAlloc alloc; + + Byte mtPad[1 << 7]; +} CLzma2DecMtThread; + +#endif + + +/* ---------- CLzma2DecMt ---------- */ + +typedef struct +{ + // ISzAllocPtr alloc; + ISzAllocPtr allocMid; + + CAlignOffsetAlloc alignOffsetAlloc; + CLzma2DecMtProps props; + Byte prop; + + ISeqInStream *inStream; + ISeqOutStream *outStream; + ICompressProgress *progress; + + Bool finishMode; + Bool outSize_Defined; + UInt64 outSize; + + UInt64 outProcessed; + UInt64 inProcessed; + Bool readWasFinished; + SRes readRes; + + Byte *inBuf; + size_t inBufSize; + Byte dec_created; + CLzma2Dec dec; + + size_t inPos; + size_t inLim; + + #ifndef _7ZIP_ST + UInt64 outProcessed_Parse; + Bool mtc_WasConstructed; + CMtDec mtc; + CLzma2DecMtThread coders[MTDEC__THREADS_MAX]; + #endif + +} CLzma2DecMt; + + + +CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) +{ + CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt)); + if (!p) + return NULL; + + // p->alloc = alloc; + p->allocMid = allocMid; + + AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); + p->alignOffsetAlloc.numAlignBits = 7; + p->alignOffsetAlloc.offset = 0; + p->alignOffsetAlloc.baseAlloc = alloc; + + p->inBuf = NULL; + p->inBufSize = 0; + p->dec_created = False; + + // Lzma2DecMtProps_Init(&p->props); + + #ifndef _7ZIP_ST + p->mtc_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + t->dec_created = False; + t->outBuf = NULL; + t->outBufSize = 0; + } + } + #endif + + return p; +} + + +#ifndef _7ZIP_ST + +static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p) +{ + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + if (t->outBuf) + { + ISzAlloc_Free(p->allocMid, t->outBuf); + t->outBuf = NULL; + t->outBufSize = 0; + } + } +} + +#endif + + +static void Lzma2DecMt_FreeSt(CLzma2DecMt *p) +{ + if (p->dec_created) + { + Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt); + p->dec_created = False; + } + if (p->inBuf) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBuf = NULL; + } + p->inBufSize = 0; +} + + +void Lzma2DecMt_Destroy(CLzma2DecMtHandle pp) +{ + CLzma2DecMt *p = (CLzma2DecMt *)pp; + + Lzma2DecMt_FreeSt(p); + + #ifndef _7ZIP_ST + + if (p->mtc_WasConstructed) + { + MtDec_Destruct(&p->mtc); + p->mtc_WasConstructed = False; + } + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + if (t->dec_created) + { + // we don't need to free dict here + Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!! + t->dec_created = False; + } + } + } + Lzma2DecMt_FreeOutBufs(p); + + #endif + + ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp); +} + + + +#ifndef _7ZIP_ST + +static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) +{ + CLzma2DecMt *me = (CLzma2DecMt *)obj; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + + PRF_STR_INT_2("Parse", coderIndex, cc->srcSize); + + cc->state = MTDEC_PARSE_CONTINUE; + + if (cc->startCall) + { + if (!t->dec_created) + { + Lzma2Dec_Construct(&t->dec); + t->dec_created = True; + AlignOffsetAlloc_CreateVTable(&t->alloc); + { + /* (1 << 12) is expected size of one way in data cache. + We optimize alignment for cache line size of 128 bytes and smaller */ + const unsigned kNumAlignBits = 12; + const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */ + t->alloc.numAlignBits = kNumAlignBits; + t->alloc.offset = ((UInt32)coderIndex * ((1 << 11) + (1 << 8) + (1 << 6))) & ((1 << kNumAlignBits) - (1 << kNumCacheLineBits)); + t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc; + } + } + Lzma2Dec_Init(&t->dec); + + t->inPreSize = 0; + t->outPreSize = 0; + // t->blockWasFinished = False; + // t->finishedWithMark = False; + t->parseStatus = LZMA_STATUS_NOT_SPECIFIED; + t->state = MTDEC_PARSE_CONTINUE; + + t->inCodeSize = 0; + t->outCodeSize = 0; + t->codeRes = SZ_OK; + + // (cc->srcSize == 0) is allowed + } + + { + ELzma2ParseStatus status; + Bool overflow; + UInt32 unpackRem = 0; + + int checkFinishBlock = True; + size_t limit = me->props.outBlockMax; + if (me->outSize_Defined) + { + UInt64 rem = me->outSize - me->outProcessed_Parse; + if (limit >= rem) + { + limit = (size_t)rem; + if (!me->finishMode) + checkFinishBlock = False; + } + } + + // checkFinishBlock = False, if we want to decode partial data + // that must be finished at position <= outBlockMax. + + { + const SizeT srcOrig = cc->srcSize; + SizeT srcSize_Point = 0; + SizeT dicPos_Point = 0; + + cc->srcSize = 0; + overflow = False; + + for (;;) + { + SizeT srcCur = srcOrig - cc->srcSize; + + status = Lzma2Dec_Parse(&t->dec, + limit - t->dec.decoder.dicPos, + cc->src + cc->srcSize, &srcCur, + checkFinishBlock); + + cc->srcSize += srcCur; + + if (status == LZMA2_PARSE_STATUS_NEW_CHUNK) + { + if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos) + { + overflow = True; + break; + } + continue; + } + + if (status == LZMA2_PARSE_STATUS_NEW_BLOCK) + { + if (t->dec.decoder.dicPos == 0) + continue; + // we decode small blocks in one thread + if (t->dec.decoder.dicPos >= (1 << 14)) + break; + dicPos_Point = t->dec.decoder.dicPos; + srcSize_Point = cc->srcSize; + continue; + } + + if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock + // && limit == t->dec.decoder.dicPos + // && limit == me->props.outBlockMax + ) + { + overflow = True; + break; + } + + unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec); + break; + } + + if (dicPos_Point != 0 + && (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK + && (int)status != LZMA_STATUS_FINISHED_WITH_MARK + && (int)status != LZMA_STATUS_NOT_SPECIFIED) + { + // we revert to latest newBlock state + status = LZMA2_PARSE_STATUS_NEW_BLOCK; + unpackRem = 0; + t->dec.decoder.dicPos = dicPos_Point; + cc->srcSize = srcSize_Point; + overflow = False; + } + } + + t->inPreSize += cc->srcSize; + t->parseStatus = status; + + if (overflow) + cc->state = MTDEC_PARSE_OVERFLOW; + else + { + size_t dicPos = t->dec.decoder.dicPos; + + if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (status == LZMA2_PARSE_STATUS_NEW_BLOCK) + { + cc->state = MTDEC_PARSE_NEW; + cc->srcSize--; // we don't need control byte of next block + t->inPreSize--; + } + else + { + cc->state = MTDEC_PARSE_END; + if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK) + { + // (status == LZMA_STATUS_NOT_SPECIFIED) + // (status == LZMA_STATUS_NOT_FINISHED) + if (unpackRem != 0) + { + /* we also reserve space for max possible number of output bytes of current LZMA chunk */ + SizeT rem = limit - dicPos; + if (rem > unpackRem) + rem = unpackRem; + dicPos += rem; + } + } + } + + me->outProcessed_Parse += dicPos; + } + + cc->outPos = dicPos; + t->outPreSize = (size_t)dicPos; + } + + t->state = cc->state; + return; + } +} + + +static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + Byte *dest = t->outBuf; + + if (t->inPreSize == 0) + { + t->codeRes = SZ_ERROR_DATA; + return t->codeRes; + } + + if (!dest || t->outBufSize < t->outPreSize) + { + if (dest) + { + ISzAlloc_Free(me->allocMid, dest); + t->outBuf = NULL; + t->outBufSize = 0; + } + + dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize + // + (1 << 28) + ); + // Sleep(200); + if (!dest) + return SZ_ERROR_MEM; + t->outBuf = dest; + t->outBufSize = t->outPreSize; + } + + t->dec.decoder.dic = dest; + t->dec.decoder.dicBufSize = t->outPreSize; + + t->needInit = True; + + return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt +} + + +static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + // int finished, int blockFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + + UNUSED_VAR(srcFinished) + + PRF_STR_INT_2("Code", coderIndex, srcSize); + + *inCodePos = t->inCodeSize; + *outCodePos = 0; + *stop = True; + + if (t->needInit) + { + Lzma2Dec_Init(&t->dec); + t->needInit = False; + } + + { + ELzmaStatus status; + size_t srcProcessed = srcSize; + Bool blockWasFinished = + ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK); + + SRes res = Lzma2Dec_DecodeToDic(&t->dec, + t->outPreSize, + src, &srcProcessed, + blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY, + &status); + + t->codeRes = res; + + t->inCodeSize += srcProcessed; + *inCodePos = t->inCodeSize; + t->outCodeSize = t->dec.decoder.dicPos; + *outCodePos = t->dec.decoder.dicPos; + + if (res != SZ_OK) + return res; + + if (srcProcessed == srcSize) + *stop = False; + + if (blockWasFinished) + { + if (srcSize != srcProcessed) + return SZ_ERROR_FAIL; + + if (t->inPreSize == t->inCodeSize) + { + if (t->outPreSize != t->outCodeSize) + return SZ_ERROR_FAIL; + *stop = True; + } + } + else + { + if (t->outPreSize == t->outCodeSize) + *stop = True; + } + + return SZ_OK; + } +} + + +#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24) + +static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex, + Bool needWriteToStream, + const Byte *src, size_t srcSize, + Bool *needContinue, Bool *canRecode) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + const CLzma2DecMtThread *t = &me->coders[coderIndex]; + size_t size = t->outCodeSize; + const Byte *data = t->outBuf; + Bool needContinue2 = True; + + PRF_STR_INT_2("Write", coderIndex, srcSize); + + *needContinue = False; + *canRecode = True; + UNUSED_VAR(src) + UNUSED_VAR(srcSize) + + if ( + // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + t->state == MTDEC_PARSE_OVERFLOW + || t->state == MTDEC_PARSE_END) + needContinue2 = False; + + + if (!needWriteToStream) + return SZ_OK; + + me->mtc.inProcessed += t->inCodeSize; + + if (t->codeRes == SZ_OK) + if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK) + if (t->outPreSize != t->outCodeSize + || t->inPreSize != t->inCodeSize) + return SZ_ERROR_FAIL; + + *canRecode = False; + + if (me->outStream) + { + for (;;) + { + size_t cur = size; + size_t written; + if (cur > LZMA2DECMT_STREAM_WRITE_STEP) + cur = LZMA2DECMT_STREAM_WRITE_STEP; + + written = ISeqOutStream_Write(me->outStream, data, cur); + + me->outProcessed += written; + // me->mtc.writtenTotal += written; + if (written != cur) + return SZ_ERROR_WRITE; + data += cur; + size -= cur; + if (size == 0) + { + *needContinue = needContinue2; + return SZ_OK; + } + RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0)); + } + } + + return SZ_ERROR_FAIL; + /* + if (size > me->outBufSize) + return SZ_ERROR_OUTPUT_EOF; + memcpy(me->outBuf, data, size); + me->outBufSize -= size; + me->outBuf += size; + *needContinue = needContinue2; + return SZ_OK; + */ +} + +#endif + + +static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p) +{ + if (!p->dec_created) + { + Lzma2Dec_Construct(&p->dec); + p->dec_created = True; + } + + RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt)); + + if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBufSize = 0; + p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); + if (!p->inBuf) + return SZ_ERROR_MEM; + p->inBufSize = p->props.inBufSize_ST; + } + + Lzma2Dec_Init(&p->dec); + + return SZ_OK; +} + + +static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p + #ifndef _7ZIP_ST + , Bool tMode + #endif + ) +{ + SizeT wrPos; + size_t inPos, inLim; + const Byte *inData; + UInt64 inPrev, outPrev; + + CLzma2Dec *dec; + + #ifndef _7ZIP_ST + if (tMode) + { + Lzma2DecMt_FreeOutBufs(p); + tMode = MtDec_PrepareRead(&p->mtc); + } + #endif + + RINOK(Lzma2Dec_Prepare_ST(p)); + + dec = &p->dec; + + inPrev = p->inProcessed; + outPrev = p->outProcessed; + + inPos = 0; + inLim = 0; + inData = NULL; + wrPos = dec->decoder.dicPos; + + for (;;) + { + SizeT dicPos; + SizeT size; + ELzmaFinishMode finishMode; + SizeT inProcessed; + ELzmaStatus status; + SRes res; + + SizeT outProcessed; + Bool outFinished; + Bool needStop; + + if (inPos == inLim) + { + #ifndef _7ZIP_ST + if (tMode) + { + inData = MtDec_Read(&p->mtc, &inLim); + inPos = 0; + if (inData) + continue; + tMode = False; + inLim = 0; + } + #endif + + if (!p->readWasFinished) + { + inPos = 0; + inLim = p->inBufSize; + inData = p->inBuf; + p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim); + // p->readProcessed += inLim; + // inLim -= 5; p->readWasFinished = True; // for test + if (inLim == 0 || p->readRes != SZ_OK) + p->readWasFinished = True; + } + } + + dicPos = dec->decoder.dicPos; + { + SizeT next = dec->decoder.dicBufSize; + if (next - wrPos > p->props.outStep_ST) + next = wrPos + p->props.outStep_ST; + size = next - dicPos; + } + + finishMode = LZMA_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (size >= rem) + { + size = (SizeT)rem; + if (p->finishMode) + finishMode = LZMA_FINISH_END; + } + } + + inProcessed = inLim - inPos; + + res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status); + + inPos += inProcessed; + p->inProcessed += inProcessed; + outProcessed = dec->decoder.dicPos - dicPos; + p->outProcessed += outProcessed; + + outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed); + + needStop = (res != SZ_OK + || (inProcessed == 0 && outProcessed == 0) + || status == LZMA_STATUS_FINISHED_WITH_MARK + || (!p->finishMode && outFinished)); + + if (needStop || outProcessed >= size) + { + SRes res2; + { + size_t writeSize = dec->decoder.dicPos - wrPos; + size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize); + res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE; + } + + if (dec->decoder.dicPos == dec->decoder.dicBufSize) + dec->decoder.dicPos = 0; + wrPos = dec->decoder.dicPos; + + RINOK(res2); + + if (needStop) + { + if (res != SZ_OK) + return res; + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (p->finishMode) + { + if (p->outSize_Defined && p->outSize != p->outProcessed) + return SZ_ERROR_DATA; + } + return SZ_OK; + } + + if (!p->finishMode && outFinished) + return SZ_OK; + + if (status == LZMA_STATUS_NEEDS_MORE_INPUT) + return SZ_ERROR_INPUT_EOF; + + return SZ_ERROR_DATA; + } + } + + if (p->progress) + { + UInt64 inDelta = p->inProcessed - inPrev; + UInt64 outDelta = p->outProcessed - outPrev; + if (inDelta >= (1 << 22) || outDelta >= (1 << 22)) + { + RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed)); + inPrev = p->inProcessed; + outPrev = p->outProcessed; + } + } + } +} + + + +SRes Lzma2DecMt_Decode(CLzma2DecMtHandle pp, + Byte prop, + const CLzma2DecMtProps *props, + ISeqOutStream *outStream, const UInt64 *outDataSize, int finishMode, + // Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + // const Byte *inData, size_t inDataSize, + UInt64 *inProcessed, + // UInt64 *outProcessed, + int *isMT, + ICompressProgress *progress) +{ + CLzma2DecMt *p = (CLzma2DecMt *)pp; + #ifndef _7ZIP_ST + Bool tMode; + #endif + + *inProcessed = 0; + + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + + p->prop = prop; + p->props = *props; + + p->inStream = inStream; + p->outStream = outStream; + p->progress = progress; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + p->finishMode = finishMode; + + p->outProcessed = 0; + p->inProcessed = 0; + + p->readWasFinished = False; + + *isMT = False; + + + #ifndef _7ZIP_ST + + tMode = False; + + // p->mtc.parseRes = SZ_OK; + + // p->mtc.numFilledThreads = 0; + // p->mtc.crossStart = 0; + // p->mtc.crossEnd = 0; + // p->mtc.allocError_for_Read_BlockIndex = 0; + // p->mtc.isAllocError = False; + + if (p->props.numThreads > 1) + { + IMtDecCallback vt; + + Lzma2DecMt_FreeSt(p); + + p->outProcessed_Parse = 0; + + if (!p->mtc_WasConstructed) + { + p->mtc_WasConstructed = True; + MtDec_Construct(&p->mtc); + } + + p->mtc.progress = progress; + p->mtc.inStream = inStream; + + // p->outBuf = NULL; + // p->outBufSize = 0; + /* + if (!outStream) + { + // p->outBuf = outBuf; + // p->outBufSize = *outBufSize; + // *outBufSize = 0; + return SZ_ERROR_PARAM; + } + */ + + // p->mtc.inBlockMax = p->props.inBlockMax; + p->mtc.alloc = &p->alignOffsetAlloc.vt; + // p->alignOffsetAlloc.baseAlloc; + // p->mtc.inData = inData; + // p->mtc.inDataSize = inDataSize; + p->mtc.mtCallback = &vt; + p->mtc.mtCallbackObject = p; + + p->mtc.inBufSize = p->props.inBufSize_MT; + + p->mtc.numThreadsMax = p->props.numThreads; + + *isMT = True; + + vt.Parse = Lzma2DecMt_MtCallback_Parse; + vt.PreCode = Lzma2DecMt_MtCallback_PreCode; + vt.Code = Lzma2DecMt_MtCallback_Code; + vt.Write = Lzma2DecMt_MtCallback_Write; + + { + Bool needContinue = False; + + SRes res = MtDec_Code(&p->mtc); + + /* + if (!outStream) + *outBufSize = p->outBuf - outBuf; + */ + + *inProcessed = p->mtc.inProcessed; + + needContinue = False; + + if (res == SZ_OK) + { + if (p->mtc.mtProgress.res != SZ_OK) + res = p->mtc.mtProgress.res; + else + needContinue = p->mtc.needContinue; + } + + if (!needContinue) + { + if (res == SZ_OK) + return p->mtc.readRes; + return res; + } + + tMode = True; + p->readRes = p->mtc.readRes; + p->readWasFinished = p->mtc.readWasFinished; + p->inProcessed = p->mtc.inProcessed; + + PRF_STR("----- decoding ST -----"); + } + } + + #endif + + + *isMT = False; + + { + SRes res = Lzma2Dec_Decode_ST(p + #ifndef _7ZIP_ST + , tMode + #endif + ); + + *inProcessed = p->inProcessed; + + // res = SZ_OK; // for test + if (res == SZ_OK && p->readRes != SZ_OK) + res = p->readRes; + + /* + #ifndef _7ZIP_ST + if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK) + res = p->mtc.parseRes; + #endif + */ + + return res; + } +} + + +/* ---------- Read from CLzma2DecMtHandle Interface ---------- */ + +SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp, + Byte prop, + const CLzma2DecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqInStream *inStream) +{ + CLzma2DecMt *p = (CLzma2DecMt *)pp; + + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + + p->prop = prop; + p->props = *props; + + p->inStream = inStream; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + p->finishMode = finishMode; + + p->outProcessed = 0; + p->inProcessed = 0; + + p->inPos = 0; + p->inLim = 0; + + return Lzma2Dec_Prepare_ST(p); +} + + +SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp, + Byte *data, size_t *outSize, + UInt64 *inStreamProcessed) +{ + CLzma2DecMt *p = (CLzma2DecMt *)pp; + ELzmaFinishMode finishMode; + SRes readRes; + size_t size = *outSize; + + *outSize = 0; + *inStreamProcessed = 0; + + finishMode = LZMA_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (size >= rem) + { + size = (size_t)rem; + if (p->finishMode) + finishMode = LZMA_FINISH_END; + } + } + + readRes = SZ_OK; + + for (;;) + { + SizeT inCur; + SizeT outCur; + ELzmaStatus status; + SRes res; + + if (p->inPos == p->inLim && readRes == SZ_OK) + { + p->inPos = 0; + p->inLim = p->props.inBufSize_ST; + readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim); + } + + inCur = p->inLim - p->inPos; + outCur = size; + + res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur, + p->inBuf + p->inPos, &inCur, finishMode, &status); + + p->inPos += inCur; + p->inProcessed += inCur; + *inStreamProcessed += inCur; + p->outProcessed += outCur; + *outSize += outCur; + size -= outCur; + data += outCur; + + if (res != 0) + return res; + + /* + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + return readRes; + + if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize) + return SZ_ERROR_DATA; + return readRes; + } + */ + + if (inCur == 0 && outCur == 0) + return readRes; + } +} diff --git a/other-licenses/7zstub/src/C/Lzma2DecMt.h b/other-licenses/7zstub/src/C/Lzma2DecMt.h new file mode 100644 index 0000000000..96f89a3ca2 --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma2DecMt.h @@ -0,0 +1,79 @@ +/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread +2018-02-17 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_DEC_MT_H +#define __LZMA2_DEC_MT_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef struct +{ + size_t inBufSize_ST; + size_t outStep_ST; + + #ifndef _7ZIP_ST + unsigned numThreads; + size_t inBufSize_MT; + size_t outBlockMax; + size_t inBlockMax; + #endif +} CLzma2DecMtProps; + +/* init to single-thread mode */ +void Lzma2DecMtProps_Init(CLzma2DecMtProps *p); + + +/* ---------- CLzma2DecMtHandle Interface ---------- */ + +/* Lzma2DecMt_ * functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + // SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef void * CLzma2DecMtHandle; + +CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid); +void Lzma2DecMt_Destroy(CLzma2DecMtHandle p); + +SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p, + Byte prop, + const CLzma2DecMtProps *props, + ISeqOutStream *outStream, + const UInt64 *outDataSize, // NULL means undefined + int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished + // Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + // const Byte *inData, size_t inDataSize, + + // out variables: + UInt64 *inProcessed, + int *isMT, /* out: (*isMT == 0), if single thread decoding was used */ + + // UInt64 *outProcessed, + ICompressProgress *progress); + + +/* ---------- Read from CLzma2DecMtHandle Interface ---------- */ + +SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp, + Byte prop, + const CLzma2DecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqInStream *inStream); + +SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp, + Byte *data, size_t *outSize, + UInt64 *inStreamProcessed); + + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Lzma2Enc.c b/other-licenses/7zstub/src/C/Lzma2Enc.c new file mode 100644 index 0000000000..5098195c12 --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma2Enc.c @@ -0,0 +1,803 @@ +/* Lzma2Enc.c -- LZMA2 Encoder +2018-04-27 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define _7ZIP_ST */ + +#include "Lzma2Enc.h" + +#ifndef _7ZIP_ST +#include "MtCoder.h" +#else +#define MTCODER__THREADS_MAX 1 +#endif + +#define LZMA2_CONTROL_LZMA (1 << 7) +#define LZMA2_CONTROL_COPY_NO_RESET 2 +#define LZMA2_CONTROL_COPY_RESET_DIC 1 +#define LZMA2_CONTROL_EOF 0 + +#define LZMA2_LCLP_MAX 4 + +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#define LZMA2_PACK_SIZE_MAX (1 << 16) +#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX +#define LZMA2_UNPACK_SIZE_MAX (1 << 21) +#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX + +#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16) + + +#define PRF(x) /* x */ + + +/* ---------- CLimitedSeqInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + ISeqInStream *realStream; + UInt64 limit; + UInt64 processed; + int finished; +} CLimitedSeqInStream; + +static void LimitedSeqInStream_Init(CLimitedSeqInStream *p) +{ + p->limit = (UInt64)(Int64)-1; + p->processed = 0; + p->finished = 0; +} + +static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt); + size_t size2 = *size; + SRes res = SZ_OK; + + if (p->limit != (UInt64)(Int64)-1) + { + UInt64 rem = p->limit - p->processed; + if (size2 > rem) + size2 = (size_t)rem; + } + if (size2 != 0) + { + res = ISeqInStream_Read(p->realStream, data, &size2); + p->finished = (size2 == 0 ? 1 : 0); + p->processed += size2; + } + *size = size2; + return res; +} + + +/* ---------- CLzma2EncInt ---------- */ + +typedef struct +{ + CLzmaEncHandle enc; + Byte propsAreSet; + Byte propsByte; + Byte needInitState; + Byte needInitProp; + UInt64 srcPos; +} CLzma2EncInt; + + +static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props) +{ + if (!p->propsAreSet) + { + SizeT propsSize = LZMA_PROPS_SIZE; + Byte propsEncoded[LZMA_PROPS_SIZE]; + RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)); + RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)); + p->propsByte = propsEncoded[0]; + p->propsAreSet = True; + } + return SZ_OK; +} + +static void Lzma2EncInt_InitBlock(CLzma2EncInt *p) +{ + p->srcPos = 0; + p->needInitState = True; + p->needInitProp = True; +} + + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); +void LzmaEnc_Finish(CLzmaEncHandle pp); +void LzmaEnc_SaveState(CLzmaEncHandle pp); +void LzmaEnc_RestoreState(CLzmaEncHandle pp); + +/* +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp); +*/ + +static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, + size_t *packSizeRes, ISeqOutStream *outStream) +{ + size_t packSizeLimit = *packSizeRes; + size_t packSize = packSizeLimit; + UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX; + unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0); + Bool useCopyBlock; + SRes res; + + *packSizeRes = 0; + if (packSize < lzHeaderSize) + return SZ_ERROR_OUTPUT_EOF; + packSize -= lzHeaderSize; + + LzmaEnc_SaveState(p->enc); + res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState, + outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize); + + PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize)); + + if (unpackSize == 0) + return res; + + if (res == SZ_OK) + useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16)); + else + { + if (res != SZ_ERROR_OUTPUT_EOF) + return res; + res = SZ_OK; + useCopyBlock = True; + } + + if (useCopyBlock) + { + size_t destPos = 0; + PRF(printf("################# COPY ")); + + while (unpackSize > 0) + { + UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; + if (packSizeLimit - destPos < u + 3) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET); + outBuf[destPos++] = (Byte)((u - 1) >> 8); + outBuf[destPos++] = (Byte)(u - 1); + memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u); + unpackSize -= u; + destPos += u; + p->srcPos += u; + + if (outStream) + { + *packSizeRes += destPos; + if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + destPos = 0; + } + else + *packSizeRes = destPos; + /* needInitState = True; */ + } + + LzmaEnc_RestoreState(p->enc); + return SZ_OK; + } + + { + size_t destPos = 0; + UInt32 u = unpackSize - 1; + UInt32 pm = (UInt32)(packSize - 1); + unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0); + + PRF(printf(" ")); + + outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F)); + outBuf[destPos++] = (Byte)(u >> 8); + outBuf[destPos++] = (Byte)u; + outBuf[destPos++] = (Byte)(pm >> 8); + outBuf[destPos++] = (Byte)pm; + + if (p->needInitProp) + outBuf[destPos++] = p->propsByte; + + p->needInitProp = False; + p->needInitState = False; + destPos += packSize; + p->srcPos += unpackSize; + + if (outStream) + if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + + *packSizeRes = destPos; + return SZ_OK; + } +} + + +/* ---------- Lzma2 Props ---------- */ + +void Lzma2EncProps_Init(CLzma2EncProps *p) +{ + LzmaEncProps_Init(&p->lzmaProps); + p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO; + p->numBlockThreads_Reduced = -1; + p->numBlockThreads_Max = -1; + p->numTotalThreads = -1; +} + +void Lzma2EncProps_Normalize(CLzma2EncProps *p) +{ + UInt64 fileSize; + int t1, t1n, t2, t2r, t3; + { + CLzmaEncProps lzmaProps = p->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + t1n = lzmaProps.numThreads; + } + + t1 = p->lzmaProps.numThreads; + t2 = p->numBlockThreads_Max; + t3 = p->numTotalThreads; + + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + + if (t3 <= 0) + { + if (t2 <= 0) + t2 = 1; + t3 = t1n * t2; + } + else if (t2 <= 0) + { + t2 = t3 / t1n; + if (t2 == 0) + { + t1 = 1; + t2 = t3; + } + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzmaProps.numThreads = t1; + + t2r = t2; + + fileSize = p->lzmaProps.reduceSize; + + if ( p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO + && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) + p->lzmaProps.reduceSize = p->blockSize; + + LzmaEncProps_Normalize(&p->lzmaProps); + + p->lzmaProps.reduceSize = fileSize; + + t1 = p->lzmaProps.numThreads; + + if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + { + t2r = t2 = 1; + t3 = t1; + } + else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1) + { + /* if there is no block multi-threading, we use SOLID block */ + p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID; + } + else + { + if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + { + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + const UInt32 dictSize = p->lzmaProps.dictSize; + 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); + p->blockSize = blockSize; + } + + if (t2 > 1 && fileSize != (UInt64)(Int64)-1) + { + UInt64 numBlocks = fileSize / p->blockSize; + if (numBlocks * p->blockSize != fileSize) + numBlocks++; + if (numBlocks < (unsigned)t2) + { + t2r = (unsigned)numBlocks; + if (t2r == 0) + t2r = 1; + t3 = t1 * t2r; + } + } + } + + p->numBlockThreads_Max = t2; + p->numBlockThreads_Reduced = t2r; + p->numTotalThreads = t3; +} + + +static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) +{ + return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; +} + + +/* ---------- Lzma2 ---------- */ + +typedef struct +{ + Byte propEncoded; + CLzma2EncProps props; + UInt64 expectedDataSize; + + Byte *tempBufLzma; + + ISzAllocPtr alloc; + ISzAllocPtr allocBig; + + CLzma2EncInt coders[MTCODER__THREADS_MAX]; + + #ifndef _7ZIP_ST + + ISeqOutStream *outStream; + Byte *outBuf; + size_t outBuf_Rem; /* remainder in outBuf */ + + size_t outBufSize; /* size of allocated outBufs[i] */ + size_t outBufsDataSizes[MTCODER__BLOCKS_MAX]; + Bool mtCoder_WasConstructed; + CMtCoder mtCoder; + Byte *outBufs[MTCODER__BLOCKS_MAX]; + + #endif + +} CLzma2Enc; + + + +CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc)); + if (!p) + return NULL; + Lzma2EncProps_Init(&p->props); + Lzma2EncProps_Normalize(&p->props); + p->expectedDataSize = (UInt64)(Int64)-1; + p->tempBufLzma = NULL; + p->alloc = alloc; + p->allocBig = allocBig; + { + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + p->coders[i].enc = NULL; + } + + #ifndef _7ZIP_ST + p->mtCoder_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + p->outBufs[i] = NULL; + p->outBufSize = 0; + } + #endif + + return p; +} + + +#ifndef _7ZIP_ST + +static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p) +{ + unsigned i; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + if (p->outBufs[i]) + { + ISzAlloc_Free(p->alloc, p->outBufs[i]); + p->outBufs[i] = NULL; + } + p->outBufSize = 0; +} + +#endif + + +void Lzma2Enc_Destroy(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + { + CLzma2EncInt *t = &p->coders[i]; + if (t->enc) + { + LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); + t->enc = NULL; + } + } + + + #ifndef _7ZIP_ST + if (p->mtCoder_WasConstructed) + { + MtCoder_Destruct(&p->mtCoder); + p->mtCoder_WasConstructed = False; + } + Lzma2Enc_FreeOutBufs(p); + #endif + + ISzAlloc_Free(p->alloc, p->tempBufLzma); + p->tempBufLzma = NULL; + + ISzAlloc_Free(p->alloc, pp); +} + + +SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + CLzmaEncProps lzmaProps = props->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX) + return SZ_ERROR_PARAM; + p->props = *props; + Lzma2EncProps_Normalize(&p->props); + return SZ_OK; +} + + +void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + p->expectedDataSize = expectedDataSiize; +} + + +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps); + for (i = 0; i < 40; i++) + if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i)) + break; + return (Byte)i; +} + + +static SRes Lzma2Enc_EncodeMt1( + CLzma2Enc *me, + CLzma2EncInt *p, + ISeqOutStream *outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + const Byte *inData, size_t inDataSize, + int finished, + ICompressProgress *progress) +{ + UInt64 unpackTotal = 0; + UInt64 packTotal = 0; + size_t outLim = 0; + CLimitedSeqInStream limitedInStream; + + if (outBuf) + { + outLim = *outBufSize; + *outBufSize = 0; + } + + if (!p->enc) + { + p->propsAreSet = False; + p->enc = LzmaEnc_Create(me->alloc); + if (!p->enc) + return SZ_ERROR_MEM; + } + + limitedInStream.realStream = inStream; + if (inStream) + { + limitedInStream.vt.Read = LimitedSeqInStream_Read; + } + + if (!outBuf) + { + // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma + if (!me->tempBufLzma) + { + me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); + if (!me->tempBufLzma) + return SZ_ERROR_MEM; + } + } + + RINOK(Lzma2EncInt_InitStream(p, &me->props)); + + for (;;) + { + SRes res = SZ_OK; + size_t inSizeCur = 0; + + Lzma2EncInt_InitBlock(p); + + LimitedSeqInStream_Init(&limitedInStream); + limitedInStream.limit = me->props.blockSize; + + if (inStream) + { + UInt64 expected = (UInt64)(Int64)-1; + // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize + if (me->expectedDataSize != (UInt64)(Int64)-1 + && me->expectedDataSize >= unpackTotal) + expected = me->expectedDataSize - unpackTotal; + if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && expected > me->props.blockSize) + expected = (size_t)me->props.blockSize; + + LzmaEnc_SetDataSize(p->enc, expected); + + RINOK(LzmaEnc_PrepareForLzma2(p->enc, + &limitedInStream.vt, + LZMA2_KEEP_WINDOW_SIZE, + me->alloc, + me->allocBig)); + } + else + { + inSizeCur = inDataSize - (size_t)unpackTotal; + if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && inSizeCur > me->props.blockSize) + inSizeCur = (size_t)me->props.blockSize; + + // LzmaEnc_SetDataSize(p->enc, inSizeCur); + + RINOK(LzmaEnc_MemPrepare(p->enc, + inData + (size_t)unpackTotal, inSizeCur, + LZMA2_KEEP_WINDOW_SIZE, + me->alloc, + me->allocBig)); + } + + for (;;) + { + size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; + if (outBuf) + packSize = outLim - (size_t)packTotal; + + res = Lzma2EncInt_EncodeSubblock(p, + outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize, + outBuf ? NULL : outStream); + + if (res != SZ_OK) + break; + + packTotal += packSize; + if (outBuf) + *outBufSize = (size_t)packTotal; + + res = Progress(progress, unpackTotal + p->srcPos, packTotal); + if (res != SZ_OK) + break; + + /* + if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0) + break; + */ + + if (packSize == 0) + break; + } + + LzmaEnc_Finish(p->enc); + + unpackTotal += p->srcPos; + + RINOK(res); + + if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur)) + return SZ_ERROR_FAIL; + + if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize)) + { + if (finished) + { + if (outBuf) + { + size_t destPos = *outBufSize; + if (destPos >= outLim) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos] = 0; + *outBufSize = destPos + 1; + } + else + { + Byte b = 0; + if (ISeqOutStream_Write(outStream, &b, 1) != 1) + return SZ_ERROR_WRITE; + } + } + return SZ_OK; + } + } +} + + + +#ifndef _7ZIP_ST + +static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished) +{ + CLzma2Enc *me = (CLzma2Enc *)pp; + size_t destSize = me->outBufSize; + SRes res; + CMtProgressThunk progressThunk; + + Byte *dest = me->outBufs[outBufIndex]; + + me->outBufsDataSizes[outBufIndex] = 0; + + if (!dest) + { + dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); + if (!dest) + return SZ_ERROR_MEM; + me->outBufs[outBufIndex] = dest; + } + + MtProgressThunk_CreateVTable(&progressThunk); + progressThunk.mtProgress = &me->mtCoder.mtProgress; + progressThunk.inSize = 0; + progressThunk.outSize = 0; + + res = Lzma2Enc_EncodeMt1(me, + &me->coders[coderIndex], + NULL, dest, &destSize, + NULL, src, srcSize, + finished, + &progressThunk.vt); + + me->outBufsDataSizes[outBufIndex] = destSize; + + return res; +} + + +static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex) +{ + CLzma2Enc *me = (CLzma2Enc *)pp; + size_t size = me->outBufsDataSizes[outBufIndex]; + const Byte *data = me->outBufs[outBufIndex]; + + if (me->outStream) + return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE; + + if (size > me->outBuf_Rem) + return SZ_ERROR_OUTPUT_EOF; + memcpy(me->outBuf, data, size); + me->outBuf_Rem -= size; + me->outBuf += size; + return SZ_OK; +} + +#endif + + + +SRes Lzma2Enc_Encode2(CLzma2EncHandle pp, + ISeqOutStream *outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + const Byte *inData, size_t inDataSize, + ICompressProgress *progress) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + + if (inStream && inData) + return SZ_ERROR_PARAM; + + if (outStream && outBuf) + return SZ_ERROR_PARAM; + + { + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + p->coders[i].propsAreSet = False; + } + + #ifndef _7ZIP_ST + + if (p->props.numBlockThreads_Reduced > 1) + { + IMtCoderCallback2 vt; + + if (!p->mtCoder_WasConstructed) + { + p->mtCoder_WasConstructed = True; + MtCoder_Construct(&p->mtCoder); + } + + vt.Code = Lzma2Enc_MtCallback_Code; + vt.Write = Lzma2Enc_MtCallback_Write; + + p->outStream = outStream; + p->outBuf = NULL; + p->outBuf_Rem = 0; + if (!outStream) + { + p->outBuf = outBuf; + p->outBuf_Rem = *outBufSize; + *outBufSize = 0; + } + + p->mtCoder.allocBig = p->allocBig; + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.inData = inData; + p->mtCoder.inDataSize = inDataSize; + p->mtCoder.mtCallback = &vt; + p->mtCoder.mtCallbackObject = p; + + p->mtCoder.blockSize = (size_t)p->props.blockSize; + if (p->mtCoder.blockSize != p->props.blockSize) + return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ + + { + size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16; + if (destBlockSize < p->mtCoder.blockSize) + return SZ_ERROR_PARAM; + if (p->outBufSize != destBlockSize) + Lzma2Enc_FreeOutBufs(p); + p->outBufSize = destBlockSize; + } + + p->mtCoder.numThreadsMax = p->props.numBlockThreads_Max; + p->mtCoder.expectedDataSize = p->expectedDataSize; + + { + SRes res = MtCoder_Code(&p->mtCoder); + if (!outStream) + *outBufSize = p->outBuf - outBuf; + return res; + } + } + + #endif + + + return Lzma2Enc_EncodeMt1(p, + &p->coders[0], + outStream, outBuf, outBufSize, + inStream, inData, inDataSize, + True, /* finished */ + progress); +} diff --git a/other-licenses/7zstub/src/C/Lzma2Enc.h b/other-licenses/7zstub/src/C/Lzma2Enc.h new file mode 100644 index 0000000000..65f2dd145d --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma2Enc.h @@ -0,0 +1,55 @@ +/* Lzma2Enc.h -- LZMA2 Encoder +2017-07-27 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_ENC_H +#define __LZMA2_ENC_H + +#include "LzmaEnc.h" + +EXTERN_C_BEGIN + +#define LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO 0 +#define LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID ((UInt64)(Int64)-1) + +typedef struct +{ + CLzmaEncProps lzmaProps; + UInt64 blockSize; + int numBlockThreads_Reduced; + int numBlockThreads_Max; + int numTotalThreads; +} CLzma2EncProps; + +void Lzma2EncProps_Init(CLzma2EncProps *p); +void Lzma2EncProps_Normalize(CLzma2EncProps *p); + +/* ---------- CLzmaEnc2Handle Interface ---------- */ + +/* Lzma2Enc_* functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef void * CLzma2EncHandle; + +CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig); +void Lzma2Enc_Destroy(CLzma2EncHandle p); +SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props); +void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize); +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p); +SRes Lzma2Enc_Encode2(CLzma2EncHandle p, + ISeqOutStream *outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + const Byte *inData, size_t inDataSize, + ICompressProgress *progress); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Lzma86.h b/other-licenses/7zstub/src/C/Lzma86.h new file mode 100644 index 0000000000..83057e5983 --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma86.h @@ -0,0 +1,111 @@ +/* Lzma86.h -- LZMA + x86 (BCJ) Filter +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA86_H +#define __LZMA86_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define LZMA86_SIZE_OFFSET (1 + 5) +#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) + +/* +It's an example for LZMA + x86 Filter use. +You can use .lzma86 extension, if you write that stream to file. +.lzma86 header adds one additional byte to standard .lzma header. +.lzma86 header (14 bytes): + Offset Size Description + 0 1 = 0 - no filter, pure LZMA + = 1 - x86 filter + LZMA + 1 1 lc, lp and pb in encoded form + 2 4 dictSize (little endian) + 6 8 uncompressed size (little endian) + + +Lzma86_Encode +------------- +level - compression level: 0 <= level <= 9, the default value for "level" is 5. + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes, for level = 5. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + For better compression ratio dictSize must be >= inSize. + +filterMode: + SZ_FILTER_NO - no Filter + SZ_FILTER_YES - x86 Filter + SZ_FILTER_AUTO - it tries both alternatives to select best. + Encoder will use 2 or 3 passes: + 2 passes when FILTER_NO provides better compression. + 3 passes when FILTER_YES provides better compression. + +Lzma86Encode allocates Data with MyAlloc functions. +RAM Requirements for compressing: + RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize + filterMode FilterBlockSize + SZ_FILTER_NO 0 + SZ_FILTER_YES inSize + SZ_FILTER_AUTO inSize + + +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +enum ESzFilterMode +{ + SZ_FILTER_NO, + SZ_FILTER_YES, + SZ_FILTER_AUTO +}; + +SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode); + + +/* +Lzma86_GetUnpackSize: + In: + src - input data + srcLen - input data size + Out: + unpackSize - size of uncompressed stream + Return code: + SZ_OK - OK + SZ_ERROR_INPUT_EOF - Error in headers +*/ + +SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); + +/* +Lzma86_Decode: + In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size + Out: + destLen - processed output size + srcLen - processed input size + Return code: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - unsupported file + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer +*/ + +SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Lzma86Dec.c b/other-licenses/7zstub/src/C/Lzma86Dec.c new file mode 100644 index 0000000000..20ac5e7a97 --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma86Dec.c @@ -0,0 +1,54 @@ +/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder +2016-05-16 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Lzma86.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaDec.h" + +SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) +{ + unsigned i; + if (srcLen < LZMA86_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + *unpackSize = 0; + for (i = 0; i < sizeof(UInt64); i++) + *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); + return SZ_OK; +} + +SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) +{ + SRes res; + int useFilter; + SizeT inSizePure; + ELzmaStatus status; + + if (*srcLen < LZMA86_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + + useFilter = src[0]; + + if (useFilter > 1) + { + *destLen = 0; + return SZ_ERROR_UNSUPPORTED; + } + + inSizePure = *srcLen - LZMA86_HEADER_SIZE; + res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, + src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); + *srcLen = inSizePure + LZMA86_HEADER_SIZE; + if (res != SZ_OK) + return res; + if (useFilter == 1) + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(dest, *destLen, 0, &x86State, 0); + } + return SZ_OK; +} diff --git a/other-licenses/7zstub/src/C/Lzma86Enc.c b/other-licenses/7zstub/src/C/Lzma86Enc.c new file mode 100644 index 0000000000..ee59fb7d77 --- /dev/null +++ b/other-licenses/7zstub/src/C/Lzma86Enc.c @@ -0,0 +1,106 @@ +/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder +2016-05-16 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "Lzma86.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaEnc.h" + +#define SZE_OUT_OVERFLOW SZE_DATA_ERROR + +int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode) +{ + size_t outSize2 = *destLen; + Byte *filteredStream; + Bool useFilter; + int mainResult = SZ_ERROR_OUTPUT_EOF; + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + + *destLen = 0; + if (outSize2 < LZMA86_HEADER_SIZE) + return SZ_ERROR_OUTPUT_EOF; + + { + int i; + UInt64 t = srcLen; + for (i = 0; i < 8; i++, t >>= 8) + dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; + } + + filteredStream = 0; + useFilter = (filterMode != SZ_FILTER_NO); + if (useFilter) + { + if (srcLen != 0) + { + filteredStream = (Byte *)MyAlloc(srcLen); + if (filteredStream == 0) + return SZ_ERROR_MEM; + memcpy(filteredStream, src, srcLen); + } + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(filteredStream, srcLen, 0, &x86State, 1); + } + } + + { + size_t minSize = 0; + Bool bestIsFiltered = False; + + /* passes for SZ_FILTER_AUTO: + 0 - BCJ + LZMA + 1 - LZMA + 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. + */ + int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; + + int i; + for (i = 0; i < numPasses; i++) + { + size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; + size_t outPropsSize = 5; + SRes curRes; + Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); + if (curModeIsFiltered && !bestIsFiltered) + break; + if (useFilter && i == 0) + curModeIsFiltered = True; + + curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, + curModeIsFiltered ? filteredStream : src, srcLen, + &props, dest + 1, &outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); + + if (curRes != SZ_ERROR_OUTPUT_EOF) + { + if (curRes != SZ_OK) + { + mainResult = curRes; + break; + } + if (outSizeProcessed <= minSize || mainResult != SZ_OK) + { + minSize = outSizeProcessed; + bestIsFiltered = curModeIsFiltered; + mainResult = SZ_OK; + } + } + } + dest[0] = (Byte)(bestIsFiltered ? 1 : 0); + *destLen = LZMA86_HEADER_SIZE + minSize; + } + if (useFilter) + MyFree(filteredStream); + return mainResult; +} diff --git a/other-licenses/7zstub/src/C/LzmaDec.c b/other-licenses/7zstub/src/C/LzmaDec.c new file mode 100644 index 0000000000..962b94bb63 --- /dev/null +++ b/other-licenses/7zstub/src/C/LzmaDec.c @@ -0,0 +1,1185 @@ +/* LzmaDec.c -- LZMA Decoder +2018-02-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +/* #include "CpuArch.h" */ +#include "LzmaDec.h" + +#include + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } + +#define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); } + +#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \ + { UPDATE_0(p + i); A0; } else \ + { UPDATE_1(p + i); A1; } +#define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; ) +#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; ) +#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; ) + +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol) +#define MATCHED_LITER_DEC \ + matchByte += matchByte; \ + bit = offs; \ + offs &= matchByte; \ + probLit = prob + (offs + bit + symbol); \ + GET_BIT2(probLit, symbol, offs ^= bit; , ;) + + + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \ + { UPDATE_0_CHECK; i += m; m += m; } else \ + { UPDATE_1_CHECK; m += m; i += m; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenLow 0 +#define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + +#define LenChoice LenLow +#define LenChoice2 (LenLow + (1 << kLenNumLowBits)) + +#define kNumStates 12 +#define kNumStates2 16 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +/* External ASM code needs same CLzmaProb array layout. So don't change it. */ + +/* (probs_1664) is faster and better for code size at some platforms */ +/* +#ifdef MY_CPU_X86_OR_AMD64 +*/ +#define kStartOffset 1664 +#define GET_PROBS p->probs_1664 +/* +#define GET_PROBS p->probs + kStartOffset +#else +#define kStartOffset 0 +#define GET_PROBS p->probs +#endif +*/ + +#define SpecPos (-kStartOffset) +#define IsRep0Long (SpecPos + kNumFullDistances) +#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax)) +#define LenCoder (RepLenCoder + kNumLenProbs) +#define IsMatch (LenCoder + kNumLenProbs) +#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax)) +#define IsRep (Align + kAlignTableSize) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define PosSlot (IsRepG2 + kNumStates) +#define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define NUM_BASE_PROBS (Literal + kStartOffset) + +#if Align != 0 && kStartOffset != 0 + #error Stop_Compiling_Bad_LZMA_kAlign +#endif + +#if NUM_BASE_PROBS != 1984 + #error Stop_Compiling_Bad_LZMA_PROBS +#endif + + +#define LZMA_LIT_SIZE 0x300 + +#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + + +#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4) +#define COMBINED_PS_STATE (posState + state) +#define GET_LEN_STATE (posState) + +#define LZMA_DIC_MIN (1 << 12) + +/* +p->remainLen : shows status of LZMA decoder: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : need init range coder + = kMatchSpecLenStart + 2 : need init range coder and state +*/ + +/* ---------- LZMA_DECODE_REAL ---------- */ +/* +LzmaDec_DecodeReal_3() can be implemented in external ASM file. +3 - is the code compatibility version of that function for check at link time. +*/ + +#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3 + +/* +LZMA_DECODE_REAL() +In: + RangeCoder is normalized + if (p->dicPos == limit) + { + LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases. + So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol + is not END_OF_PAYALOAD_MARKER, then function returns error code. + } + +Processing: + first LZMA symbol will be decoded in any case + All checks for limits are at the end of main loop, + It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit), + RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked. + +Out: + RangeCoder is normalized + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished +*/ + + +#ifdef _LZMA_DEC_OPT + +int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit); + +#else + +static +int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = GET_PROBS; + unsigned state = (unsigned)p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lc = p->prop.lc; + unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc); + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = CALC_POS_STATE(processedPos, pbMask); + + prob = probs + IsMatch + COMBINED_PS_STATE; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (processedPos != 0 || checkDicSize != 0) + prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc); + processedPos++; + + if (state < kNumLitStates) + { + state -= (state < 4) ? state : 3; + symbol = 1; + #ifdef _LZMA_SIZE_OPT + do { NORMAL_LITER_DEC } while (symbol < 0x100); + #else + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + #endif + } + else + { + unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + unsigned offs = 0x100; + state -= (state < 10) ? 3 : 6; + symbol = 1; + #ifdef _LZMA_SIZE_OPT + do + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + } + while (symbol < 0x100); + #else + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + } + #endif + } + + dic[dicPos++] = (Byte)symbol; + continue; + } + + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + /* + // that case was checked before with kBadRepCode + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + */ + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + COMBINED_PS_STATE; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + + #ifdef _LZMA_SIZE_OPT + { + unsigned lim, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE; + offset = 0; + lim = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + offset = kLenNumLowSymbols; + lim = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols * 2; + lim = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, lim, len); + len += offset; + } + #else + { + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE; + len = 1; + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + len -= 8; + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + len = 1; + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + TREE_DECODE(probLen, (1 << kLenNumHighBits), len); + len += kLenNumLowSymbols * 2; + } + } + } + #endif + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos; + { + UInt32 m = 1; + distance++; + do + { + REV_BIT_VAR(prob, distance, m); + } + while (--numDirectBits); + distance -= m; + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + REV_BIT_CONST(prob, i, 1); + REV_BIT_CONST(prob, i, 2); + REV_BIT_CONST(prob, i, 4); + REV_BIT_LAST (prob, i, 8); + distance |= i; + } + if (distance == (UInt32)0xFFFFFFFF) + { + len = kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) + { + p->dicPos = dicPos; + return SZ_ERROR_DATA; + } + } + + len += kMatchMinLen; + + { + SizeT rem; + unsigned curLen; + SizeT pos; + + if ((rem = limit - dicPos) == 0) + { + p->dicPos = dicPos; + return SZ_ERROR_DATA; + } + + curLen = ((rem < len) ? (unsigned)rem : len); + pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (curLen <= dicBufSize - pos) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + + NORMALIZE; + + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} +#endif + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = (unsigned)p->remainLen; + SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */ + SizeT rem = limit - dicPos; + if (rem < len) + len = (unsigned)(rem); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len != 0) + { + len--; + dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + + +#define kRange0 0xFFFFFFFF +#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)) +#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))) +#if kBadRepCode != (0xC0000000 - 0x400) + #error Stop_Compiling_Bad_LZMA_Check +#endif + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + + if (p->processedPos == 0) + if (p->code >= kBadRepCode) + return SZ_ERROR_DATA; + } + + RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit)); + + if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + const CLzmaProb *probs = GET_PROBS; + unsigned state = (unsigned)p->state; + ELzmaDummy res; + + { + const CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1); + + prob = probs + IsMatch + COMBINED_PS_STATE; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += ((UInt32)LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + (p->dicPos < p->reps[0] ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + const CLzmaProb *probLit; + matchByte += matchByte; + bit = offs; + offs &= matchByte; + probLit = prob + (offs + bit + symbol); + GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; ) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + COMBINED_PS_STATE; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + const CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + GET_LEN_STATE; + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols * 2; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + unsigned numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits); + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + unsigned m = 1; + do + { + REV_BIT_CHECK(prob, i, m); + } + while (--numDirectBits); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->remainLen = kMatchSpecLenStart + 1; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->remainLen = kMatchSpecLenStart + 2; + } + if (initState) + p->remainLen = kMatchSpecLenStart + 2; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + + *status = LZMA_STATUS_NOT_SPECIFIED; + + if (p->remainLen > kMatchSpecLenStart) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize != 0 && p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + p->code = + ((UInt32)p->tempBuf[1] << 24) + | ((UInt32)p->tempBuf[2] << 16) + | ((UInt32)p->tempBuf[3] << 8) + | ((UInt32)p->tempBuf[4]); + p->range = 0xFFFFFFFF; + p->tempBufSize = 0; + + if (p->remainLen > kMatchSpecLenStart + 1) + { + SizeT numProbs = LzmaProps_GetNumProbs(&p->prop); + SizeT i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + } + + p->remainLen = 0; + } + + LzmaDec_WriteRem(p, dicLimit); + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow = 0; + + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + + { + unsigned kkk = (unsigned)(p->buf - p->tempBuf); + if (rem < kkk) + return SZ_ERROR_FAIL; /* some internal error */ + rem -= kkk; + if (lookAhead < rem) + return SZ_ERROR_FAIL; /* some internal error */ + lookAhead -= rem; + } + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + + if (p->code != 0) + return SZ_ERROR_DATA; + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; +} + + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->probs); + p->probs = NULL; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->dic); + p->dic = NULL; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = (Byte)(d % 9); + d /= 9; + p->pb = (Byte)(d / 5); + p->lp = (Byte)(d % 5); + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (!p->probs || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb)); + if (!p->probs) + return SZ_ERROR_MEM; + p->probs_1664 = p->probs + 1664; + p->numProbs = numProbs; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + + { + UInt32 dictSize = propNew.dicSize; + SizeT mask = ((UInt32)1 << 12) - 1; + if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1; + else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;; + dicBufSize = ((SizeT)dictSize + mask) & ~mask; + if (dicBufSize < dictSize) + dicBufSize = dictSize; + } + + if (!p->dic || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)ISzAlloc_Alloc(alloc, dicBufSize); + if (!p->dic) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAllocPtr alloc) +{ + CLzmaDec p; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + LzmaDec_Construct(&p); + RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)); + p.dic = dest; + p.dicBufSize = outSize; + LzmaDec_Init(&p); + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/other-licenses/7zstub/src/C/LzmaDec.h b/other-licenses/7zstub/src/C/LzmaDec.h new file mode 100644 index 0000000000..28ce60c3ea --- /dev/null +++ b/other-licenses/7zstub/src/C/LzmaDec.h @@ -0,0 +1,234 @@ +/* LzmaDec.h -- LZMA Decoder +2018-04-21 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +typedef +#ifdef _LZMA_PROB32 + UInt32 +#else + UInt16 +#endif + CLzmaProb; + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + Byte lc; + Byte lp; + Byte pb; + Byte _pad_; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + /* Don't change this structure. ASM code can use it. */ + CLzmaProps prop; + CLzmaProb *probs; + CLzmaProb *probs_1664; + Byte *dic; + SizeT dicBufSize; + SizeT dicPos; + const Byte *buf; + UInt32 range; + UInt32 code; + UInt32 processedPos; + UInt32 checkDicSize; + UInt32 reps[4]; + UInt32 state; + UInt32 remainLen; + + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + - Stream with end mark. That end mark adds about 6 bytes to compressed size. + - Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc); + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); +void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Construct() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAllocPtr alloc); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/LzmaEnc.c b/other-licenses/7zstub/src/C/LzmaEnc.c new file mode 100644 index 0000000000..bebe664d3e --- /dev/null +++ b/other-licenses/7zstub/src/C/LzmaEnc.c @@ -0,0 +1,2787 @@ +/* LzmaEnc.c -- LZMA Encoder +2018-04-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define SHOW_STAT */ +/* #define SHOW_STAT2 */ + +#if defined(SHOW_STAT) || defined(SHOW_STAT2) +#include +#endif + +#include "LzmaEnc.h" + +#include "LzFind.h" +#ifndef _7ZIP_ST +#include "LzFindMt.h" +#endif + +#ifdef SHOW_STAT +static unsigned g_STAT_OFFSET = 0; +#endif + +#define kLzmaMaxHistorySize ((UInt32)3 << 29) +/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */ + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 +#define kProbInitValue (kBitModelTotal >> 1) + +#define kNumMoveReducingBits 4 +#define kNumBitPriceShiftBits 4 +#define kBitPrice (1 << kNumBitPriceShiftBits) + +void LzmaEncProps_Init(CLzmaEncProps *p) +{ + p->level = 5; + p->dictSize = p->mc = 0; + p->reduceSize = (UInt64)(Int64)-1; + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->writeEndMark = 0; +} + +void LzmaEncProps_Normalize(CLzmaEncProps *p) +{ + int level = p->level; + if (level < 0) level = 5; + p->level = level; + + if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26))); + if (p->dictSize > p->reduceSize) + { + unsigned i; + UInt32 reduceSize = (UInt32)p->reduceSize; + for (i = 11; i <= 30; i++) + { + if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } + if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } + } + } + + if (p->lc < 0) p->lc = 3; + if (p->lp < 0) p->lp = 0; + if (p->pb < 0) p->pb = 2; + + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = 4; + if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); + + if (p->numThreads < 0) + p->numThreads = + #ifndef _7ZIP_ST + ((p->btMode && p->algo) ? 2 : 1); + #else + 1; + #endif +} + +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +{ + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + return props.dictSize; +} + +#if (_MSC_VER >= 1400) +/* BSR code is fast for some new CPUs */ +/* #define LZMA_LOG_BSR */ +#endif + +#ifdef LZMA_LOG_BSR + +#define kDicLogSizeMaxCompress 32 + +#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); } + +static unsigned GetPosSlot1(UInt32 pos) +{ + unsigned res; + BSR2_RET(pos, res); + return res; +} +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } + +#else + +#define kNumLogBits (9 + sizeof(size_t) / 2) +/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */ + +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +static void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + unsigned slot; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + g_FastPos += 2; + + for (slot = 2; slot < kNumLogBits * 2; slot++) + { + size_t k = ((size_t)1 << ((slot >> 1) - 1)); + size_t j; + for (j = 0; j < k; j++) + g_FastPos[j] = (Byte)slot; + g_FastPos += k; + } +} + +/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */ +/* +#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } +*/ + +/* +#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } +*/ + +#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } + +/* +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ + p->g_FastPos[pos >> 6] + 12 : \ + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +*/ + +#define GetPosSlot1(pos) p->g_FastPos[pos] +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); } + +#endif + + +#define LZMA_NUM_REPS 4 + +typedef UInt16 CState; +typedef UInt16 CExtra; + +typedef struct +{ + UInt32 price; + CState state; + CExtra extra; + // 0 : normal + // 1 : LIT : MATCH + // > 1 : MATCH (extra-1) : LIT : REP0 (len) + UInt32 len; + UInt32 dist; + UInt32 reps[LZMA_NUM_REPS]; +} COptimal; + + +#define kNumOpts (1 << 12) +#define kPackReserve (1 + kNumOpts * 2) + +#define kNumLenToPosStates 4 +#define kNumPosSlotBits 6 +#define kDicLogSizeMin 0 +#define kDicLogSizeMax 32 +#define kDistTableSizeMax (kDicLogSizeMax * 2) + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) +#define kAlignMask (kAlignTableSize - 1) + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +typedef +#ifdef _LZMA_PROB32 + UInt32 +#else + UInt16 +#endif + CLzmaProb; + +#define LZMA_PB_MAX 4 +#define LZMA_LC_MAX 8 +#define LZMA_LP_MAX 4 + +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) +#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + + +typedef struct +{ + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + + +typedef struct +{ + unsigned tableSize; + unsigned counters[LZMA_NUM_PB_STATES_MAX]; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; +} CLenPriceEnc; + + +typedef struct +{ + UInt32 range; + unsigned cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + + +typedef struct +{ + CLzmaProb *litProbs; + + unsigned state; + UInt32 reps[LZMA_NUM_REPS]; + + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances]; + + CLenEnc lenProbs; + CLenEnc repLenProbs; + +} CSaveState; + + +typedef UInt32 CProbPrice; + + +typedef struct +{ + void *matchFinderObj; + IMatchFinder matchFinder; + + unsigned optCur; + unsigned optEnd; + + unsigned longestMatchLen; + unsigned numPairs; + UInt32 numAvail; + + unsigned state; + unsigned numFastBytes; + unsigned additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + unsigned lpMask, pbMask; + CLzmaProb *litProbs; + CRangeEnc rc; + + UInt32 backRes; + + unsigned lc, lp, pb; + unsigned lclp; + + Bool fastMode; + Bool writeEndMark; + Bool finished; + Bool multiThread; + Bool needInit; + + UInt64 nowPos64; + + unsigned matchPriceCount; + unsigned alignPriceCount; + + unsigned distTableSize; + + UInt32 dictSize; + SRes result; + + #ifndef _7ZIP_ST + Bool mtMode; + // begin of CMatchFinderMt is used in LZ thread + CMatchFinderMt matchFinderMt; + // end of CMatchFinderMt is used in BT and HASH threads + #endif + + CMatchFinder matchFinderBase; + + #ifndef _7ZIP_ST + Byte pad[128]; + #endif + + // LZ thread + CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + + UInt32 alignPrices[kAlignTableSize]; + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances]; + + CLenEnc lenProbs; + CLenEnc repLenProbs; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + COptimal opt[kNumOpts]; + + CSaveState saveState; + + #ifndef _7ZIP_ST + Byte pad2[128]; + #endif +} CLzmaEnc; + + + +#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr)); + +void LzmaEnc_SaveState(CLzmaEncHandle pp) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CSaveState *dest = &p->saveState; + + dest->state = p->state; + + dest->lenProbs = p->lenProbs; + dest->repLenProbs = p->repLenProbs; + + COPY_ARR(dest, p, reps); + + COPY_ARR(dest, p, posAlignEncoder); + COPY_ARR(dest, p, isRep); + COPY_ARR(dest, p, isRepG0); + COPY_ARR(dest, p, isRepG1); + COPY_ARR(dest, p, isRepG2); + COPY_ARR(dest, p, isMatch); + COPY_ARR(dest, p, isRep0Long); + COPY_ARR(dest, p, posSlotEncoder); + COPY_ARR(dest, p, posEncoders); + + memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb)); +} + + +void LzmaEnc_RestoreState(CLzmaEncHandle pp) +{ + CLzmaEnc *dest = (CLzmaEnc *)pp; + const CSaveState *p = &dest->saveState; + + dest->state = p->state; + + dest->lenProbs = p->lenProbs; + dest->repLenProbs = p->repLenProbs; + + COPY_ARR(dest, p, reps); + + COPY_ARR(dest, p, posAlignEncoder); + COPY_ARR(dest, p, isRep); + COPY_ARR(dest, p, isRepG0); + COPY_ARR(dest, p, isRepG1); + COPY_ARR(dest, p, isRepG2); + COPY_ARR(dest, p, isMatch); + COPY_ARR(dest, p, isRep0Long); + COPY_ARR(dest, p, posSlotEncoder); + COPY_ARR(dest, p, posEncoders); + + memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb)); +} + + + +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + + if (props.lc > LZMA_LC_MAX + || props.lp > LZMA_LP_MAX + || props.pb > LZMA_PB_MAX + || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress) + || props.dictSize > kLzmaMaxHistorySize) + return SZ_ERROR_PARAM; + + p->dictSize = props.dictSize; + { + unsigned fb = props.fb; + if (fb < 5) + fb = 5; + if (fb > LZMA_MATCH_LEN_MAX) + fb = LZMA_MATCH_LEN_MAX; + p->numFastBytes = fb; + } + p->lc = props.lc; + p->lp = props.lp; + p->pb = props.pb; + p->fastMode = (props.algo == 0); + p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0); + { + unsigned numHashBytes = 4; + if (props.btMode) + { + if (props.numHashBytes < 2) + numHashBytes = 2; + else if (props.numHashBytes < 4) + numHashBytes = props.numHashBytes; + } + p->matchFinderBase.numHashBytes = numHashBytes; + } + + p->matchFinderBase.cutValue = props.mc; + + p->writeEndMark = props.writeEndMark; + + #ifndef _7ZIP_ST + /* + if (newMultiThread != _multiThread) + { + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + */ + p->multiThread = (props.numThreads > 1); + #endif + + return SZ_OK; +} + + +void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->matchFinderBase.expectedDataSize = expectedDataSiize; +} + + +#define kState_Start 0 +#define kState_LitAfterMatch 4 +#define kState_LitAfterRep 5 +#define kState_MatchAfterLit 7 +#define kState_RepAfterLit 8 + +static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +#define IsLitState(s) ((s) < 7) +#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1) +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = NULL; + p->bufBase = NULL; +} + +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) +#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize) + +#define RC_BUF_SIZE (1 << 16) + +static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc) +{ + if (!p->bufBase) + { + p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE); + if (!p->bufBase) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->range = 0xFFFFFFFF; + p->cache = 0; + p->low = 0; + p->cacheSize = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = p->buf - p->bufBase; + if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + UInt32 low = (UInt32)p->low; + unsigned high = (unsigned)(p->low >> 32); + p->low = (UInt32)(low << 8); + if (low < (UInt32)0xFF000000 || high != 0) + { + { + Byte *buf = p->buf; + *buf++ = (Byte)(p->cache + high); + p->cache = (unsigned)(low >> 24); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + if (p->cacheSize == 0) + return; + } + high += 0xFF; + for (;;) + { + Byte *buf = p->buf; + *buf++ = (Byte)(high); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + if (--p->cacheSize == 0) + return; + } + } + p->cacheSize++; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); } + +#define RC_BIT_PRE(p, prob) \ + ttt = *(prob); \ + newBound = (range >> kNumBitModelTotalBits) * ttt; + +// #define _LZMA_ENC_USE_BRANCH + +#ifdef _LZMA_ENC_USE_BRANCH + +#define RC_BIT(p, prob, symbol) { \ + RC_BIT_PRE(p, prob) \ + if (symbol == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \ + else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \ + *(prob) = (CLzmaProb)ttt; \ + RC_NORM(p) \ + } + +#else + +#define RC_BIT(p, prob, symbol) { \ + UInt32 mask; \ + RC_BIT_PRE(p, prob) \ + mask = 0 - (UInt32)symbol; \ + range &= mask; \ + mask &= newBound; \ + range -= mask; \ + (p)->low += mask; \ + mask = (UInt32)symbol - 1; \ + range += newBound & mask; \ + mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \ + mask += ((1 << kNumMoveBits) - 1); \ + ttt += (Int32)(mask - ttt) >> kNumMoveBits; \ + *(prob) = (CLzmaProb)ttt; \ + RC_NORM(p) \ + } + +#endif + + + + +#define RC_BIT_0_BASE(p, prob) \ + range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); + +#define RC_BIT_1_BASE(p, prob) \ + range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \ + +#define RC_BIT_0(p, prob) \ + RC_BIT_0_BASE(p, prob) \ + RC_NORM(p) + +#define RC_BIT_1(p, prob) \ + RC_BIT_1_BASE(p, prob) \ + RC_NORM(p) + +static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob) +{ + UInt32 range, ttt, newBound; + range = p->range; + RC_BIT_PRE(p, prob) + RC_BIT_0(p, prob) + p->range = range; +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) +{ + UInt32 range = p->range; + symbol |= 0x100; + do + { + UInt32 ttt, newBound; + // RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); + CLzmaProb *prob = probs + (symbol >> 8); + UInt32 bit = (symbol >> 7) & 1; + symbol <<= 1; + RC_BIT(p, prob, bit); + } + while (symbol < 0x10000); + p->range = range; +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) +{ + UInt32 range = p->range; + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + UInt32 ttt, newBound; + CLzmaProb *prob; + UInt32 bit; + matchByte <<= 1; + // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); + prob = probs + (offs + (matchByte & offs) + (symbol >> 8)); + bit = (symbol >> 7) & 1; + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + RC_BIT(p, prob, bit); + } + while (symbol < 0x10000); + p->range = range; +} + + + +static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices) +{ + UInt32 i; + for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++) + { + const unsigned kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1)); + unsigned bitCount = 0; + unsigned j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + // printf("\n%3d: %5d", i, ProbPrices[i]); + } +} + + +#define GET_PRICE(prob, symbol) \ + p->ProbPrices[((prob) ^ (unsigned)(((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, symbol) \ + ProbPrices[((prob) ^ (unsigned)((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const CProbPrice *ProbPrices) +{ + UInt32 price = 0; + symbol |= 0x100; + do + { + unsigned bit = symbol & 1; + symbol >>= 1; + price += GET_PRICEa(probs[symbol], bit); + } + while (symbol >= 2); + return price; +} + + +static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const CProbPrice *ProbPrices) +{ + UInt32 price = 0; + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); + return price; +} + + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, UInt32 symbol) +{ + UInt32 range = rc->range; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + unsigned bit = symbol & 1; + // RangeEnc_EncodeBit(rc, probs + m, bit); + symbol >>= 1; + RC_BIT(rc, probs + m, bit); + m = (m << 1) | bit; + } + while (--numBits); + rc->range = range; +} + + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned symbol, unsigned posState) +{ + UInt32 range, ttt, newBound; + CLzmaProb *probs = p->low; + range = rc->range; + RC_BIT_PRE(rc, probs); + if (symbol >= kLenNumLowSymbols) + { + RC_BIT_1(rc, probs); + probs += kLenNumLowSymbols; + RC_BIT_PRE(rc, probs); + if (symbol >= kLenNumLowSymbols * 2) + { + RC_BIT_1(rc, probs); + rc->range = range; + // RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols * 2); + LitEnc_Encode(rc, p->high, symbol - kLenNumLowSymbols * 2); + return; + } + symbol -= kLenNumLowSymbols; + } + + // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, symbol); + { + unsigned m; + unsigned bit; + RC_BIT_0(rc, probs); + probs += (posState << (1 + kLenNumLowBits)); + bit = (symbol >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit; + bit = (symbol >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit; + bit = symbol & 1; RC_BIT(rc, probs + m, bit); + rc->range = range; + } +} + +static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices) +{ + unsigned i; + for (i = 0; i < 8; i += 2) + { + UInt32 price = startPrice; + UInt32 prob; + price += GET_PRICEa(probs[1 ], (i >> 2)); + price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1); + prob = probs[4 + (i >> 1)]; + prices[i ] = price + GET_PRICEa_0(prob); + prices[i + 1] = price + GET_PRICEa_1(prob); + } +} + + +MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTable( + CLenPriceEnc *p, unsigned posState, + const CLenEnc *enc, + const CProbPrice *ProbPrices) +{ + // int y; for (y = 0; y < 100; y++) { + UInt32 a; + unsigned i, numSymbols; + + UInt32 *prices = p->prices[posState]; + { + const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits)); + SetPrices_3(probs, GET_PRICEa_0(enc->low[0]), prices, ProbPrices); + a = GET_PRICEa_1(enc->low[0]); + SetPrices_3(probs + kLenNumLowSymbols, a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]), prices + kLenNumLowSymbols, ProbPrices); + a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]); + } + numSymbols = p->tableSize; + p->counters[posState] = numSymbols; + for (i = kLenNumLowSymbols * 2; i < numSymbols; i += 1) + { + prices[i] = a + + // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices); + LitEnc_GetPrice(enc->high, i - kLenNumLowSymbols * 2, ProbPrices); + /* + unsigned sym = (i - kLenNumLowSymbols * 2) >> 1; + UInt32 price = a + RcTree_GetPrice(enc->high, kLenNumHighBits - 1, sym, ProbPrices); + UInt32 prob = enc->high[(1 << 7) + sym]; + prices[i ] = price + GET_PRICEa_0(prob); + prices[i + 1] = price + GET_PRICEa_1(prob); + */ + } + // } +} + +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, unsigned numPosStates, + const CLenEnc *enc, + const CProbPrice *ProbPrices) +{ + unsigned posState; + for (posState = 0; posState < numPosStates; posState++) + LenPriceEnc_UpdateTable(p, posState, enc, ProbPrices); +} + + +/* + #ifdef SHOW_STAT + g_STAT_OFFSET += num; + printf("\n MovePos %u", num); + #endif +*/ + +#define MOVE_POS(p, num) { \ + p->additionalOffset += (num); \ + p->matchFinder.Skip(p->matchFinderObj, (num)); } + + +static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) +{ + unsigned numPairs; + + p->additionalOffset++; + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + *numPairsRes = numPairs; + + #ifdef SHOW_STAT + printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2); + g_STAT_OFFSET++; + { + unsigned i; + for (i = 0; i < numPairs; i += 2) + printf("%2u %6u | ", p->matches[i], p->matches[i + 1]); + } + #endif + + if (numPairs == 0) + return 0; + { + unsigned len = p->matches[(size_t)numPairs - 2]; + if (len != p->numFastBytes) + return len; + { + UInt32 numAvail = p->numAvail; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + { + const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + const Byte *p2 = p1 + len; + ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1]; + const Byte *lim = p1 + numAvail; + for (; p2 != lim && *p2 == p2[dif]; p2++); + return (unsigned)(p2 - p1); + } + } + } +} + +#define MARK_LIT ((UInt32)(Int32)-1) + +#define MakeAs_Lit(p) { (p)->dist = MARK_LIT; (p)->extra = 0; } +#define MakeAs_ShortRep(p) { (p)->dist = 0; (p)->extra = 0; } +#define IsShortRep(p) ((p)->dist == 0) + + +#define GetPrice_ShortRep(p, state, posState) \ + ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState])) + +#define GetPrice_Rep_0(p, state, posState) ( \ + GET_PRICE_1(p->isMatch[state][posState]) \ + + GET_PRICE_1(p->isRep0Long[state][posState])) \ + + GET_PRICE_1(p->isRep[state]) \ + + GET_PRICE_0(p->isRepG0[state]) + + +static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState) +{ + UInt32 price; + UInt32 prob = p->isRepG0[state]; + if (repIndex == 0) + { + price = GET_PRICE_0(prob); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(prob); + prob = p->isRepG1[state]; + if (repIndex == 1) + price += GET_PRICE_0(prob); + else + { + price += GET_PRICE_1(prob); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + + +static unsigned Backward(CLzmaEnc *p, unsigned cur) +{ + unsigned wr = cur + 1; + p->optEnd = wr; + + for (;;) + { + UInt32 dist = p->opt[cur].dist; + UInt32 len = p->opt[cur].len; + UInt32 extra = p->opt[cur].extra; + cur -= len; + + if (extra) + { + wr--; + p->opt[wr].len = len; + cur -= extra; + len = extra; + if (extra == 1) + { + p->opt[wr].dist = dist; + dist = MARK_LIT; + } + else + { + p->opt[wr].dist = 0; + len--; + wr--; + p->opt[wr].dist = MARK_LIT; + p->opt[wr].len = 1; + } + } + + if (cur == 0) + { + p->backRes = dist; + p->optCur = wr; + return len; + } + + wr--; + p->opt[wr].dist = dist; + p->opt[wr].len = len; + } +} + + + +#define LIT_PROBS(pos, prevByte) \ + (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc)) + + +static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) +{ + unsigned last, cur; + UInt32 reps[LZMA_NUM_REPS]; + unsigned repLens[LZMA_NUM_REPS]; + UInt32 *matches; + + { + UInt32 numAvail; + unsigned numPairs, mainLen, repMaxIndex, i, posState; + UInt32 matchPrice, repMatchPrice; + const Byte *data; + Byte curByte, matchByte; + + p->optCur = p->optEnd = 0; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLen; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + if (numAvail < 2) + { + p->backRes = MARK_LIT; + return 1; + } + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repMaxIndex = 0; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data - reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (len = 2; len < numAvail && data[len] == data2[len]; len++); + repLens[i] = len; + if (len > repLens[repMaxIndex]) + repMaxIndex = i; + } + + if (repLens[repMaxIndex] >= p->numFastBytes) + { + unsigned len; + p->backRes = repMaxIndex; + len = repLens[repMaxIndex]; + MOVE_POS(p, len - 1) + return len; + } + + matches = p->matches; + + if (mainLen >= p->numFastBytes) + { + p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS; + MOVE_POS(p, mainLen - 1) + return mainLen; + } + + curByte = *data; + matchByte = *(data - reps[0]); + + if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) + { + p->backRes = MARK_LIT; + return 1; + } + + p->opt[0].state = (CState)p->state; + + posState = (position & p->pbMask); + + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + + (!IsLitState(p->state) ? + LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + MakeAs_Lit(&p->opt[1]); + + matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); + + if (matchByte == curByte) + { + UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAs_ShortRep(&p->opt[1]); + } + } + + last = (mainLen >= repLens[repMaxIndex] ? mainLen : repLens[repMaxIndex]); + + if (last < 2) + { + p->backRes = p->opt[1].dist; + return 1; + } + + p->opt[1].len = 1; + + p->opt[0].reps[0] = reps[0]; + p->opt[0].reps[1] = reps[1]; + p->opt[0].reps[2] = reps[2]; + p->opt[0].reps[3] = reps[3]; + + { + unsigned len = last; + do + p->opt[len--].price = kInfinityPrice; + while (len >= 2); + } + + // ---------- REP ---------- + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState); + do + { + UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)repLen - 2]; + COptimal *opt = &p->opt[repLen]; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = repLen; + opt->dist = i; + opt->extra = 0; + } + } + while (--repLen >= 2); + } + + + // ---------- MATCH ---------- + { + unsigned len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= mainLen) + { + unsigned offs = 0; + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); + + while (len > matches[offs]) + offs += 2; + + for (; ; len++) + { + COptimal *opt; + UInt32 dist = matches[(size_t)offs + 1]; + UInt32 price2 = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN]; + unsigned lenToPosState = GetLenToPosState(len); + + if (dist < kNumFullDistances) + price2 += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)]; + else + { + unsigned slot; + GetPosSlot2(dist, slot); + price2 += p->alignPrices[dist & kAlignMask]; + price2 += p->posSlotPrices[lenToPosState][slot]; + } + + opt = &p->opt[len]; + + if (price2 < opt->price) + { + opt->price = price2; + opt->len = len; + opt->dist = dist + LZMA_NUM_REPS; + opt->extra = 0; + } + + if (len == matches[offs]) + { + offs += 2; + if (offs == numPairs) + break; + } + } + } + } + + + cur = 0; + + #ifdef SHOW_STAT2 + /* if (position >= 0) */ + { + unsigned i; + printf("\n pos = %4X", position); + for (i = cur; i <= last; i++) + printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price); + } + #endif + } + + + + // ---------- Optimal Parsing ---------- + + for (;;) + { + UInt32 numAvail, numAvailFull; + unsigned newLen, numPairs, prev, state, posState, startLen; + UInt32 curPrice, litPrice, matchPrice, repMatchPrice; + Bool nextIsLit; + Byte curByte, matchByte; + const Byte *data; + COptimal *curOpt, *nextOpt; + + if (++cur == last) + return Backward(p, cur); + + newLen = ReadMatchDistances(p, &numPairs); + + if (newLen >= p->numFastBytes) + { + p->numPairs = numPairs; + p->longestMatchLen = newLen; + return Backward(p, cur); + } + + curOpt = &p->opt[cur]; + prev = cur - curOpt->len; + + if (curOpt->len == 1) + { + state = p->opt[prev].state; + if (IsShortRep(curOpt)) + state = kShortRepNextStates[state]; + else + state = kLiteralNextStates[state]; + } + else + { + const COptimal *prevOpt; + UInt32 b0; + UInt32 dist = curOpt->dist; + + if (curOpt->extra) + { + prev -= curOpt->extra; + state = kState_RepAfterLit; + if (curOpt->extra == 1) + state = (dist < LZMA_NUM_REPS) ? kState_RepAfterLit : kState_MatchAfterLit; + } + else + { + state = p->opt[prev].state; + if (dist < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + + prevOpt = &p->opt[prev]; + b0 = prevOpt->reps[0]; + + if (dist < LZMA_NUM_REPS) + { + if (dist == 0) + { + reps[0] = b0; + reps[1] = prevOpt->reps[1]; + reps[2] = prevOpt->reps[2]; + reps[3] = prevOpt->reps[3]; + } + else + { + reps[1] = b0; + b0 = prevOpt->reps[1]; + if (dist == 1) + { + reps[0] = b0; + reps[2] = prevOpt->reps[2]; + reps[3] = prevOpt->reps[3]; + } + else + { + reps[2] = b0; + reps[0] = prevOpt->reps[dist]; + reps[3] = prevOpt->reps[dist ^ 1]; + } + } + } + else + { + reps[0] = (dist - LZMA_NUM_REPS + 1); + reps[1] = b0; + reps[2] = prevOpt->reps[1]; + reps[3] = prevOpt->reps[2]; + } + } + + curOpt->state = (CState)state; + curOpt->reps[0] = reps[0]; + curOpt->reps[1] = reps[1]; + curOpt->reps[2] = reps[2]; + curOpt->reps[3] = reps[3]; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + curByte = *data; + matchByte = *(data - reps[0]); + + position++; + posState = (position & p->pbMask); + + /* + The order of Price checks: + < LIT + <= SHORT_REP + < LIT : REP_0 + < REP [ : LIT : REP_0 ] + < MATCH [ : LIT : REP_0 ] + */ + + curPrice = curOpt->price; + litPrice = curPrice + GET_PRICE_0(p->isMatch[state][posState]); + + nextOpt = &p->opt[(size_t)cur + 1]; + nextIsLit = False; + + // if (litPrice >= nextOpt->price) litPrice = 0; else // 18.new + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + litPrice += (!IsLitState(state) ? + LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + + if (litPrice < nextOpt->price) + { + nextOpt->price = litPrice; + nextOpt->len = 1; + MakeAs_Lit(nextOpt); + nextIsLit = True; + } + } + + matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + // ---------- SHORT_REP ---------- + // if (IsLitState(state)) // 18.new + if (matchByte == curByte) + // if (repMatchPrice < nextOpt->price) // 18.new + if (nextOpt->len < 2 + || (nextOpt->dist != 0 + && nextOpt->extra <= 1 // 17.old + )) + { + UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState); + if (shortRepPrice <= nextOpt->price) // 17.old + // if (shortRepPrice < nextOpt->price) // 18.new + { + nextOpt->price = shortRepPrice; + nextOpt->len = 1; + MakeAs_ShortRep(nextOpt); + nextIsLit = False; + } + } + + numAvailFull = p->numAvail; + { + UInt32 temp = kNumOpts - 1 - cur; + if (numAvailFull > temp) + numAvailFull = temp; + } + + if (numAvailFull < 2) + continue; + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); + + // numAvail <= p->numFastBytes + + // ---------- LIT : REP_0 ---------- + + if ( + // litPrice != 0 && // 18.new + !nextIsLit + && matchByte != curByte + && numAvailFull > 2) + { + const Byte *data2 = data - reps[0]; + if (data[1] == data2[1] && data[2] == data2[2]) + { + unsigned len; + unsigned limit = p->numFastBytes + 1; + if (limit > numAvailFull) + limit = numAvailFull; + for (len = 3; len < limit && data[len] == data2[len]; len++); + + { + unsigned state2 = kLiteralNextStates[state]; + unsigned posState2 = (position + 1) & p->pbMask; + UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2); + { + unsigned offset = cur + len; + while (last < offset) + p->opt[++last].price = kInfinityPrice; + + // do + { + UInt32 price2; + COptimal *opt; + len--; + // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2); + price2 = price + p->repLenEnc.prices[posState2][len - LZMA_MATCH_LEN_MIN]; + + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = len; + opt->dist = 0; + opt->extra = 1; + } + } + // while (len >= 3); + } + } + } + } + + startLen = 2; /* speed optimization */ + { + // ---------- REP ---------- + unsigned repIndex = 0; // 17.old + // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused + for (; repIndex < LZMA_NUM_REPS; repIndex++) + { + unsigned len; + UInt32 price; + const Byte *data2 = data - reps[repIndex]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + + for (len = 2; len < numAvail && data[len] == data2[len]; len++); + + // if (len < startLen) continue; // 18.new: speed optimization + + while (last < cur + len) + p->opt[++last].price = kInfinityPrice; + { + unsigned len2 = len; + price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState); + do + { + UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)len2 - 2]; + COptimal *opt = &p->opt[cur + len2]; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = len2; + opt->dist = repIndex; + opt->extra = 0; + } + } + while (--len2 >= 2); + } + + if (repIndex == 0) startLen = len + 1; // 17.old + // startLen = len + 1; // 18.new + + /* if (_maxMode) */ + { + // ---------- REP : LIT : REP_0 ---------- + // numFastBytes + 1 + numFastBytes + + unsigned len2 = len + 1; + unsigned limit = len2 + p->numFastBytes; + if (limit > numAvailFull) + limit = numAvailFull; + + for (; len2 < limit && data[len2] == data2[len2]; len2++); + + len2 -= len; + if (len2 >= 3) + { + unsigned state2 = kRepNextStates[state]; + unsigned posState2 = (position + len) & p->pbMask; + price += + p->repLenEnc.prices[posState][(size_t)len - 2] + + GET_PRICE_0(p->isMatch[state2][posState2]) + + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]), + data[len], data2[len], p->ProbPrices); + + // state2 = kLiteralNextStates[state2]; + state2 = kState_LitAfterRep; + posState2 = (posState2 + 1) & p->pbMask; + + + price += GetPrice_Rep_0(p, state2, posState2); + { + unsigned offset = cur + len + len2; + while (last < offset) + p->opt[++last].price = kInfinityPrice; + // do + { + unsigned price2; + COptimal *opt; + len2--; + // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2); + price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN]; + + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = len2; + opt->extra = (CExtra)(len + 1); + opt->dist = repIndex; + } + } + // while (len2 >= 3); + } + } + } + } + } + + + // ---------- MATCH ---------- + /* for (unsigned len = 2; len <= newLen; len++) */ + if (newLen > numAvail) + { + newLen = numAvail; + for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); + matches[numPairs] = newLen; + numPairs += 2; + } + + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); + UInt32 dist; + unsigned offs, posSlot, len; + while (last < cur + newLen) + p->opt[++last].price = kInfinityPrice; + + offs = 0; + while (startLen > matches[offs]) + offs += 2; + dist = matches[(size_t)offs + 1]; + + // if (dist >= kNumFullDistances) + GetPosSlot2(dist, posSlot); + + for (len = /*2*/ startLen; ; len++) + { + UInt32 price = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN]; + { + COptimal *opt; + unsigned lenToPosState = len - 2; lenToPosState = GetLenToPosState2(lenToPosState); + if (dist < kNumFullDistances) + price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)]; + else + price += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[dist & kAlignMask]; + + opt = &p->opt[cur + len]; + if (price < opt->price) + { + opt->price = price; + opt->len = len; + opt->dist = dist + LZMA_NUM_REPS; + opt->extra = 0; + } + } + + if (/*_maxMode && */ len == matches[offs]) + { + // MATCH : LIT : REP_0 + + const Byte *data2 = data - dist - 1; + unsigned len2 = len + 1; + unsigned limit = len2 + p->numFastBytes; + if (limit > numAvailFull) + limit = numAvailFull; + + for (; len2 < limit && data[len2] == data2[len2]; len2++); + + len2 -= len; + + if (len2 >= 3) + { + unsigned state2 = kMatchNextStates[state]; + unsigned posState2 = (position + len) & p->pbMask; + unsigned offset; + price += GET_PRICE_0(p->isMatch[state2][posState2]); + price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]), + data[len], data2[len], p->ProbPrices); + + // state2 = kLiteralNextStates[state2]; + state2 = kState_LitAfterMatch; + + posState2 = (posState2 + 1) & p->pbMask; + price += GetPrice_Rep_0(p, state2, posState2); + + offset = cur + len + len2; + while (last < offset) + p->opt[++last].price = kInfinityPrice; + // do + { + UInt32 price2; + COptimal *opt; + len2--; + // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2); + price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN]; + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = len2; + opt->extra = (CExtra)(len + 1); + opt->dist = dist + LZMA_NUM_REPS; + } + } + // while (len2 >= 3); + } + + offs += 2; + if (offs == numPairs) + break; + dist = matches[(size_t)offs + 1]; + // if (dist >= kNumFullDistances) + GetPosSlot2(dist, posSlot); + } + } + } + } +} + + + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + + + +static unsigned GetOptimumFast(CLzmaEnc *p) +{ + UInt32 numAvail, mainDist; + unsigned mainLen, numPairs, repIndex, repLen, i; + const Byte *data; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLen; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + p->backRes = MARK_LIT; + if (numAvail < 2) + return 1; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repLen = repIndex = 0; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len; + const Byte *data2 = data - p->reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (len = 2; len < numAvail && data[len] == data2[len]; len++); + if (len >= p->numFastBytes) + { + p->backRes = i; + MOVE_POS(p, len - 1) + return len; + } + if (len > repLen) + { + repIndex = i; + repLen = len; + } + } + + if (mainLen >= p->numFastBytes) + { + p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS; + MOVE_POS(p, mainLen - 1) + return mainLen; + } + + mainDist = 0; /* for GCC */ + + if (mainLen >= 2) + { + mainDist = p->matches[(size_t)numPairs - 1]; + while (numPairs > 2) + { + UInt32 dist2; + if (mainLen != p->matches[(size_t)numPairs - 4] + 1) + break; + dist2 = p->matches[(size_t)numPairs - 3]; + if (!ChangePair(dist2, mainDist)) + break; + numPairs -= 2; + mainLen--; + mainDist = dist2; + } + if (mainLen == 2 && mainDist >= 0x80) + mainLen = 1; + } + + if (repLen >= 2) + if ( repLen + 1 >= mainLen + || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) + || (repLen + 3 >= mainLen && mainDist >= (1 << 15))) + { + p->backRes = repIndex; + MOVE_POS(p, repLen - 1) + return repLen; + } + + if (mainLen < 2 || numAvail <= 2) + return 1; + + { + unsigned len1 = ReadMatchDistances(p, &p->numPairs); + p->longestMatchLen = len1; + + if (len1 >= 2) + { + UInt32 newDist = p->matches[(size_t)p->numPairs - 1]; + if ( (len1 >= mainLen && newDist < mainDist) + || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist)) + || (len1 > mainLen + 1) + || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist))) + return 1; + } + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len, limit; + const Byte *data2 = data - p->reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + limit = mainLen - 1; + for (len = 2;; len++) + { + if (len >= limit) + return 1; + if (data[len] != data2[len]) + break; + } + } + + p->backRes = mainDist + LZMA_NUM_REPS; + if (mainLen != 2) + { + MOVE_POS(p, mainLen - 2) + } + return mainLen; +} + + + + +static void WriteEndMarker(CLzmaEnc *p, unsigned posState) +{ + UInt32 range; + range = p->rc.range; + { + UInt32 ttt, newBound; + CLzmaProb *prob = &p->isMatch[p->state][posState]; + RC_BIT_PRE(&p->rc, prob) + RC_BIT_1(&p->rc, prob) + prob = &p->isRep[p->state]; + RC_BIT_PRE(&p->rc, prob) + RC_BIT_0(&p->rc, prob) + } + p->state = kMatchNextStates[p->state]; + + p->rc.range = range; + LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState); + range = p->rc.range; + + { + // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1); + CLzmaProb *probs = p->posSlotEncoder[0]; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + RC_BIT_PRE(p, probs + m) + RC_BIT_1(&p->rc, probs + m); + m = (m << 1) + 1; + } + while (m < (1 << kNumPosSlotBits)); + } + { + // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits); UInt32 range = p->range; + unsigned numBits = 30 - kNumAlignBits; + do + { + range >>= 1; + p->rc.low += range; + RC_NORM(&p->rc) + } + while (--numBits); + } + + { + // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); + CLzmaProb *probs = p->posAlignEncoder; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + RC_BIT_PRE(p, probs + m) + RC_BIT_1(&p->rc, probs + m); + m = (m << 1) + 1; + } + while (m < kAlignTableSize); + } + p->rc.range = range; +} + + +static SRes CheckErrors(CLzmaEnc *p) +{ + if (p->result != SZ_OK) + return p->result; + if (p->rc.res != SZ_OK) + p->result = SZ_ERROR_WRITE; + if (p->matchFinderBase.result != SZ_OK) + p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) + p->finished = True; + return p->result; +} + + +MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +{ + /* ReleaseMFStream(); */ + p->finished = True; + if (p->writeEndMark) + WriteEndMarker(p, nowPos & p->pbMask); + RangeEnc_FlushData(&p->rc); + RangeEnc_FlushStream(&p->rc); + return CheckErrors(p); +} + + + +static void FillAlignPrices(CLzmaEnc *p) +{ + unsigned i; + const CProbPrice *ProbPrices = p->ProbPrices; + const CLzmaProb *probs = p->posAlignEncoder; + p->alignPriceCount = 0; + for (i = 0; i < kAlignTableSize / 2; i++) + { + UInt32 price = 0; + unsigned symbol = i; + unsigned m = 1; + unsigned bit; + UInt32 prob; + bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + prob = probs[m]; + p->alignPrices[i ] = price + GET_PRICEa_0(prob); + p->alignPrices[i + 8] = price + GET_PRICEa_1(prob); + // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + } +} + + +static void FillDistancesPrices(CLzmaEnc *p) +{ + UInt32 tempPrices[kNumFullDistances]; + unsigned i, lenToPosState; + + const CProbPrice *ProbPrices = p->ProbPrices; + p->matchPriceCount = 0; + + for (i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + unsigned posSlot = GetPosSlot1(i); + unsigned footerBits = ((posSlot >> 1) - 1); + unsigned base = ((2 | (posSlot & 1)) << footerBits); + // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices); + + const CLzmaProb *probs = p->posEncoders + base; + UInt32 price = 0; + unsigned m = 1; + unsigned symbol = i - base; + do + { + unsigned bit = symbol & 1; + symbol >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) + bit; + } + while (--footerBits); + tempPrices[i] = price; + } + + for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + unsigned posSlot; + const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; + unsigned distTableSize = p->distTableSize; + const CLzmaProb *probs = encoder; + for (posSlot = 0; posSlot < distTableSize; posSlot += 2) + { + // posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); + UInt32 price = 0; + unsigned bit; + unsigned symbol = (posSlot >> 1) + (1 << (kNumPosSlotBits - 1)); + UInt32 prob; + bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit); + bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit); + bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit); + bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit); + bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit); + prob = probs[(posSlot >> 1) + (1 << (kNumPosSlotBits - 1))]; + posSlotPrices[posSlot ] = price + GET_PRICEa_0(prob); + posSlotPrices[posSlot + 1] = price + GET_PRICEa_1(prob); + } + for (posSlot = kEndPosModelIndex; posSlot < distTableSize; posSlot++) + posSlotPrices[posSlot] += ((UInt32)(((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + + { + UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; + { + distancesPrices[0] = posSlotPrices[0]; + distancesPrices[1] = posSlotPrices[1]; + distancesPrices[2] = posSlotPrices[2]; + distancesPrices[3] = posSlotPrices[3]; + } + for (i = 4; i < kNumFullDistances; i += 2) + { + UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)]; + distancesPrices[i ] = slotPrice + tempPrices[i]; + distancesPrices[i + 1] = slotPrice + tempPrices[i + 1]; + } + } + } +} + + + +void LzmaEnc_Construct(CLzmaEnc *p) +{ + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&p->matchFinderBase); + + #ifndef _7ZIP_ST + MatchFinderMt_Construct(&p->matchFinderMt); + p->matchFinderMt.MatchFinder = &p->matchFinderBase; + #endif + + { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + LzmaEnc_SetProps(p, &props); + } + + #ifndef LZMA_LOG_BSR + LzmaEnc_FastPosInit(p->g_FastPos); + #endif + + LzmaEnc_InitPriceTables(p->ProbPrices); + p->litProbs = NULL; + p->saveState.litProbs = NULL; + +} + +CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) +{ + void *p; + p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc)); + if (p) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->litProbs); + ISzAlloc_Free(alloc, p->saveState.litProbs); + p->litProbs = NULL; + p->saveState.litProbs = NULL; +} + +void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + #ifndef _7ZIP_ST + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + + MatchFinder_Free(&p->matchFinderBase, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + ISzAlloc_Free(alloc, p); +} + + +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize) +{ + UInt32 nowPos32, startPos32; + if (p->needInit) + { + p->matchFinder.Init(p->matchFinderObj); + p->needInit = 0; + } + + if (p->finished) + return p->result; + RINOK(CheckErrors(p)); + + nowPos32 = (UInt32)p->nowPos64; + startPos32 = nowPos32; + + if (p->nowPos64 == 0) + { + unsigned numPairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numPairs); + RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]); + // p->state = kLiteralNextStates[p->state]; + curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset); + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + + for (;;) + { + UInt32 dist; + unsigned len, posState; + UInt32 range, ttt, newBound; + CLzmaProb *probs; + + if (p->fastMode) + len = GetOptimumFast(p); + else + { + unsigned oci = p->optCur; + if (p->optEnd == oci) + len = GetOptimum(p, nowPos32); + else + { + const COptimal *opt = &p->opt[oci]; + len = opt->len; + p->backRes = opt->dist; + p->optCur = oci + 1; + } + } + + posState = (unsigned)nowPos32 & p->pbMask; + range = p->rc.range; + probs = &p->isMatch[p->state][posState]; + + RC_BIT_PRE(&p->rc, probs) + + dist = p->backRes; + + #ifdef SHOW_STAT2 + printf("\n pos = %6X, len = %3u pos = %6u", nowPos32, len, dist); + #endif + + if (dist == MARK_LIT) + { + Byte curByte; + const Byte *data; + unsigned state; + + RC_BIT_0(&p->rc, probs); + p->rc.range = range; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + probs = LIT_PROBS(nowPos32, *(data - 1)); + curByte = *data; + state = p->state; + p->state = kLiteralNextStates[state]; + if (IsLitState(state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0])); + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRep[p->state]; + RC_BIT_PRE(&p->rc, probs) + + if (dist < LZMA_NUM_REPS) + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG0[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 0) + { + RC_BIT_0(&p->rc, probs); + probs = &p->isRep0Long[p->state][posState]; + RC_BIT_PRE(&p->rc, probs) + if (len != 1) + { + RC_BIT_1_BASE(&p->rc, probs); + } + else + { + RC_BIT_0_BASE(&p->rc, probs); + p->state = kShortRepNextStates[p->state]; + } + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG1[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 1) + { + RC_BIT_0_BASE(&p->rc, probs); + dist = p->reps[1]; + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG2[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 2) + { + RC_BIT_0_BASE(&p->rc, probs); + dist = p->reps[2]; + } + else + { + RC_BIT_1_BASE(&p->rc, probs); + dist = p->reps[3]; + p->reps[3] = p->reps[2]; + } + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = dist; + } + + RC_NORM(&p->rc) + + p->rc.range = range; + + if (len != 1) + { + LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState); + if (!p->fastMode) + if (--p->repLenEnc.counters[posState] == 0) + LenPriceEnc_UpdateTable(&p->repLenEnc, posState, &p->repLenProbs, p->ProbPrices); + + p->state = kRepNextStates[p->state]; + } + } + else + { + unsigned posSlot; + RC_BIT_0(&p->rc, probs); + p->rc.range = range; + p->state = kMatchNextStates[p->state]; + + LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState); + if (!p->fastMode) + if (--p->lenEnc.counters[posState] == 0) + LenPriceEnc_UpdateTable(&p->lenEnc, posState, &p->lenProbs, p->ProbPrices); + + dist -= LZMA_NUM_REPS; + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = dist + 1; + + p->matchPriceCount++; + GetPosSlot(dist, posSlot); + // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot); + { + UInt32 symbol = posSlot + (1 << kNumPosSlotBits); + range = p->rc.range; + probs = p->posSlotEncoder[GetLenToPosState(len)]; + do + { + CLzmaProb *prob = probs + (symbol >> kNumPosSlotBits); + UInt32 bit = (symbol >> (kNumPosSlotBits - 1)) & 1; + symbol <<= 1; + RC_BIT(&p->rc, prob, bit); + } + while (symbol < (1 << kNumPosSlotBits * 2)); + p->rc.range = range; + } + + if (dist >= kStartPosModelIndex) + { + unsigned footerBits = ((posSlot >> 1) - 1); + + if (dist < kNumFullDistances) + { + unsigned base = ((2 | (posSlot & 1)) << footerBits); + RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, dist - base); + } + else + { + UInt32 pos2 = (dist | 0xF) << (32 - footerBits); + range = p->rc.range; + // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + /* + do + { + range >>= 1; + p->rc.low += range & (0 - ((dist >> --footerBits) & 1)); + RC_NORM(&p->rc) + } + while (footerBits > kNumAlignBits); + */ + do + { + range >>= 1; + p->rc.low += range & (0 - (pos2 >> 31)); + pos2 += pos2; + RC_NORM(&p->rc) + } + while (pos2 != 0xF0000000); + + + // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + + { + unsigned m = 1; + unsigned bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); + p->rc.range = range; + p->alignPriceCount++; + } + } + } + } + } + + nowPos32 += len; + p->additionalOffset -= len; + + if (p->additionalOffset == 0) + { + UInt32 processed; + + if (!p->fastMode) + { + if (p->matchPriceCount >= (1 << 7)) + FillDistancesPrices(p); + if (p->alignPriceCount >= kAlignTableSize) + FillAlignPrices(p); + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + break; + processed = nowPos32 - startPos32; + + if (maxPackSize) + { + if (processed + kNumOpts + 300 >= maxUnpackSize + || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize) + break; + } + else if (processed >= (1 << 17)) + { + p->nowPos64 += nowPos32 - startPos32; + return CheckErrors(p); + } + } + } + + p->nowPos64 += nowPos32 - startPos32; + return Flush(p, nowPos32); +} + + + +#define kBigHashDicLimit ((UInt32)1 << 24) + +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + UInt32 beforeSize = kNumOpts; + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; + + #ifndef _7ZIP_ST + p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0)); + #endif + + { + unsigned lclp = p->lc + p->lp; + if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); + p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); + if (!p->litProbs || !p->saveState.litProbs) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0); + + if (beforeSize + p->dictSize < keepWindowSize) + beforeSize = keepWindowSize - p->dictSize; + + #ifndef _7ZIP_ST + if (p->mtMode) + { + RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, + LZMA_MATCH_LEN_MAX + + 1 /* 18.04 */ + , allocBig)); + p->matchFinderObj = &p->matchFinderMt; + p->matchFinderBase.bigHash = (Byte)( + (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0); + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); + } + else + #endif + { + if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + return SZ_ERROR_MEM; + p->matchFinderObj = &p->matchFinderBase; + MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + } + + return SZ_OK; +} + +void LzmaEnc_Init(CLzmaEnc *p) +{ + unsigned i; + p->state = 0; + p->reps[0] = + p->reps[1] = + p->reps[2] = + p->reps[3] = 1; + + RangeEnc_Init(&p->rc); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + for (i = 0; i < kNumStates; i++) + { + unsigned j; + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) + { + p->isMatch[i][j] = kProbInitValue; + p->isRep0Long[i][j] = kProbInitValue; + } + p->isRep[i] = kProbInitValue; + p->isRepG0[i] = kProbInitValue; + p->isRepG1[i] = kProbInitValue; + p->isRepG2[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + unsigned j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for (i = 0; i < kNumFullDistances; i++) + p->posEncoders[i] = kProbInitValue; + } + + { + UInt32 num = (UInt32)0x300 << (p->lp + p->lc); + UInt32 k; + CLzmaProb *probs = p->litProbs; + for (k = 0; k < num; k++) + probs[k] = kProbInitValue; + } + + + LenEnc_Init(&p->lenProbs); + LenEnc_Init(&p->repLenProbs); + + p->optEnd = 0; + p->optCur = 0; + p->additionalOffset = 0; + + p->pbMask = (1 << p->pb) - 1; + p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc); +} + +void LzmaEnc_InitPrices(CLzmaEnc *p) +{ + if (!p->fastMode) + { + FillDistancesPrices(p); + FillAlignPrices(p); + } + + p->lenEnc.tableSize = + p->repLenEnc.tableSize = + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices); +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + unsigned i; + for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++) + if (p->dictSize <= ((UInt32)1 << i)) + break; + p->distTableSize = i * 2; + + p->finished = False; + p->result = SZ_OK; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + p->nowPos64 = 0; + return SZ_OK; +} + +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->matchFinderBase.stream = inStream; + p->needInit = 1; + p->rc.outStream = outStream; + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +} + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, + ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->matchFinderBase.stream = inStream; + p->needInit = 1; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +{ + p->matchFinderBase.directInput = 1; + p->matchFinderBase.bufferBase = (Byte *)src; + p->matchFinderBase.directInputRem = srcLen; +} + +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + LzmaEnc_SetInputBuf(p, src, srcLen); + p->needInit = 1; + + LzmaEnc_SetDataSize(pp, srcLen); + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +void LzmaEnc_Finish(CLzmaEncHandle pp) +{ + #ifndef _7ZIP_ST + CLzmaEnc *p = (CLzmaEnc *)pp; + if (p->mtMode) + MatchFinderMt_ReleaseStream(&p->matchFinderMt); + #else + UNUSED_VAR(pp); + #endif +} + + +typedef struct +{ + ISeqOutStream vt; + Byte *data; + SizeT rem; + Bool overflow; +} CLzmaEnc_SeqOutStreamBuf; + +static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size) +{ + CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt); + if (p->rem < size) + { + size = p->rem; + p->overflow = True; + } + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + return size; +} + + +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +} + + +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +} + + +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + UInt64 nowPos64; + SRes res; + CLzmaEnc_SeqOutStreamBuf outStream; + + outStream.vt.Write = SeqOutStreamBuf_Write; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = False; + p->finished = False; + p->result = SZ_OK; + + if (reInit) + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + + nowPos64 = p->nowPos64; + RangeEnc_Init(&p->rc); + p->rc.outStream = &outStream.vt; + + if (desiredPackSize == 0) + return SZ_ERROR_OUTPUT_EOF; + + res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize); + + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + + return res; +} + + +static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) +{ + SRes res = SZ_OK; + + #ifndef _7ZIP_ST + Byte allocaDummy[0x300]; + allocaDummy[0] = 0; + allocaDummy[1] = allocaDummy[0]; + #endif + + for (;;) + { + res = LzmaEnc_CodeOneBlock(p, 0, 0); + if (res != SZ_OK || p->finished) + break; + if (progress) + { + res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + + LzmaEnc_Finish(p); + + /* + if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase)) + res = SZ_ERROR_FAIL; + } + */ + + return res; +} + + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); + return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); +} + + +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + unsigned i; + UInt32 dictSize = p->dictSize; + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + if (dictSize >= ((UInt32)1 << 22)) + { + UInt32 kDictMask = ((UInt32)1 << 20) - 1; + if (dictSize < (UInt32)0xFFFFFFFF - kDictMask) + dictSize = (dictSize + kDictMask) & ~kDictMask; + } + else for (i = 11; i <= 30; i++) + { + if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } + if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } + } + + for (i = 0; i < 4; i++) + props[1 + i] = (Byte)(dictSize >> (8 * i)); + return SZ_OK; +} + + +unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp) +{ + return ((CLzmaEnc *)pp)->writeEndMark; +} + + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CLzmaEnc_SeqOutStreamBuf outStream; + + outStream.vt.Write = SeqOutStreamBuf_Write; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + p->rc.outStream = &outStream.vt; + + res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); + + if (res == SZ_OK) + { + res = LzmaEnc_Encode2(p, progress); + if (res == SZ_OK && p->nowPos64 != srcLen) + res = SZ_ERROR_FAIL; + } + + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + return res; +} + + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (!p) + return SZ_ERROR_MEM; + + res = LzmaEnc_SetProps(p, props); + if (res == SZ_OK) + { + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); + if (res == SZ_OK) + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, + writeEndMark, progress, alloc, allocBig); + } + + LzmaEnc_Destroy(p, alloc, allocBig); + return res; +} diff --git a/other-licenses/7zstub/src/C/LzmaEnc.h b/other-licenses/7zstub/src/C/LzmaEnc.h new file mode 100644 index 0000000000..c9938f04bc --- /dev/null +++ b/other-licenses/7zstub/src/C/LzmaEnc.h @@ -0,0 +1,76 @@ +/* LzmaEnc.h -- LZMA Encoder +2017-07-27 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaEncProps +{ + int level; /* 0 <= level <= 9 */ + UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version + (1 << 12) <= dictSize <= (3 << 29) for 64-bit version + default = (1 << 24) */ + int lc; /* 0 <= lc <= 8, default = 3 */ + int lp; /* 0 <= lp <= 4, default = 0 */ + int pb; /* 0 <= pb <= 4, default = 2 */ + int algo; /* 0 - fast, 1 - normal, default = 1 */ + int fb; /* 5 <= fb <= 273, default = 32 */ + int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ + int numHashBytes; /* 2, 3 or 4, default = 4 */ + UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ + unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ + int numThreads; /* 1 or 2, default = 2 */ + + UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. + Encoder uses this value to reduce dictionary size */ +} CLzmaEncProps; + +void LzmaEncProps_Init(CLzmaEncProps *p); +void LzmaEncProps_Normalize(CLzmaEncProps *p); +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); + + +/* ---------- CLzmaEncHandle Interface ---------- */ + +/* LzmaEnc* functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef void * CLzmaEncHandle; + +CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc); +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig); + +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize); +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p); + +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); + + +/* ---------- One Call Interface ---------- */ + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/LzmaLib.c b/other-licenses/7zstub/src/C/LzmaLib.c new file mode 100644 index 0000000000..c10cf1a0f2 --- /dev/null +++ b/other-licenses/7zstub/src/C/LzmaLib.c @@ -0,0 +1,40 @@ +/* LzmaLib.c -- LZMA library wrapper +2015-06-13 : Igor Pavlov : Public domain */ + +#include "Alloc.h" +#include "LzmaDec.h" +#include "LzmaEnc.h" +#include "LzmaLib.h" + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads /* 1 or 2, default = 2 */ +) +{ + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + props.lc = lc; + props.lp = lp; + props.pb = pb; + props.fb = fb; + props.numThreads = numThreads; + + return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); +} + + +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, + const unsigned char *props, size_t propsSize) +{ + ELzmaStatus status; + return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); +} diff --git a/other-licenses/7zstub/src/C/LzmaLib.h b/other-licenses/7zstub/src/C/LzmaLib.h new file mode 100644 index 0000000000..5c35e53654 --- /dev/null +++ b/other-licenses/7zstub/src/C/LzmaLib.h @@ -0,0 +1,131 @@ +/* LzmaLib.h -- LZMA library interface +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_LIB_H +#define __LZMA_LIB_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define MY_STDAPI int MY_STD_CALL + +#define LZMA_PROPS_SIZE 5 + +/* +RAM requirements for LZMA: + for compression: (dictSize * 11.5 + 6 MB) + state_size + for decompression: dictSize + state_size + state_size = (4 + (1.5 << (lc + lp))) KB + by default (lc=3, lp=0), state_size = 16 KB. + +LZMA properties (5 bytes) format + Offset Size Description + 0 1 lc, lp and pb in encoded form. + 1 4 dictSize (little endian). +*/ + +/* +LzmaCompress +------------ + +outPropsSize - + In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + + LZMA Encoder will use defult values for any parameter, if it is + -1 for any from: level, loc, lp, pb, fb, numThreads + 0 for dictSize + +level - compression level: 0 <= level <= 9; + + level dictSize algo fb + 0: 16 KB 0 32 + 1: 64 KB 0 32 + 2: 256 KB 0 32 + 3: 1 MB 0 32 + 4: 4 MB 0 32 + 5: 16 MB 1 32 + 6: 32 MB 1 32 + 7+: 64 MB 1 64 + + The default value for "level" is 5. + + algo = 0 means fast method + algo = 1 means normal method + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + +lc - The number of literal context bits (high bits of previous literal). + It can be in the range from 0 to 8. The default value is 3. + Sometimes lc=4 gives the gain for big files. + +lp - The number of literal pos bits (low bits of current position for literals). + It can be in the range from 0 to 4. The default value is 0. + The lp switch is intended for periodical data when the period is equal to 2^lp. + For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's + better to set lc=0, if you change lp switch. + +pb - The number of pos bits (low bits of current position). + It can be in the range from 0 to 4. The default value is 2. + The pb switch is intended for periodical data when the period is equal 2^pb. + +fb - Word size (the number of fast bytes). + It can be in the range from 5 to 273. The default value is 32. + Usually, a big number gives a little bit better compression ratio and + slower compression process. + +numThreads - The number of thereads. 1 or 2. The default value is 2. + Fast mode (algo = 0) can use only 1 thread. + +Out: + destLen - processed output size +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* default = (1 << 24) */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads /* 1 or 2, default = 2 */ + ); + +/* +LzmaUncompress +-------------- +In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size +Out: + destLen - processed output size + srcLen - processed input size +Returns: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation arror + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) +*/ + +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, + const unsigned char *props, size_t propsSize); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/MtCoder.c b/other-licenses/7zstub/src/C/MtCoder.c new file mode 100644 index 0000000000..ddc7c02858 --- /dev/null +++ b/other-licenses/7zstub/src/C/MtCoder.c @@ -0,0 +1,601 @@ +/* MtCoder.c -- Multi-thread Coder +2018-02-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "MtCoder.h" + +#ifndef _7ZIP_ST + +SRes MtProgressThunk_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) +{ + CMtProgressThunk *thunk = CONTAINER_FROM_VTBL(pp, CMtProgressThunk, vt); + UInt64 inSize2 = 0; + UInt64 outSize2 = 0; + if (inSize != (UInt64)(Int64)-1) + { + inSize2 = inSize - thunk->inSize; + thunk->inSize = inSize; + } + if (outSize != (UInt64)(Int64)-1) + { + outSize2 = outSize - thunk->outSize; + thunk->outSize = outSize; + } + return MtProgress_ProgressAdd(thunk->mtProgress, inSize2, outSize2); +} + + +void MtProgressThunk_CreateVTable(CMtProgressThunk *p) +{ + p->vt.Progress = MtProgressThunk_Progress; +} + + + +#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } + + +static WRes ArEvent_OptCreate_And_Reset(CEvent *p) +{ + if (Event_IsCreated(p)) + return Event_Reset(p); + return AutoResetEvent_CreateNotSignaled(p); +} + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp); + + +static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t) +{ + WRes wres = ArEvent_OptCreate_And_Reset(&t->startEvent); + if (wres == 0) + { + t->stop = False; + if (!Thread_WasCreated(&t->thread)) + wres = Thread_Create(&t->thread, ThreadFunc, t); + if (wres == 0) + wres = Event_Set(&t->startEvent); + } + if (wres == 0) + return SZ_OK; + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +static void MtCoderThread_Destruct(CMtCoderThread *t) +{ + if (Thread_WasCreated(&t->thread)) + { + t->stop = 1; + Event_Set(&t->startEvent); + Thread_Wait(&t->thread); + Thread_Close(&t->thread); + } + + Event_Close(&t->startEvent); + + if (t->inBuf) + { + ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf); + t->inBuf = NULL; + } +} + + + +static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize) +{ + size_t size = *processedSize; + *processedSize = 0; + while (size != 0) + { + size_t cur = size; + SRes res = ISeqInStream_Read(stream, data, &cur); + *processedSize += cur; + data += cur; + size -= cur; + RINOK(res); + if (cur == 0) + return SZ_OK; + } + return SZ_OK; +} + + +/* + ThreadFunc2() returns: + SZ_OK - in all normal cases (even for stream error or memory allocation error) + SZ_ERROR_THREAD - in case of failure in system synch function +*/ + +static SRes ThreadFunc2(CMtCoderThread *t) +{ + CMtCoder *mtc = t->mtCoder; + + for (;;) + { + unsigned bi; + SRes res; + SRes res2; + Bool finished; + unsigned bufIndex; + size_t size; + const Byte *inData; + UInt64 readProcessed = 0; + + RINOK_THREAD(Event_Wait(&mtc->readEvent)) + + /* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */ + + if (mtc->stopReading) + { + return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD; + } + + res = MtProgress_GetError(&mtc->mtProgress); + + size = 0; + inData = NULL; + finished = True; + + if (res == SZ_OK) + { + size = mtc->blockSize; + if (mtc->inStream) + { + if (!t->inBuf) + { + t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize); + if (!t->inBuf) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = FullRead(mtc->inStream, t->inBuf, &size); + readProcessed = mtc->readProcessed + size; + mtc->readProcessed = readProcessed; + } + if (res != SZ_OK) + { + mtc->readRes = res; + /* after reading error - we can stop encoding of previous blocks */ + MtProgress_SetError(&mtc->mtProgress, res); + } + else + finished = (size != mtc->blockSize); + } + else + { + size_t rem; + readProcessed = mtc->readProcessed; + rem = mtc->inDataSize - (size_t)readProcessed; + if (size > rem) + size = rem; + inData = mtc->inData + (size_t)readProcessed; + readProcessed += size; + mtc->readProcessed = readProcessed; + finished = (mtc->inDataSize == (size_t)readProcessed); + } + } + + /* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */ + + res2 = SZ_OK; + + if (Semaphore_Wait(&mtc->blocksSemaphore) != 0) + { + res2 = SZ_ERROR_THREAD; + if (res == SZ_OK) + { + res = res2; + // MtProgress_SetError(&mtc->mtProgress, res); + } + } + + bi = mtc->blockIndex; + + if (++mtc->blockIndex >= mtc->numBlocksMax) + mtc->blockIndex = 0; + + bufIndex = (unsigned)(int)-1; + + if (res == SZ_OK) + res = MtProgress_GetError(&mtc->mtProgress); + + if (res != SZ_OK) + finished = True; + + if (!finished) + { + if (mtc->numStartedThreads < mtc->numStartedThreadsLimit + && mtc->expectedDataSize != readProcessed) + { + res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]); + if (res == SZ_OK) + mtc->numStartedThreads++; + else + { + MtProgress_SetError(&mtc->mtProgress, res); + finished = True; + } + } + } + + if (finished) + mtc->stopReading = True; + + RINOK_THREAD(Event_Set(&mtc->readEvent)) + + if (res2 != SZ_OK) + return res2; + + if (res == SZ_OK) + { + CriticalSection_Enter(&mtc->cs); + bufIndex = mtc->freeBlockHead; + mtc->freeBlockHead = mtc->freeBlockList[bufIndex]; + CriticalSection_Leave(&mtc->cs); + + res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex, + mtc->inStream ? t->inBuf : inData, size, finished); + + // MtProgress_Reinit(&mtc->mtProgress, t->index); + + if (res != SZ_OK) + MtProgress_SetError(&mtc->mtProgress, res); + } + + { + CMtCoderBlock *block = &mtc->blocks[bi]; + block->res = res; + block->bufIndex = bufIndex; + block->finished = finished; + } + + #ifdef MTCODER__USE_WRITE_THREAD + RINOK_THREAD(Event_Set(&mtc->writeEvents[bi])) + #else + { + unsigned wi; + { + CriticalSection_Enter(&mtc->cs); + wi = mtc->writeIndex; + if (wi == bi) + mtc->writeIndex = (unsigned)(int)-1; + else + mtc->ReadyBlocks[bi] = True; + CriticalSection_Leave(&mtc->cs); + } + + if (wi != bi) + { + if (res != SZ_OK || finished) + return 0; + continue; + } + + if (mtc->writeRes != SZ_OK) + res = mtc->writeRes; + + for (;;) + { + if (res == SZ_OK && bufIndex != (unsigned)(int)-1) + { + res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex); + if (res != SZ_OK) + { + mtc->writeRes = res; + MtProgress_SetError(&mtc->mtProgress, res); + } + } + + if (++wi >= mtc->numBlocksMax) + wi = 0; + { + Bool isReady; + + CriticalSection_Enter(&mtc->cs); + + if (bufIndex != (unsigned)(int)-1) + { + mtc->freeBlockList[bufIndex] = mtc->freeBlockHead; + mtc->freeBlockHead = bufIndex; + } + + isReady = mtc->ReadyBlocks[wi]; + + if (isReady) + mtc->ReadyBlocks[wi] = False; + else + mtc->writeIndex = wi; + + CriticalSection_Leave(&mtc->cs); + + RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore)) + + if (!isReady) + break; + } + + { + CMtCoderBlock *block = &mtc->blocks[wi]; + if (res == SZ_OK && block->res != SZ_OK) + res = block->res; + bufIndex = block->bufIndex; + finished = block->finished; + } + } + } + #endif + + if (finished || res != SZ_OK) + return 0; + } +} + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp) +{ + CMtCoderThread *t = (CMtCoderThread *)pp; + for (;;) + { + if (Event_Wait(&t->startEvent) != 0) + return SZ_ERROR_THREAD; + if (t->stop) + return 0; + { + SRes res = ThreadFunc2(t); + CMtCoder *mtc = t->mtCoder; + if (res != SZ_OK) + { + MtProgress_SetError(&mtc->mtProgress, res); + } + + #ifndef MTCODER__USE_WRITE_THREAD + { + unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads); + if (numFinished == mtc->numStartedThreads) + if (Event_Set(&mtc->finishedEvent) != 0) + return SZ_ERROR_THREAD; + } + #endif + } + } +} + + + +void MtCoder_Construct(CMtCoder *p) +{ + unsigned i; + + p->blockSize = 0; + p->numThreadsMax = 0; + p->expectedDataSize = (UInt64)(Int64)-1; + + p->inStream = NULL; + p->inData = NULL; + p->inDataSize = 0; + + p->progress = NULL; + p->allocBig = NULL; + + p->mtCallback = NULL; + p->mtCallbackObject = NULL; + + p->allocatedBufsSize = 0; + + Event_Construct(&p->readEvent); + Semaphore_Construct(&p->blocksSemaphore); + + for (i = 0; i < MTCODER__THREADS_MAX; i++) + { + CMtCoderThread *t = &p->threads[i]; + t->mtCoder = p; + t->index = i; + t->inBuf = NULL; + t->stop = False; + Event_Construct(&t->startEvent); + Thread_Construct(&t->thread); + } + + #ifdef MTCODER__USE_WRITE_THREAD + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + Event_Construct(&p->writeEvents[i]); + #else + Event_Construct(&p->finishedEvent); + #endif + + CriticalSection_Init(&p->cs); + CriticalSection_Init(&p->mtProgress.cs); +} + + + + +static void MtCoder_Free(CMtCoder *p) +{ + unsigned i; + + /* + p->stopReading = True; + if (Event_IsCreated(&p->readEvent)) + Event_Set(&p->readEvent); + */ + + for (i = 0; i < MTCODER__THREADS_MAX; i++) + MtCoderThread_Destruct(&p->threads[i]); + + Event_Close(&p->readEvent); + Semaphore_Close(&p->blocksSemaphore); + + #ifdef MTCODER__USE_WRITE_THREAD + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + Event_Close(&p->writeEvents[i]); + #else + Event_Close(&p->finishedEvent); + #endif +} + + +void MtCoder_Destruct(CMtCoder *p) +{ + MtCoder_Free(p); + + CriticalSection_Delete(&p->cs); + CriticalSection_Delete(&p->mtProgress.cs); +} + + +SRes MtCoder_Code(CMtCoder *p) +{ + unsigned numThreads = p->numThreadsMax; + unsigned numBlocksMax; + unsigned i; + SRes res = SZ_OK; + + if (numThreads > MTCODER__THREADS_MAX) + numThreads = MTCODER__THREADS_MAX; + numBlocksMax = MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads); + + if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++; + if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++; + if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++; + + if (numBlocksMax > MTCODER__BLOCKS_MAX) + numBlocksMax = MTCODER__BLOCKS_MAX; + + if (p->blockSize != p->allocatedBufsSize) + { + for (i = 0; i < MTCODER__THREADS_MAX; i++) + { + CMtCoderThread *t = &p->threads[i]; + if (t->inBuf) + { + ISzAlloc_Free(p->allocBig, t->inBuf); + t->inBuf = NULL; + } + } + p->allocatedBufsSize = p->blockSize; + } + + p->readRes = SZ_OK; + + MtProgress_Init(&p->mtProgress, p->progress); + + #ifdef MTCODER__USE_WRITE_THREAD + for (i = 0; i < numBlocksMax; i++) + { + RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->writeEvents[i])); + } + #else + RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent)); + #endif + + { + RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->readEvent)); + + if (Semaphore_IsCreated(&p->blocksSemaphore)) + { + RINOK_THREAD(Semaphore_Close(&p->blocksSemaphore)); + } + RINOK_THREAD(Semaphore_Create(&p->blocksSemaphore, numBlocksMax, numBlocksMax)); + } + + for (i = 0; i < MTCODER__BLOCKS_MAX - 1; i++) + p->freeBlockList[i] = i + 1; + p->freeBlockList[MTCODER__BLOCKS_MAX - 1] = (unsigned)(int)-1; + p->freeBlockHead = 0; + + p->readProcessed = 0; + p->blockIndex = 0; + p->numBlocksMax = numBlocksMax; + p->stopReading = False; + + #ifndef MTCODER__USE_WRITE_THREAD + p->writeIndex = 0; + p->writeRes = SZ_OK; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + p->ReadyBlocks[i] = False; + p->numFinishedThreads = 0; + #endif + + p->numStartedThreadsLimit = numThreads; + p->numStartedThreads = 0; + + // for (i = 0; i < numThreads; i++) + { + CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++]; + RINOK(MtCoderThread_CreateAndStart(nextThread)); + } + + RINOK_THREAD(Event_Set(&p->readEvent)) + + #ifdef MTCODER__USE_WRITE_THREAD + { + unsigned bi = 0; + + for (;; bi++) + { + if (bi >= numBlocksMax) + bi = 0; + + RINOK_THREAD(Event_Wait(&p->writeEvents[bi])) + + { + const CMtCoderBlock *block = &p->blocks[bi]; + unsigned bufIndex = block->bufIndex; + Bool finished = block->finished; + if (res == SZ_OK && block->res != SZ_OK) + res = block->res; + + if (bufIndex != (unsigned)(int)-1) + { + if (res == SZ_OK) + { + res = p->mtCallback->Write(p->mtCallbackObject, bufIndex); + if (res != SZ_OK) + MtProgress_SetError(&p->mtProgress, res); + } + + CriticalSection_Enter(&p->cs); + { + p->freeBlockList[bufIndex] = p->freeBlockHead; + p->freeBlockHead = bufIndex; + } + CriticalSection_Leave(&p->cs); + } + + RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore)) + + if (finished) + break; + } + } + } + #else + { + WRes wres = Event_Wait(&p->finishedEvent); + res = MY_SRes_HRESULT_FROM_WRes(wres); + } + #endif + + if (res == SZ_OK) + res = p->readRes; + + if (res == SZ_OK) + res = p->mtProgress.res; + + #ifndef MTCODER__USE_WRITE_THREAD + if (res == SZ_OK) + res = p->writeRes; + #endif + + if (res != SZ_OK) + MtCoder_Free(p); + return res; +} + +#endif diff --git a/other-licenses/7zstub/src/C/MtCoder.h b/other-licenses/7zstub/src/C/MtCoder.h new file mode 100644 index 0000000000..7982e847cf --- /dev/null +++ b/other-licenses/7zstub/src/C/MtCoder.h @@ -0,0 +1,141 @@ +/* MtCoder.h -- Multi-thread Coder +2018-02-21 : Igor Pavlov : Public domain */ + +#ifndef __MT_CODER_H +#define __MT_CODER_H + +#include "MtDec.h" + +EXTERN_C_BEGIN + +/* + if ( defined MTCODER__USE_WRITE_THREAD) : main thread writes all data blocks to output stream + if (not defined MTCODER__USE_WRITE_THREAD) : any coder thread can write data blocks to output stream +*/ +/* #define MTCODER__USE_WRITE_THREAD */ + +#ifndef _7ZIP_ST + #define MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1) + #define MTCODER__THREADS_MAX 64 + #define MTCODER__BLOCKS_MAX (MTCODER__GET_NUM_BLOCKS_FROM_THREADS(MTCODER__THREADS_MAX) + 3) +#else + #define MTCODER__THREADS_MAX 1 + #define MTCODER__BLOCKS_MAX 1 +#endif + + +#ifndef _7ZIP_ST + + +typedef struct +{ + ICompressProgress vt; + CMtProgress *mtProgress; + UInt64 inSize; + UInt64 outSize; +} CMtProgressThunk; + +void MtProgressThunk_CreateVTable(CMtProgressThunk *p); + +#define MtProgressThunk_Init(p) { (p)->inSize = 0; (p)->outSize = 0; } + + +struct _CMtCoder; + + +typedef struct +{ + struct _CMtCoder *mtCoder; + unsigned index; + int stop; + Byte *inBuf; + + CAutoResetEvent startEvent; + CThread thread; +} CMtCoderThread; + + +typedef struct +{ + SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished); + SRes (*Write)(void *p, unsigned outBufIndex); +} IMtCoderCallback2; + + +typedef struct +{ + SRes res; + unsigned bufIndex; + Bool finished; +} CMtCoderBlock; + + +typedef struct _CMtCoder +{ + /* input variables */ + + size_t blockSize; /* size of input block */ + unsigned numThreadsMax; + UInt64 expectedDataSize; + + ISeqInStream *inStream; + const Byte *inData; + size_t inDataSize; + + ICompressProgress *progress; + ISzAllocPtr allocBig; + + IMtCoderCallback2 *mtCallback; + void *mtCallbackObject; + + + /* internal variables */ + + size_t allocatedBufsSize; + + CAutoResetEvent readEvent; + CSemaphore blocksSemaphore; + + Bool stopReading; + SRes readRes; + + #ifdef MTCODER__USE_WRITE_THREAD + CAutoResetEvent writeEvents[MTCODER__BLOCKS_MAX]; + #else + CAutoResetEvent finishedEvent; + SRes writeRes; + unsigned writeIndex; + Byte ReadyBlocks[MTCODER__BLOCKS_MAX]; + LONG numFinishedThreads; + #endif + + unsigned numStartedThreadsLimit; + unsigned numStartedThreads; + + unsigned numBlocksMax; + unsigned blockIndex; + UInt64 readProcessed; + + CCriticalSection cs; + + unsigned freeBlockHead; + unsigned freeBlockList[MTCODER__BLOCKS_MAX]; + + CMtProgress mtProgress; + CMtCoderBlock blocks[MTCODER__BLOCKS_MAX]; + CMtCoderThread threads[MTCODER__THREADS_MAX]; +} CMtCoder; + + +void MtCoder_Construct(CMtCoder *p); +void MtCoder_Destruct(CMtCoder *p); +SRes MtCoder_Code(CMtCoder *p); + + +#endif + + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/MtDec.c b/other-licenses/7zstub/src/C/MtDec.c new file mode 100644 index 0000000000..60d31b07ce --- /dev/null +++ b/other-licenses/7zstub/src/C/MtDec.c @@ -0,0 +1,1137 @@ +/* MtDec.c -- Multi-thread Decoder +2018-03-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #define SHOW_DEBUG_INFO + +// #include + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) + +#include "MtDec.h" + +#ifndef _7ZIP_ST + +void MtProgress_Init(CMtProgress *p, ICompressProgress *progress) +{ + p->progress = progress; + p->res = SZ_OK; + p->totalInSize = 0; + p->totalOutSize = 0; +} + + +SRes MtProgress_Progress_ST(CMtProgress *p) +{ + if (p->res == SZ_OK && p->progress) + if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) + p->res = SZ_ERROR_PROGRESS; + return p->res; +} + + +SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize) +{ + SRes res; + CriticalSection_Enter(&p->cs); + + p->totalInSize += inSize; + p->totalOutSize += outSize; + if (p->res == SZ_OK && p->progress) + if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) + p->res = SZ_ERROR_PROGRESS; + res = p->res; + + CriticalSection_Leave(&p->cs); + return res; +} + + +SRes MtProgress_GetError(CMtProgress *p) +{ + SRes res; + CriticalSection_Enter(&p->cs); + res = p->res; + CriticalSection_Leave(&p->cs); + return res; +} + + +void MtProgress_SetError(CMtProgress *p, SRes res) +{ + CriticalSection_Enter(&p->cs); + if (p->res == SZ_OK) + p->res = res; + CriticalSection_Leave(&p->cs); +} + + +#define RINOK_THREAD(x) RINOK(x) + + +static WRes ArEvent_OptCreate_And_Reset(CEvent *p) +{ + if (Event_IsCreated(p)) + return Event_Reset(p); + return AutoResetEvent_CreateNotSignaled(p); +} + + + +typedef struct +{ + void *next; + void *pad[3]; +} CMtDecBufLink; + +#define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink) +#define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET) + + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp); + + +static WRes MtDecThread_CreateEvents(CMtDecThread *t) +{ + WRes wres = ArEvent_OptCreate_And_Reset(&t->canWrite); + if (wres == 0) + { + wres = ArEvent_OptCreate_And_Reset(&t->canRead); + if (wres == 0) + return SZ_OK; + } + return wres; +} + + +static SRes MtDecThread_CreateAndStart(CMtDecThread *t) +{ + WRes wres = MtDecThread_CreateEvents(t); + // wres = 17; // for test + if (wres == 0) + { + if (Thread_WasCreated(&t->thread)) + return SZ_OK; + wres = Thread_Create(&t->thread, ThreadFunc, t); + if (wres == 0) + return SZ_OK; + } + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +void MtDecThread_FreeInBufs(CMtDecThread *t) +{ + if (t->inBuf) + { + void *link = t->inBuf; + t->inBuf = NULL; + do + { + void *next = ((CMtDecBufLink *)link)->next; + ISzAlloc_Free(t->mtDec->alloc, link); + link = next; + } + while (link); + } +} + + +static void MtDecThread_CloseThread(CMtDecThread *t) +{ + if (Thread_WasCreated(&t->thread)) + { + Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */ + Event_Set(&t->canRead); + Thread_Wait(&t->thread); + Thread_Close(&t->thread); + } + + Event_Close(&t->canRead); + Event_Close(&t->canWrite); +} + +static void MtDec_CloseThreads(CMtDec *p) +{ + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + MtDecThread_CloseThread(&p->threads[i]); +} + +static void MtDecThread_Destruct(CMtDecThread *t) +{ + MtDecThread_CloseThread(t); + MtDecThread_FreeInBufs(t); +} + + + +static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize) +{ + size_t size = *processedSize; + *processedSize = 0; + while (size != 0) + { + size_t cur = size; + SRes res = ISeqInStream_Read(stream, data, &cur); + *processedSize += cur; + data += cur; + size -= cur; + RINOK(res); + if (cur == 0) + return SZ_OK; + } + return SZ_OK; +} + + +static SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, Bool *wasInterrupted) +{ + SRes res; + CriticalSection_Enter(&p->mtProgress.cs); + *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); + res = p->mtProgress.res; + CriticalSection_Leave(&p->mtProgress.cs); + return res; +} + +static SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, Bool *wasInterrupted) +{ + SRes res; + CriticalSection_Enter(&p->mtProgress.cs); + + p->mtProgress.totalInSize += inSize; + p->mtProgress.totalOutSize += outSize; + if (p->mtProgress.res == SZ_OK && p->mtProgress.progress) + if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK) + p->mtProgress.res = SZ_ERROR_PROGRESS; + + *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); + res = p->mtProgress.res; + + CriticalSection_Leave(&p->mtProgress.cs); + + return res; +} + +static void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex) +{ + CriticalSection_Enter(&p->mtProgress.cs); + if (!p->needInterrupt || interruptIndex < p->interruptIndex) + { + p->interruptIndex = interruptIndex; + p->needInterrupt = True; + } + CriticalSection_Leave(&p->mtProgress.cs); +} + +Byte *MtDec_GetCrossBuff(CMtDec *p) +{ + Byte *cr = p->crossBlock; + if (!cr) + { + cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); + if (!cr) + return NULL; + p->crossBlock = cr; + } + return MTDEC__DATA_PTR_FROM_LINK(cr); +} + + +/* + ThreadFunc2() returns: + 0 - in all normal cases (even for stream error or memory allocation error) + (!= 0) - WRes error return by system threading function +*/ + +// #define MTDEC_ProgessStep (1 << 22) +#define MTDEC_ProgessStep (1 << 0) + +static WRes ThreadFunc2(CMtDecThread *t) +{ + CMtDec *p = t->mtDec; + + PRF_STR_INT("ThreadFunc2", t->index); + + // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index); + + for (;;) + { + SRes res, codeRes; + Bool wasInterrupted, isAllocError, overflow, finish; + SRes threadingErrorSRes; + Bool needCode, needWrite, needContinue; + + size_t inDataSize_Start; + UInt64 inDataSize; + // UInt64 inDataSize_Full; + + UInt64 blockIndex; + + UInt64 inPrev = 0; + UInt64 outPrev = 0; + UInt64 inCodePos; + UInt64 outCodePos; + + Byte *afterEndData = NULL; + size_t afterEndData_Size = 0; + + Bool canCreateNewThread = False; + // CMtDecCallbackInfo parse; + CMtDecThread *nextThread; + + PRF_STR_INT("Event_Wait(&t->canRead)", t->index); + + RINOK_THREAD(Event_Wait(&t->canRead)); + if (p->exitThread) + return 0; + + PRF_STR_INT("after Event_Wait(&t->canRead)", t->index); + + // if (t->index == 3) return 19; // for test + + blockIndex = p->blockIndex++; + + // PRF(printf("\ncanRead\n")) + + res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); + + finish = p->readWasFinished; + needCode = False; + needWrite = False; + isAllocError = False; + overflow = False; + + inDataSize_Start = 0; + inDataSize = 0; + // inDataSize_Full = 0; + + if (res == SZ_OK && !wasInterrupted) + { + // if (p->inStream) + { + CMtDecBufLink *prev = NULL; + CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; + size_t crossSize = p->crossEnd - p->crossStart; + + PRF(printf("\ncrossSize = %d\n", crossSize)); + + for (;;) + { + if (!link) + { + link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); + if (!link) + { + finish = True; + // p->allocError_for_Read_BlockIndex = blockIndex; + isAllocError = True; + break; + } + link->next = NULL; + if (prev) + { + // static unsigned g_num = 0; + // printf("\n%6d : %x", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev)); + prev->next = link; + } + else + t->inBuf = (void *)link; + } + + { + Byte *data = MTDEC__DATA_PTR_FROM_LINK(link); + Byte *parseData = data; + size_t size; + + if (crossSize != 0) + { + inDataSize = crossSize; + // inDataSize_Full = inDataSize; + inDataSize_Start = crossSize; + size = crossSize; + parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; + PRF(printf("\ncross : crossStart = %7d crossEnd = %7d finish = %1d", + (int)p->crossStart, (int)p->crossEnd, (int)finish)); + } + else + { + size = p->inBufSize; + + res = FullRead(p->inStream, data, &size); + + // size = 10; // test + + inDataSize += size; + // inDataSize_Full = inDataSize; + if (!prev) + inDataSize_Start = size; + + p->readProcessed += size; + finish = (size != p->inBufSize); + if (finish) + p->readWasFinished = True; + + // res = E_INVALIDARG; // test + + if (res != SZ_OK) + { + // PRF(printf("\nRead error = %d\n", res)) + // we want to decode all data before error + p->readRes = res; + // p->readError_BlockIndex = blockIndex; + p->readWasFinished = True; + finish = True; + res = SZ_OK; + // break; + } + + if (inDataSize - inPrev >= MTDEC_ProgessStep) + { + res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); + if (res != SZ_OK || wasInterrupted) + break; + inPrev = inDataSize; + } + } + + { + CMtDecCallbackInfo parse; + + parse.startCall = (prev == NULL); + parse.src = parseData; + parse.srcSize = size; + parse.srcFinished = finish; + parse.canCreateNewThread = True; + + // PRF(printf("\nParse size = %d\n", (unsigned)size)) + + p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse); + + needWrite = True; + canCreateNewThread = parse.canCreateNewThread; + + // printf("\n\n%12I64u %12I64u", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize); + + if ( + // parseRes != SZ_OK || + // inDataSize - (size - parse.srcSize) > p->inBlockMax + // || + parse.state == MTDEC_PARSE_OVERFLOW + // || wasInterrupted + ) + { + // Overflow or Parse error - switch from MT decoding to ST decoding + finish = True; + overflow = True; + + { + PRF(printf("\n Overflow")); + // PRF(printf("\nisBlockFinished = %d", (unsigned)parse.blockWasFinished)); + PRF(printf("\n inDataSize = %d", (unsigned)inDataSize)); + } + + if (crossSize != 0) + memcpy(data, parseData, size); + p->crossStart = 0; + p->crossEnd = 0; + break; + } + + if (crossSize != 0) + { + memcpy(data, parseData, parse.srcSize); + p->crossStart += parse.srcSize; + } + + if (parse.state != MTDEC_PARSE_CONTINUE || finish) + { + // we don't need to parse in current thread anymore + + if (parse.state == MTDEC_PARSE_END) + finish = True; + + needCode = True; + // p->crossFinished = finish; + + if (parse.srcSize == size) + { + // full parsed - no cross transfer + p->crossStart = 0; + p->crossEnd = 0; + break; + } + + if (parse.state == MTDEC_PARSE_END) + { + p->crossStart = 0; + p->crossEnd = 0; + + if (crossSize != 0) + memcpy(data + parse.srcSize, parseData + parse.srcSize, size - parse.srcSize); // we need all data + afterEndData_Size = size - parse.srcSize; + afterEndData = parseData + parse.srcSize; + + // we reduce data size to required bytes (parsed only) + inDataSize -= (size - parse.srcSize); + if (!prev) + inDataSize_Start = parse.srcSize; + break; + } + + { + // partial parsed - need cross transfer + if (crossSize != 0) + inDataSize = parse.srcSize; // it's only parsed now + else + { + // partial parsed - is not in initial cross block - we need to copy new data to cross block + Byte *cr = MtDec_GetCrossBuff(p); + if (!cr) + { + { + PRF(printf("\ncross alloc error error\n")); + // res = SZ_ERROR_MEM; + finish = True; + // p->allocError_for_Read_BlockIndex = blockIndex; + isAllocError = True; + break; + } + } + + { + size_t crSize = size - parse.srcSize; + inDataSize -= crSize; + p->crossEnd = crSize; + p->crossStart = 0; + memcpy(cr, parseData + parse.srcSize, crSize); + } + } + + // inDataSize_Full = inDataSize; + if (!prev) + inDataSize_Start = parse.srcSize; // it's partial size (parsed only) + + finish = False; + break; + } + } + + if (parse.srcSize != size) + { + res = SZ_ERROR_FAIL; + PRF(printf("\nfinished error SZ_ERROR_FAIL = %d\n", res)); + break; + } + } + } + + prev = link; + link = link->next; + + if (crossSize != 0) + { + crossSize = 0; + p->crossStart = 0; + p->crossEnd = 0; + } + } + } + + if (res == SZ_OK) + res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted); + } + + codeRes = SZ_OK; + + if (res == SZ_OK && needCode && !wasInterrupted) + { + codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index); + if (codeRes != SZ_OK) + { + needCode = False; + finish = True; + // SZ_ERROR_MEM is expected error here. + // if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later. + // if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding. + } + } + + if (res != SZ_OK || wasInterrupted) + finish = True; + + nextThread = NULL; + threadingErrorSRes = SZ_OK; + + if (!finish) + { + if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread) + { + SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]); + if (res2 == SZ_OK) + { + // if (p->numStartedThreads % 1000 == 0) PRF(printf("\n numStartedThreads=%d\n", p->numStartedThreads)); + p->numStartedThreads++; + } + else + { + PRF(printf("\nERROR: numStartedThreads=%d\n", p->numStartedThreads)); + if (p->numStartedThreads == 1) + { + // if only one thread is possible, we leave muti-threading code + finish = True; + needCode = False; + threadingErrorSRes = res2; + } + else + p->numStartedThreads_Limit = p->numStartedThreads; + } + } + + if (!finish) + { + unsigned nextIndex = t->index + 1; + nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex]; + RINOK_THREAD(Event_Set(&nextThread->canRead)) + // We have started executing for new iteration (with next thread) + // And that next thread now is responsible for possible exit from decoding (threading_code) + } + } + + // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite) + // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case + // if ( finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block): + // - if (needContinue) after Write(&needContinue), we restore decoding with new iteration + // - otherwise we stop decoding and exit from ThreadFunc2() + + // Don't change (finish) variable in the further code + + + // ---------- CODE ---------- + + inPrev = 0; + outPrev = 0; + inCodePos = 0; + outCodePos = 0; + + if (res == SZ_OK && needCode && codeRes == SZ_OK) + { + Bool isStartBlock = True; + CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; + + for (;;) + { + size_t inSize; + int stop; + + if (isStartBlock) + inSize = inDataSize_Start; + else + { + UInt64 rem = inDataSize - inCodePos; + inSize = p->inBufSize; + if (inSize > rem) + inSize = (size_t)rem; + } + + inCodePos += inSize; + stop = True; + + codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index, + (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize, + (inCodePos == inDataSize), // srcFinished + &inCodePos, &outCodePos, &stop); + + if (codeRes != SZ_OK) + { + PRF(printf("\nCode Interrupt error = %x\n", codeRes)); + // we interrupt only later blocks + MtDec_Interrupt(p, blockIndex); + break; + } + + if (stop || inCodePos == inDataSize) + break; + + { + const UInt64 inDelta = inCodePos - inPrev; + const UInt64 outDelta = outCodePos - outPrev; + if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep) + { + // Sleep(1); + res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted); + if (res != SZ_OK || wasInterrupted) + break; + inPrev = inCodePos; + outPrev = outCodePos; + } + } + + link = link->next; + isStartBlock = False; + } + } + + + // ---------- WRITE ---------- + + RINOK_THREAD(Event_Wait(&t->canWrite)); + + { + Bool isErrorMode = False; + Bool canRecode = True; + Bool needWriteToStream = needWrite; + + if (p->exitThread) return 0; // it's never executed in normal cases + + if (p->wasInterrupted) + wasInterrupted = True; + else + { + if (codeRes != SZ_OK) // || !needCode // check it !!! + { + p->wasInterrupted = True; + p->codeRes = codeRes; + if (codeRes == SZ_ERROR_MEM) + isAllocError = True; + } + + if (threadingErrorSRes) + { + p->wasInterrupted = True; + p->threadingErrorSRes = threadingErrorSRes; + needWriteToStream = False; + } + if (isAllocError) + { + p->wasInterrupted = True; + p->isAllocError = True; + needWriteToStream = False; + } + if (overflow) + { + p->wasInterrupted = True; + p->overflow = True; + needWriteToStream = False; + } + } + + if (needCode) + { + if (wasInterrupted) + { + inCodePos = 0; + outCodePos = 0; + } + { + const UInt64 inDelta = inCodePos - inPrev; + const UInt64 outDelta = outCodePos - outPrev; + // if (inDelta != 0 || outDelta != 0) + res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta); + } + } + + needContinue = (!finish); + + // if (res == SZ_OK && needWrite && !wasInterrupted) + if (needWrite) + { + // p->inProcessed += inCodePos; + + res = p->mtCallback->Write(p->mtCallbackObject, t->index, + res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite + afterEndData, afterEndData_Size, + &needContinue, + &canRecode); + + // res= E_INVALIDARG; // for test + + PRF(printf("\nAfter Write needContinue = %d\n", (unsigned)needContinue)); + PRF(printf("\nprocessed = %d\n", (unsigned)p->inProcessed)); + + if (res != SZ_OK) + { + PRF(printf("\nWrite error = %d\n", res)); + isErrorMode = True; + p->wasInterrupted = True; + } + if (res != SZ_OK + || (!needContinue && !finish)) + { + PRF(printf("\nWrite Interrupt error = %x\n", res)); + MtDec_Interrupt(p, blockIndex); + } + } + + if (canRecode) + if (!needCode + || res != SZ_OK + || p->wasInterrupted + || codeRes != SZ_OK + || wasInterrupted + || p->numFilledThreads != 0 + || isErrorMode) + { + if (p->numFilledThreads == 0) + p->filledThreadStart = t->index; + if (inDataSize != 0 || !finish) + { + t->inDataSize_Start = inDataSize_Start; + t->inDataSize = inDataSize; + p->numFilledThreads++; + } + PRF(printf("\np->numFilledThreads = %d\n", p->numFilledThreads)); + PRF(printf("p->filledThreadStart = %d\n", p->filledThreadStart)); + } + + if (!finish) + { + RINOK_THREAD(Event_Set(&nextThread->canWrite)); + } + else + { + if (needContinue) + { + // we restore decoding with new iteration + RINOK_THREAD(Event_Set(&p->threads[0].canWrite)); + } + else + { + // we exit from decoding + if (t->index == 0) + return SZ_OK; + p->exitThread = True; + } + RINOK_THREAD(Event_Set(&p->threads[0].canRead)); + } + } + } +} + +#ifdef _WIN32 +#define USE_ALLOCA +#endif + +#ifdef USE_ALLOCA +#ifdef _WIN32 +#include +#else +#include +#endif +#endif + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc1(void *pp) +{ + WRes res; + + CMtDecThread *t = (CMtDecThread *)pp; + CMtDec *p; + + // fprintf(stdout, "\n%d = %p\n", t->index, &t); + + res = ThreadFunc2(t); + p = t->mtDec; + if (res == 0) + return p->exitThreadWRes; + { + // it's unexpected situation for some threading function error + if (p->exitThreadWRes == 0) + p->exitThreadWRes = res; + PRF(printf("\nthread exit error = %d\n", res)); + p->exitThread = True; + Event_Set(&p->threads[0].canRead); + Event_Set(&p->threads[0].canWrite); + MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res)); + } + return res; +} + +static MY_NO_INLINE THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp) +{ + CMtDecThread *t = (CMtDecThread *)pp; + + // fprintf(stderr, "\n%d = %p - before", t->index, &t); + #ifdef USE_ALLOCA + t->allocaPtr = alloca(t->index * 128); + #endif + return ThreadFunc1(pp); +} + + +int MtDec_PrepareRead(CMtDec *p) +{ + if (p->crossBlock && p->crossStart == p->crossEnd) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + if (i > p->numStartedThreads + || p->numFilledThreads <= + (i >= p->filledThreadStart ? + i - p->filledThreadStart : + i + p->numStartedThreads - p->filledThreadStart)) + MtDecThread_FreeInBufs(&p->threads[i]); + } + + return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd); +} + + +const Byte *MtDec_Read(CMtDec *p, size_t *inLim) +{ + while (p->numFilledThreads != 0) + { + CMtDecThread *t = &p->threads[p->filledThreadStart]; + + if (*inLim != 0) + { + { + void *link = t->inBuf; + void *next = ((CMtDecBufLink *)link)->next; + ISzAlloc_Free(p->alloc, link); + t->inBuf = next; + } + + if (t->inDataSize == 0) + { + MtDecThread_FreeInBufs(t); + if (--p->numFilledThreads == 0) + break; + if (++p->filledThreadStart == p->numStartedThreads) + p->filledThreadStart = 0; + t = &p->threads[p->filledThreadStart]; + } + } + + { + size_t lim = t->inDataSize_Start; + if (lim != 0) + t->inDataSize_Start = 0; + else + { + UInt64 rem = t->inDataSize; + lim = p->inBufSize; + if (lim > rem) + lim = (size_t)rem; + } + t->inDataSize -= lim; + *inLim = lim; + return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf); + } + } + + { + size_t crossSize = p->crossEnd - p->crossStart; + if (crossSize != 0) + { + const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; + *inLim = crossSize; + p->crossStart = 0; + p->crossEnd = 0; + return data; + } + *inLim = 0; + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + return NULL; + } +} + + +void MtDec_Construct(CMtDec *p) +{ + unsigned i; + + p->inBufSize = (size_t)1 << 18; + + p->numThreadsMax = 0; + + p->inStream = NULL; + + // p->inData = NULL; + // p->inDataSize = 0; + + p->crossBlock = NULL; + p->crossStart = 0; + p->crossEnd = 0; + + p->numFilledThreads = 0; + + p->progress = NULL; + p->alloc = NULL; + + p->mtCallback = NULL; + p->mtCallbackObject = NULL; + + p->allocatedBufsSize = 0; + + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CMtDecThread *t = &p->threads[i]; + t->mtDec = p; + t->index = i; + t->inBuf = NULL; + Event_Construct(&t->canRead); + Event_Construct(&t->canWrite); + Thread_Construct(&t->thread); + } + + // Event_Construct(&p->finishedEvent); + + CriticalSection_Init(&p->mtProgress.cs); +} + + +static void MtDec_Free(CMtDec *p) +{ + unsigned i; + + p->exitThread = True; + + for (i = 0; i < MTDEC__THREADS_MAX; i++) + MtDecThread_Destruct(&p->threads[i]); + + // Event_Close(&p->finishedEvent); + + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } +} + + +void MtDec_Destruct(CMtDec *p) +{ + MtDec_Free(p); + + CriticalSection_Delete(&p->mtProgress.cs); +} + + +SRes MtDec_Code(CMtDec *p) +{ + unsigned i; + + p->inProcessed = 0; + + p->blockIndex = 1; // it must be larger than not_defined index (0) + p->isAllocError = False; + p->overflow = False; + p->threadingErrorSRes = SZ_OK; + + p->needContinue = True; + + p->readWasFinished = False; + p->needInterrupt = False; + p->interruptIndex = (UInt64)(Int64)-1; + + p->readProcessed = 0; + p->readRes = SZ_OK; + p->codeRes = SZ_OK; + p->wasInterrupted = False; + + p->crossStart = 0; + p->crossEnd = 0; + + p->filledThreadStart = 0; + p->numFilledThreads = 0; + + { + unsigned numThreads = p->numThreadsMax; + if (numThreads > MTDEC__THREADS_MAX) + numThreads = MTDEC__THREADS_MAX; + p->numStartedThreads_Limit = numThreads; + p->numStartedThreads = 0; + } + + if (p->inBufSize != p->allocatedBufsSize) + { + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CMtDecThread *t = &p->threads[i]; + if (t->inBuf) + MtDecThread_FreeInBufs(t); + } + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + + p->allocatedBufsSize = p->inBufSize; + } + + MtProgress_Init(&p->mtProgress, p->progress); + + // RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent)); + p->exitThread = False; + p->exitThreadWRes = 0; + + { + WRes wres; + WRes sres; + CMtDecThread *nextThread = &p->threads[p->numStartedThreads++]; + // wres = MtDecThread_CreateAndStart(nextThread); + wres = MtDecThread_CreateEvents(nextThread); + if (wres == 0) { wres = Event_Set(&nextThread->canWrite); + if (wres == 0) { wres = Event_Set(&nextThread->canRead); + if (wres == 0) { wres = ThreadFunc(nextThread); + if (wres != 0) + { + p->needContinue = False; + MtDec_CloseThreads(p); + }}}} + + // wres = 17; // for test + // wres = Event_Wait(&p->finishedEvent); + + sres = MY_SRes_HRESULT_FROM_WRes(wres); + + if (sres != 0) + p->threadingErrorSRes = sres; + + if ( + // wres == 0 + // wres != 0 + // || p->mtc.codeRes == SZ_ERROR_MEM + p->isAllocError + || p->threadingErrorSRes != SZ_OK + || p->overflow) + { + // p->needContinue = True; + } + else + p->needContinue = False; + + if (p->needContinue) + return SZ_OK; + + // if (sres != SZ_OK) + return sres; + // return E_FAIL; + } +} + +#endif diff --git a/other-licenses/7zstub/src/C/MtDec.h b/other-licenses/7zstub/src/C/MtDec.h new file mode 100644 index 0000000000..b445bc9d04 --- /dev/null +++ b/other-licenses/7zstub/src/C/MtDec.h @@ -0,0 +1,201 @@ +/* MtDec.h -- Multi-thread Decoder +2018-03-02 : Igor Pavlov : Public domain */ + +#ifndef __MT_DEC_H +#define __MT_DEC_H + +#include "7zTypes.h" + +#ifndef _7ZIP_ST +#include "Threads.h" +#endif + +EXTERN_C_BEGIN + +#ifndef _7ZIP_ST + +#ifndef _7ZIP_ST + #define MTDEC__THREADS_MAX 32 +#else + #define MTDEC__THREADS_MAX 1 +#endif + + +typedef struct +{ + ICompressProgress *progress; + SRes res; + UInt64 totalInSize; + UInt64 totalOutSize; + CCriticalSection cs; +} CMtProgress; + +void MtProgress_Init(CMtProgress *p, ICompressProgress *progress); +SRes MtProgress_Progress_ST(CMtProgress *p); +SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize); +SRes MtProgress_GetError(CMtProgress *p); +void MtProgress_SetError(CMtProgress *p, SRes res); + +struct _CMtDec; + +typedef struct +{ + struct _CMtDec *mtDec; + unsigned index; + void *inBuf; + + size_t inDataSize_Start; // size of input data in start block + UInt64 inDataSize; // total size of input data in all blocks + + CThread thread; + CAutoResetEvent canRead; + CAutoResetEvent canWrite; + void *allocaPtr; +} CMtDecThread; + +void MtDecThread_FreeInBufs(CMtDecThread *t); + + +typedef enum +{ + MTDEC_PARSE_CONTINUE, // continue this block with more input data + MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread + MTDEC_PARSE_NEW, // new block + MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue) +} EMtDecParseState; + +typedef struct +{ + // in + int startCall; + const Byte *src; + size_t srcSize; + // in : (srcSize == 0) is allowed + // out : it's allowed to return less that actually was used ? + int srcFinished; + + // out + EMtDecParseState state; + Bool canCreateNewThread; + UInt64 outPos; // check it (size_t) +} CMtDecCallbackInfo; + + +typedef struct +{ + void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci); + + // PreCode() and Code(): + // (SRes_return_result != SZ_OK) means stop decoding, no need another blocks + SRes (*PreCode)(void *p, unsigned coderIndex); + SRes (*Code)(void *p, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop); + // stop - means stop another Code calls + + + /* Write() must be called, if Parse() was called + set (needWrite) if + { + && (was not interrupted by progress) + && (was not interrupted in previous block) + } + + out: + if (*needContinue), decoder still need to continue decoding with new iteration, + even after MTDEC_PARSE_END + if (*canRecode), we didn't flush current block data, so we still can decode current block later. + */ + SRes (*Write)(void *p, unsigned coderIndex, + Bool needWriteToStream, + const Byte *src, size_t srcSize, + // int srcFinished, + Bool *needContinue, + Bool *canRecode); +} IMtDecCallback; + + + +typedef struct _CMtDec +{ + /* input variables */ + + size_t inBufSize; /* size of input block */ + unsigned numThreadsMax; + // size_t inBlockMax; + unsigned numThreadsMax_2; + + ISeqInStream *inStream; + // const Byte *inData; + // size_t inDataSize; + + ICompressProgress *progress; + ISzAllocPtr alloc; + + IMtDecCallback *mtCallback; + void *mtCallbackObject; + + + /* internal variables */ + + size_t allocatedBufsSize; + + Bool exitThread; + WRes exitThreadWRes; + + UInt64 blockIndex; + Bool isAllocError; + Bool overflow; + SRes threadingErrorSRes; + + Bool needContinue; + + // CAutoResetEvent finishedEvent; + + SRes readRes; + SRes codeRes; + + Bool wasInterrupted; + + unsigned numStartedThreads_Limit; + unsigned numStartedThreads; + + Byte *crossBlock; + size_t crossStart; + size_t crossEnd; + UInt64 readProcessed; + Bool readWasFinished; + UInt64 inProcessed; + + unsigned filledThreadStart; + unsigned numFilledThreads; + + #ifndef _7ZIP_ST + Bool needInterrupt; + UInt64 interruptIndex; + CMtProgress mtProgress; + CMtDecThread threads[MTDEC__THREADS_MAX]; + #endif +} CMtDec; + + +void MtDec_Construct(CMtDec *p); +void MtDec_Destruct(CMtDec *p); + +/* +MtDec_Code() returns: + SZ_OK - in most cases + MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function +*/ + +SRes MtDec_Code(CMtDec *p); +Byte *MtDec_GetCrossBuff(CMtDec *p); + +int MtDec_PrepareRead(CMtDec *p); +const Byte *MtDec_Read(CMtDec *p, size_t *inLim); + +#endif + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Ppmd.h b/other-licenses/7zstub/src/C/Ppmd.h new file mode 100644 index 0000000000..4b99415212 --- /dev/null +++ b/other-licenses/7zstub/src/C/Ppmd.h @@ -0,0 +1,85 @@ +/* Ppmd.h -- PPMD codec common code +2017-04-03 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#ifndef __PPMD_H +#define __PPMD_H + +#include "CpuArch.h" + +EXTERN_C_BEGIN + +#ifdef MY_CPU_32BIT + #define PPMD_32BIT +#endif + +#define PPMD_INT_BITS 7 +#define PPMD_PERIOD_BITS 7 +#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS)) + +#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift)) +#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2) +#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob)) +#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob)) + +#define PPMD_N1 4 +#define PPMD_N2 4 +#define PPMD_N3 4 +#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4) +#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4) + +#pragma pack(push, 1) +/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */ + +/* SEE-contexts for PPM-contexts with masked symbols */ +typedef struct +{ + UInt16 Summ; /* Freq */ + Byte Shift; /* Speed of Freq change; low Shift is for fast change */ + Byte Count; /* Count to next change of Shift */ +} CPpmd_See; + +#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ + { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); } + +typedef struct +{ + Byte Symbol; + Byte Freq; + UInt16 SuccessorLow; + UInt16 SuccessorHigh; +} CPpmd_State; + +#pragma pack(pop) + +typedef + #ifdef PPMD_32BIT + CPpmd_State * + #else + UInt32 + #endif + CPpmd_State_Ref; + +typedef + #ifdef PPMD_32BIT + void * + #else + UInt32 + #endif + CPpmd_Void_Ref; + +typedef + #ifdef PPMD_32BIT + Byte * + #else + UInt32 + #endif + CPpmd_Byte_Ref; + +#define PPMD_SetAllBitsIn256Bytes(p) \ + { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \ + p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }} + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Ppmd7.c b/other-licenses/7zstub/src/C/Ppmd7.c new file mode 100644 index 0000000000..ef93cb2d47 --- /dev/null +++ b/other-licenses/7zstub/src/C/Ppmd7.c @@ -0,0 +1,712 @@ +/* Ppmd7.c -- PPMdH codec +2017-04-03 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "Precomp.h" + +#include + +#include "Ppmd7.h" + +const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; +static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; + +#define MAX_FREQ 124 +#define UNIT_SIZE 12 + +#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) +#define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1]) +#define I2U(indx) (p->Indx2Units[indx]) + +#ifdef PPMD_32BIT + #define REF(ptr) (ptr) +#else + #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) +#endif + +#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) + +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +#define STATS(ctx) Ppmd7_GetStats(p, ctx) +#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) +#define SUFFIX(ctx) CTX((ctx)->Suffix) + +typedef CPpmd7_Context * CTX_PTR; + +struct CPpmd7_Node_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd7_Node_ * + #else + UInt32 + #endif + CPpmd7_Node_Ref; + +typedef struct CPpmd7_Node_ +{ + UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ + UInt16 NU; + CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ + CPpmd7_Node_Ref Prev; +} CPpmd7_Node; + +#ifdef PPMD_32BIT + #define NODE(ptr) (ptr) +#else + #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs))) +#endif + +void Ppmd7_Construct(CPpmd7 *p) +{ + unsigned i, k, m; + + p->Base = 0; + + for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) + { + unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); + do { p->Units2Indx[k++] = (Byte)i; } while (--step); + p->Indx2Units[i] = (Byte)k; + } + + p->NS2BSIndx[0] = (0 << 1); + p->NS2BSIndx[1] = (1 << 1); + memset(p->NS2BSIndx + 2, (2 << 1), 9); + memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); + + for (i = 0; i < 3; i++) + p->NS2Indx[i] = (Byte)i; + for (m = i, k = 1; i < 256; i++) + { + p->NS2Indx[i] = (Byte)m; + if (--k == 0) + k = (++m) - 2; + } + + memset(p->HB2Flag, 0, 0x40); + memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); +} + +void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->Base); + p->Size = 0; + p->Base = 0; +} + +Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc) +{ + if (!p->Base || p->Size != size) + { + size_t size2; + Ppmd7_Free(p, alloc); + size2 = 0 + #ifndef PPMD_32BIT + + UNIT_SIZE + #endif + ; + p->AlignOffset = + #ifdef PPMD_32BIT + (4 - size) & 3; + #else + 4 - (size & 3); + #endif + if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size + size2)) == 0) + return False; + p->Size = size; + } + return True; +} + +static void InsertNode(CPpmd7 *p, void *node, unsigned indx) +{ + *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; + p->FreeList[indx] = REF(node); +} + +static void *RemoveNode(CPpmd7 *p, unsigned indx) +{ + CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); + p->FreeList[indx] = *node; + return node; +} + +static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) +{ + unsigned i, nu = I2U(oldIndx) - I2U(newIndx); + ptr = (Byte *)ptr + U2B(I2U(newIndx)); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); + } + InsertNode(p, ptr, i); +} + +static void GlueFreeBlocks(CPpmd7 *p) +{ + #ifdef PPMD_32BIT + CPpmd7_Node headItem; + CPpmd7_Node_Ref head = &headItem; + #else + CPpmd7_Node_Ref head = p->AlignOffset + p->Size; + #endif + + CPpmd7_Node_Ref n = head; + unsigned i; + + p->GlueCount = 255; + + /* create doubly-linked list of free blocks */ + for (i = 0; i < PPMD_NUM_INDEXES; i++) + { + UInt16 nu = I2U(i); + CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; + p->FreeList[i] = 0; + while (next != 0) + { + CPpmd7_Node *node = NODE(next); + node->Next = n; + n = NODE(n)->Prev = next; + next = *(const CPpmd7_Node_Ref *)node; + node->Stamp = 0; + node->NU = (UInt16)nu; + } + } + NODE(head)->Stamp = 1; + NODE(head)->Next = n; + NODE(n)->Prev = head; + if (p->LoUnit != p->HiUnit) + ((CPpmd7_Node *)p->LoUnit)->Stamp = 1; + + /* Glue free blocks */ + while (n != head) + { + CPpmd7_Node *node = NODE(n); + UInt32 nu = (UInt32)node->NU; + for (;;) + { + CPpmd7_Node *node2 = NODE(n) + nu; + nu += node2->NU; + if (node2->Stamp != 0 || nu >= 0x10000) + break; + NODE(node2->Prev)->Next = node2->Next; + NODE(node2->Next)->Prev = node2->Prev; + node->NU = (UInt16)nu; + } + n = node->Next; + } + + /* Fill lists of free blocks */ + for (n = NODE(head)->Next; n != head;) + { + CPpmd7_Node *node = NODE(n); + unsigned nu; + CPpmd7_Node_Ref next = node->Next; + for (nu = node->NU; nu > 128; nu -= 128, node += 128) + InsertNode(p, node, PPMD_NUM_INDEXES - 1); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, node + k, nu - k - 1); + } + InsertNode(p, node, i); + n = next; + } +} + +static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) +{ + unsigned i; + void *retVal; + if (p->GlueCount == 0) + { + GlueFreeBlocks(p); + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + } + i = indx; + do + { + if (++i == PPMD_NUM_INDEXES) + { + UInt32 numBytes = U2B(I2U(indx)); + p->GlueCount--; + return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); + } + } + while (p->FreeList[i] == 0); + retVal = RemoveNode(p, i); + SplitBlock(p, retVal, i, indx); + return retVal; +} + +static void *AllocUnits(CPpmd7 *p, unsigned indx) +{ + UInt32 numBytes; + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + numBytes = U2B(I2U(indx)); + if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit)) + { + void *retVal = p->LoUnit; + p->LoUnit += numBytes; + return retVal; + } + return AllocUnitsRare(p, indx); +} + +#define MyMem12Cpy(dest, src, num) \ + { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ + do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while (--n); } + +static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) +{ + unsigned i0 = U2I(oldNU); + unsigned i1 = U2I(newNU); + if (i0 == i1) + return oldPtr; + if (p->FreeList[i1] != 0) + { + void *ptr = RemoveNode(p, i1); + MyMem12Cpy(ptr, oldPtr, newNU); + InsertNode(p, oldPtr, i0); + return ptr; + } + SplitBlock(p, oldPtr, i0, i1); + return oldPtr; +} + +#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) + +static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) +{ + (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); + (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); +} + +static void RestartModel(CPpmd7 *p) +{ + unsigned i, k, m; + + memset(p->FreeList, 0, sizeof(p->FreeList)); + p->Text = p->Base + p->AlignOffset; + p->HiUnit = p->Text + p->Size; + p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; + p->GlueCount = 0; + + p->OrderFall = p->MaxOrder; + p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; + p->PrevSuccess = 0; + + p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ + p->MinContext->Suffix = 0; + p->MinContext->NumStats = 256; + p->MinContext->SummFreq = 256 + 1; + p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ + p->LoUnit += U2B(256 / 2); + p->MinContext->Stats = REF(p->FoundState); + for (i = 0; i < 256; i++) + { + CPpmd_State *s = &p->FoundState[i]; + s->Symbol = (Byte)i; + s->Freq = 1; + SetSuccessor(s, 0); + } + + for (i = 0; i < 128; i++) + for (k = 0; k < 8; k++) + { + UInt16 *dest = p->BinSumm[i] + k; + UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); + for (m = 0; m < 64; m += 8) + dest[m] = val; + } + + for (i = 0; i < 25; i++) + for (k = 0; k < 16; k++) + { + CPpmd_See *s = &p->See[i][k]; + s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); + s->Count = 4; + } +} + +void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) +{ + p->MaxOrder = maxOrder; + RestartModel(p); + p->DummySee.Shift = PPMD_PERIOD_BITS; + p->DummySee.Summ = 0; /* unused */ + p->DummySee.Count = 64; /* unused */ +} + +static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip) +{ + CPpmd_State upState; + CTX_PTR c = p->MinContext; + CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); + CPpmd_State *ps[PPMD7_MAX_ORDER]; + unsigned numPs = 0; + + if (!skip) + ps[numPs++] = p->FoundState; + + while (c->Suffix) + { + CPpmd_Void_Ref successor; + CPpmd_State *s; + c = SUFFIX(c); + if (c->NumStats != 1) + { + for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); + } + else + s = ONE_STATE(c); + successor = SUCCESSOR(s); + if (successor != upBranch) + { + c = CTX(successor); + if (numPs == 0) + return c; + break; + } + ps[numPs++] = s; + } + + upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch); + SetSuccessor(&upState, upBranch + 1); + + if (c->NumStats == 1) + upState.Freq = ONE_STATE(c)->Freq; + else + { + UInt32 cf, s0; + CPpmd_State *s; + for (s = STATS(c); s->Symbol != upState.Symbol; s++); + cf = s->Freq - 1; + s0 = c->SummFreq - c->NumStats - cf; + upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); + } + + do + { + /* Create Child */ + CTX_PTR c1; /* = AllocContext(p); */ + if (p->HiUnit != p->LoUnit) + c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); + else if (p->FreeList[0] != 0) + c1 = (CTX_PTR)RemoveNode(p, 0); + else + { + c1 = (CTX_PTR)AllocUnitsRare(p, 0); + if (!c1) + return NULL; + } + c1->NumStats = 1; + *ONE_STATE(c1) = upState; + c1->Suffix = REF(c); + SetSuccessor(ps[--numPs], REF(c1)); + c = c1; + } + while (numPs != 0); + + return c; +} + +static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) +{ + CPpmd_State tmp = *t1; + *t1 = *t2; + *t2 = tmp; +} + +static void UpdateModel(CPpmd7 *p) +{ + CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); + CTX_PTR c; + unsigned s0, ns; + + if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) + { + c = SUFFIX(p->MinContext); + + if (c->NumStats == 1) + { + CPpmd_State *s = ONE_STATE(c); + if (s->Freq < 32) + s->Freq++; + } + else + { + CPpmd_State *s = STATS(c); + if (s->Symbol != p->FoundState->Symbol) + { + do { s++; } while (s->Symbol != p->FoundState->Symbol); + if (s[0].Freq >= s[-1].Freq) + { + SwapStates(&s[0], &s[-1]); + s--; + } + } + if (s->Freq < MAX_FREQ - 9) + { + s->Freq += 2; + c->SummFreq += 2; + } + } + } + + if (p->OrderFall == 0) + { + p->MinContext = p->MaxContext = CreateSuccessors(p, True); + if (p->MinContext == 0) + { + RestartModel(p); + return; + } + SetSuccessor(p->FoundState, REF(p->MinContext)); + return; + } + + *p->Text++ = p->FoundState->Symbol; + successor = REF(p->Text); + if (p->Text >= p->UnitsStart) + { + RestartModel(p); + return; + } + + if (fSuccessor) + { + if (fSuccessor <= successor) + { + CTX_PTR cs = CreateSuccessors(p, False); + if (cs == NULL) + { + RestartModel(p); + return; + } + fSuccessor = REF(cs); + } + if (--p->OrderFall == 0) + { + successor = fSuccessor; + p->Text -= (p->MaxContext != p->MinContext); + } + } + else + { + SetSuccessor(p->FoundState, successor); + fSuccessor = REF(p->MinContext); + } + + s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1); + + for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c)) + { + unsigned ns1; + UInt32 cf, sf; + if ((ns1 = c->NumStats) != 1) + { + if ((ns1 & 1) == 0) + { + /* Expand for one UNIT */ + unsigned oldNU = ns1 >> 1; + unsigned i = U2I(oldNU); + if (i != U2I((size_t)oldNU + 1)) + { + void *ptr = AllocUnits(p, i + 1); + void *oldPtr; + if (!ptr) + { + RestartModel(p); + return; + } + oldPtr = STATS(c); + MyMem12Cpy(ptr, oldPtr, oldNU); + InsertNode(p, oldPtr, i); + c->Stats = STATS_REF(ptr); + } + } + c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1))); + } + else + { + CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); + if (!s) + { + RestartModel(p); + return; + } + *s = *ONE_STATE(c); + c->Stats = REF(s); + if (s->Freq < MAX_FREQ / 4 - 1) + s->Freq <<= 1; + else + s->Freq = MAX_FREQ - 4; + c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3)); + } + cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6); + sf = (UInt32)s0 + c->SummFreq; + if (cf < 6 * sf) + { + cf = 1 + (cf > sf) + (cf >= 4 * sf); + c->SummFreq += 3; + } + else + { + cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); + c->SummFreq = (UInt16)(c->SummFreq + cf); + } + { + CPpmd_State *s = STATS(c) + ns1; + SetSuccessor(s, successor); + s->Symbol = p->FoundState->Symbol; + s->Freq = (Byte)cf; + c->NumStats = (UInt16)(ns1 + 1); + } + } + p->MaxContext = p->MinContext = CTX(fSuccessor); +} + +static void Rescale(CPpmd7 *p) +{ + unsigned i, adder, sumFreq, escFreq; + CPpmd_State *stats = STATS(p->MinContext); + CPpmd_State *s = p->FoundState; + { + CPpmd_State tmp = *s; + for (; s != stats; s--) + s[0] = s[-1]; + *s = tmp; + } + escFreq = p->MinContext->SummFreq - s->Freq; + s->Freq += 4; + adder = (p->OrderFall != 0); + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq = s->Freq; + + i = p->MinContext->NumStats - 1; + do + { + escFreq -= (++s)->Freq; + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq += s->Freq; + if (s[0].Freq > s[-1].Freq) + { + CPpmd_State *s1 = s; + CPpmd_State tmp = *s1; + do + s1[0] = s1[-1]; + while (--s1 != stats && tmp.Freq > s1[-1].Freq); + *s1 = tmp; + } + } + while (--i); + + if (s->Freq == 0) + { + unsigned numStats = p->MinContext->NumStats; + unsigned n0, n1; + do { i++; } while ((--s)->Freq == 0); + escFreq += i; + p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i); + if (p->MinContext->NumStats == 1) + { + CPpmd_State tmp = *stats; + do + { + tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); + escFreq >>= 1; + } + while (escFreq > 1); + InsertNode(p, stats, U2I(((numStats + 1) >> 1))); + *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; + return; + } + n0 = (numStats + 1) >> 1; + n1 = (p->MinContext->NumStats + 1) >> 1; + if (n0 != n1) + p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + } + p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); + p->FoundState = STATS(p->MinContext); +} + +CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) +{ + CPpmd_See *see; + unsigned nonMasked = p->MinContext->NumStats - numMasked; + if (p->MinContext->NumStats != 256) + { + see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + + (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + + 2 * (unsigned)(p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + + 4 * (unsigned)(numMasked > nonMasked) + + p->HiBitsFlag; + { + unsigned r = (see->Summ >> see->Shift); + see->Summ = (UInt16)(see->Summ - r); + *escFreq = r + (r == 0); + } + } + else + { + see = &p->DummySee; + *escFreq = 1; + } + return see; +} + +static void NextContext(CPpmd7 *p) +{ + CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); + if (p->OrderFall == 0 && (Byte *)c > p->Text) + p->MinContext = p->MaxContext = c; + else + UpdateModel(p); +} + +void Ppmd7_Update1(CPpmd7 *p) +{ + CPpmd_State *s = p->FoundState; + s->Freq += 4; + p->MinContext->SummFreq += 4; + if (s[0].Freq > s[-1].Freq) + { + SwapStates(&s[0], &s[-1]); + p->FoundState = --s; + if (s->Freq > MAX_FREQ) + Rescale(p); + } + NextContext(p); +} + +void Ppmd7_Update1_0(CPpmd7 *p) +{ + p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq); + p->RunLength += p->PrevSuccess; + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + NextContext(p); +} + +void Ppmd7_UpdateBin(CPpmd7 *p) +{ + p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0)); + p->PrevSuccess = 1; + p->RunLength++; + NextContext(p); +} + +void Ppmd7_Update2(CPpmd7 *p) +{ + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + p->RunLength = p->InitRL; + UpdateModel(p); +} diff --git a/other-licenses/7zstub/src/C/Ppmd7.h b/other-licenses/7zstub/src/C/Ppmd7.h new file mode 100644 index 0000000000..ee2c035d00 --- /dev/null +++ b/other-licenses/7zstub/src/C/Ppmd7.h @@ -0,0 +1,142 @@ +/* Ppmd7.h -- PPMdH compression codec +2017-04-03 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +/* This code supports virtual RangeDecoder and includes the implementation +of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H. +If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */ + +#ifndef __PPMD7_H +#define __PPMD7_H + +#include "Ppmd.h" + +EXTERN_C_BEGIN + +#define PPMD7_MIN_ORDER 2 +#define PPMD7_MAX_ORDER 64 + +#define PPMD7_MIN_MEM_SIZE (1 << 11) +#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3) + +struct CPpmd7_Context_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd7_Context_ * + #else + UInt32 + #endif + CPpmd7_Context_Ref; + +typedef struct CPpmd7_Context_ +{ + UInt16 NumStats; + UInt16 SummFreq; + CPpmd_State_Ref Stats; + CPpmd7_Context_Ref Suffix; +} CPpmd7_Context; + +#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) + +typedef struct +{ + CPpmd7_Context *MinContext, *MaxContext; + CPpmd_State *FoundState; + unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag; + Int32 RunLength, InitRL; /* must be 32-bit at least */ + + UInt32 Size; + UInt32 GlueCount; + Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; + UInt32 AlignOffset; + + Byte Indx2Units[PPMD_NUM_INDEXES]; + Byte Units2Indx[128]; + CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; + Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; + CPpmd_See DummySee, See[25][16]; + UInt16 BinSumm[128][64]; +} CPpmd7; + +void Ppmd7_Construct(CPpmd7 *p); +Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc); +void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc); +void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder); +#define Ppmd7_WasAllocated(p) ((p)->Base != NULL) + + +/* ---------- Internal Functions ---------- */ + +extern const Byte PPMD7_kExpEscape[16]; + +#ifdef PPMD_32BIT + #define Ppmd7_GetPtr(p, ptr) (ptr) + #define Ppmd7_GetContext(p, ptr) (ptr) + #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats) +#else + #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs))) + #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs))) + #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats))) +#endif + +void Ppmd7_Update1(CPpmd7 *p); +void Ppmd7_Update1_0(CPpmd7 *p); +void Ppmd7_Update2(CPpmd7 *p); +void Ppmd7_UpdateBin(CPpmd7 *p); + +#define Ppmd7_GetBinSumm(p) \ + &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ + p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ + (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ + 2 * p->HB2Flag[(unsigned)Ppmd7Context_OneState(p->MinContext)->Symbol] + \ + ((p->RunLength >> 26) & 0x20)] + +CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); + + +/* ---------- Decode ---------- */ + +typedef struct IPpmd7_RangeDec IPpmd7_RangeDec; + +struct IPpmd7_RangeDec +{ + UInt32 (*GetThreshold)(const IPpmd7_RangeDec *p, UInt32 total); + void (*Decode)(const IPpmd7_RangeDec *p, UInt32 start, UInt32 size); + UInt32 (*DecodeBit)(const IPpmd7_RangeDec *p, UInt32 size0); +}; + +typedef struct +{ + IPpmd7_RangeDec vt; + UInt32 Range; + UInt32 Code; + IByteIn *Stream; +} CPpmd7z_RangeDec; + +void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p); +Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p); +#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) + +int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc); + + +/* ---------- Encode ---------- */ + +typedef struct +{ + UInt64 Low; + UInt32 Range; + Byte Cache; + UInt64 CacheSize; + IByteOut *Stream; +} CPpmd7z_RangeEnc; + +void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p); +void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p); + +void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Ppmd7Dec.c b/other-licenses/7zstub/src/C/Ppmd7Dec.c new file mode 100644 index 0000000000..3023b6776d --- /dev/null +++ b/other-licenses/7zstub/src/C/Ppmd7Dec.c @@ -0,0 +1,191 @@ +/* Ppmd7Dec.c -- PPMdH Decoder +2017-04-03 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "Precomp.h" + +#include "Ppmd7.h" + +#define kTopValue (1 << 24) + +Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) +{ + unsigned i; + p->Code = 0; + p->Range = 0xFFFFFFFF; + if (IByteIn_Read(p->Stream) != 0) + return False; + for (i = 0; i < 4; i++) + p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); + return (p->Code < 0xFFFFFFFF); +} + +#define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt); + +static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total) +{ + GET_Ppmd7z_RangeDec + return p->Code / (p->Range /= total); +} + +static void Range_Normalize(CPpmd7z_RangeDec *p) +{ + if (p->Range < kTopValue) + { + p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); + p->Range <<= 8; + if (p->Range < kTopValue) + { + p->Code = (p->Code << 8) | IByteIn_Read(p->Stream); + p->Range <<= 8; + } + } +} + +static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size) +{ + GET_Ppmd7z_RangeDec + p->Code -= start * p->Range; + p->Range *= size; + Range_Normalize(p); +} + +static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0) +{ + GET_Ppmd7z_RangeDec + UInt32 newBound = (p->Range >> 14) * size0; + UInt32 symbol; + if (p->Code < newBound) + { + symbol = 0; + p->Range = newBound; + } + else + { + symbol = 1; + p->Code -= newBound; + p->Range -= newBound; + } + Range_Normalize(p); + return symbol; +} + +void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) +{ + p->vt.GetThreshold = Range_GetThreshold; + p->vt.Decode = Range_Decode; + p->vt.DecodeBit = Range_DecodeBit; +} + + +#define MASK(sym) ((signed char *)charMask)[sym] + +int Ppmd7_DecodeSymbol(CPpmd7 *p, const IPpmd7_RangeDec *rc) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + unsigned i; + UInt32 count, hiCnt; + if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) + { + Byte symbol; + rc->Decode(rc, 0, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update1_0(p); + return symbol; + } + p->PrevSuccess = 0; + i = p->MinContext->NumStats - 1; + do + { + if ((hiCnt += (++s)->Freq) > count) + { + Byte symbol; + rc->Decode(rc, hiCnt - s->Freq, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update1(p); + return symbol; + } + } + while (--i); + if (count >= p->MinContext->SummFreq) + return -2; + p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; + rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt); + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats - 1; + do { MASK((--s)->Symbol) = 0; } while (--i); + } + else + { + UInt16 *prob = Ppmd7_GetBinSumm(p); + if (rc->DecodeBit(rc, *prob) == 0) + { + Byte symbol; + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; + Ppmd7_UpdateBin(p); + return symbol; + } + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; + p->PrevSuccess = 0; + } + for (;;) + { + CPpmd_State *ps[256], *s; + UInt32 freqSum, count, hiCnt; + CPpmd_See *see; + unsigned i, num, numMasked = p->MinContext->NumStats; + do + { + p->OrderFall++; + if (!p->MinContext->Suffix) + return -1; + p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + hiCnt = 0; + s = Ppmd7_GetStats(p, p->MinContext); + i = 0; + num = p->MinContext->NumStats - numMasked; + do + { + int k = (int)(MASK(s->Symbol)); + hiCnt += (s->Freq & k); + ps[i] = s++; + i -= k; + } + while (i != num); + + see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); + freqSum += hiCnt; + count = rc->GetThreshold(rc, freqSum); + + if (count < hiCnt) + { + Byte symbol; + CPpmd_State **pps = ps; + for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); + s = *pps; + rc->Decode(rc, hiCnt - s->Freq, s->Freq); + Ppmd_See_Update(see); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update2(p); + return symbol; + } + if (count >= freqSum) + return -2; + rc->Decode(rc, hiCnt, freqSum - hiCnt); + see->Summ = (UInt16)(see->Summ + freqSum); + do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); + } +} diff --git a/other-licenses/7zstub/src/C/Ppmd7Enc.c b/other-licenses/7zstub/src/C/Ppmd7Enc.c new file mode 100644 index 0000000000..a74d3002b6 --- /dev/null +++ b/other-licenses/7zstub/src/C/Ppmd7Enc.c @@ -0,0 +1,187 @@ +/* Ppmd7Enc.c -- PPMdH Encoder +2017-04-03 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "Precomp.h" + +#include "Ppmd7.h" + +#define kTopValue (1 << 24) + +void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p) +{ + p->Low = 0; + p->Range = 0xFFFFFFFF; + p->Cache = 0; + p->CacheSize = 1; +} + +static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p) +{ + if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0) + { + Byte temp = p->Cache; + do + { + IByteOut_Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); + temp = 0xFF; + } + while (--p->CacheSize != 0); + p->Cache = (Byte)((UInt32)p->Low >> 24); + } + p->CacheSize++; + p->Low = (UInt32)p->Low << 8; +} + +static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total) +{ + p->Low += start * (p->Range /= total); + p->Range *= size; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0) +{ + p->Range = (p->Range >> 14) * size0; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0) +{ + UInt32 newBound = (p->Range >> 14) * size0; + p->Low += newBound; + p->Range -= newBound; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p) +{ + unsigned i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + + +#define MASK(sym) ((signed char *)charMask)[sym] + +void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + UInt32 sum; + unsigned i; + if (s->Symbol == symbol) + { + RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq); + p->FoundState = s; + Ppmd7_Update1_0(p); + return; + } + p->PrevSuccess = 0; + sum = s->Freq; + i = p->MinContext->NumStats - 1; + do + { + if ((++s)->Symbol == symbol) + { + RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq); + p->FoundState = s; + Ppmd7_Update1(p); + return; + } + sum += s->Freq; + } + while (--i); + + p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats - 1; + do { MASK((--s)->Symbol) = 0; } while (--i); + RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq); + } + else + { + UInt16 *prob = Ppmd7_GetBinSumm(p); + CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); + if (s->Symbol == symbol) + { + RangeEnc_EncodeBit_0(rc, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + p->FoundState = s; + Ppmd7_UpdateBin(p); + return; + } + else + { + RangeEnc_EncodeBit_1(rc, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + p->PrevSuccess = 0; + } + } + for (;;) + { + UInt32 escFreq; + CPpmd_See *see; + CPpmd_State *s; + UInt32 sum; + unsigned i, numMasked = p->MinContext->NumStats; + do + { + p->OrderFall++; + if (!p->MinContext->Suffix) + return; /* EndMarker (symbol = -1) */ + p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + + see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); + s = Ppmd7_GetStats(p, p->MinContext); + sum = 0; + i = p->MinContext->NumStats; + do + { + int cur = s->Symbol; + if (cur == symbol) + { + UInt32 low = sum; + CPpmd_State *s1 = s; + do + { + sum += (s->Freq & (int)(MASK(s->Symbol))); + s++; + } + while (--i); + RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq); + Ppmd_See_Update(see); + p->FoundState = s1; + Ppmd7_Update2(p); + return; + } + sum += (s->Freq & (int)(MASK(cur))); + MASK(cur) = 0; + s++; + } + while (--i); + + RangeEnc_Encode(rc, sum, escFreq, sum + escFreq); + see->Summ = (UInt16)(see->Summ + sum + escFreq); + } +} diff --git a/other-licenses/7zstub/src/C/Precomp.h b/other-licenses/7zstub/src/C/Precomp.h new file mode 100644 index 0000000000..edb5814439 --- /dev/null +++ b/other-licenses/7zstub/src/C/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "Compiler.h" +/* #include "7zTypes.h" */ + +#endif diff --git a/other-licenses/7zstub/src/C/RotateDefs.h b/other-licenses/7zstub/src/C/RotateDefs.h new file mode 100644 index 0000000000..6c790e791e --- /dev/null +++ b/other-licenses/7zstub/src/C/RotateDefs.h @@ -0,0 +1,30 @@ +/* RotateDefs.h -- Rotate functions +2015-03-25 : Igor Pavlov : Public domain */ + +#ifndef __ROTATE_DEFS_H +#define __ROTATE_DEFS_H + +#ifdef _MSC_VER + +#include + +/* don't use _rotl with MINGW. It can insert slow call to function. */ + +/* #if (_MSC_VER >= 1200) */ +#pragma intrinsic(_rotl) +#pragma intrinsic(_rotr) +/* #endif */ + +#define rotlFixed(x, n) _rotl((x), (n)) +#define rotrFixed(x, n) _rotr((x), (n)) + +#else + +/* new compilers can translate these macros to fast commands. */ + +#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#endif + +#endif diff --git a/other-licenses/7zstub/src/C/Sha256.c b/other-licenses/7zstub/src/C/Sha256.c new file mode 100644 index 0000000000..90994e5abb --- /dev/null +++ b/other-licenses/7zstub/src/C/Sha256.c @@ -0,0 +1,248 @@ +/* Crypto/Sha256.c -- SHA-256 Hash +2017-04-03 : Igor Pavlov : Public domain +This code is based on public domain code from Wei Dai's Crypto++ library. */ + +#include "Precomp.h" + +#include + +#include "CpuArch.h" +#include "RotateDefs.h" +#include "Sha256.h" + +/* define it for speed optimization */ +#ifndef _SFX +#define _SHA256_UNROLL +#define _SHA256_UNROLL2 +#endif + +/* #define _SHA256_UNROLL2 */ + +void Sha256_Init(CSha256 *p) +{ + p->state[0] = 0x6a09e667; + p->state[1] = 0xbb67ae85; + p->state[2] = 0x3c6ef372; + p->state[3] = 0xa54ff53a; + p->state[4] = 0x510e527f; + p->state[5] = 0x9b05688c; + p->state[6] = 0x1f83d9ab; + p->state[7] = 0x5be0cd19; + p->count = 0; +} + +#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22)) +#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25)) +#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) +#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) + +#define blk0(i) (W[i]) +#define blk2(i) (W[i] += s1(W[((i)-2)&15]) + W[((i)-7)&15] + s0(W[((i)-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + +#ifdef _SHA256_UNROLL2 + +#define R(a,b,c,d,e,f,g,h, i) \ + h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + (j ? blk2(i) : blk0(i)); \ + d += h; \ + h += S0(a) + Maj(a, b, c) + +#define RX_8(i) \ + R(a,b,c,d,e,f,g,h, i); \ + R(h,a,b,c,d,e,f,g, i+1); \ + R(g,h,a,b,c,d,e,f, i+2); \ + R(f,g,h,a,b,c,d,e, i+3); \ + R(e,f,g,h,a,b,c,d, i+4); \ + R(d,e,f,g,h,a,b,c, i+5); \ + R(c,d,e,f,g,h,a,b, i+6); \ + R(b,c,d,e,f,g,h,a, i+7) + +#define RX_16 RX_8(0); RX_8(8); + +#else + +#define a(i) T[(0-(i))&7] +#define b(i) T[(1-(i))&7] +#define c(i) T[(2-(i))&7] +#define d(i) T[(3-(i))&7] +#define e(i) T[(4-(i))&7] +#define f(i) T[(5-(i))&7] +#define g(i) T[(6-(i))&7] +#define h(i) T[(7-(i))&7] + +#define R(i) \ + h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+(size_t)(j)] + (j ? blk2(i) : blk0(i)); \ + d(i) += h(i); \ + h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) \ + +#ifdef _SHA256_UNROLL + +#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7); +#define RX_16 RX_8(0); RX_8(8); + +#else + +#define RX_16 unsigned i; for (i = 0; i < 16; i++) { R(i); } + +#endif + +#endif + +static const UInt32 K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static void Sha256_WriteByteBlock(CSha256 *p) +{ + UInt32 W[16]; + unsigned j; + UInt32 *state; + + #ifdef _SHA256_UNROLL2 + UInt32 a,b,c,d,e,f,g,h; + #else + UInt32 T[8]; + #endif + + for (j = 0; j < 16; j += 4) + { + const Byte *ccc = p->buffer + j * 4; + W[j ] = GetBe32(ccc); + W[j + 1] = GetBe32(ccc + 4); + W[j + 2] = GetBe32(ccc + 8); + W[j + 3] = GetBe32(ccc + 12); + } + + state = p->state; + + #ifdef _SHA256_UNROLL2 + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + #else + for (j = 0; j < 8; j++) + T[j] = state[j]; + #endif + + for (j = 0; j < 64; j += 16) + { + RX_16 + } + + #ifdef _SHA256_UNROLL2 + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + #else + for (j = 0; j < 8; j++) + state[j] += T[j]; + #endif + + /* Wipe variables */ + /* memset(W, 0, sizeof(W)); */ + /* memset(T, 0, sizeof(T)); */ +} + +#undef S0 +#undef S1 +#undef s0 +#undef s1 + +void Sha256_Update(CSha256 *p, const Byte *data, size_t size) +{ + if (size == 0) + return; + + { + unsigned pos = (unsigned)p->count & 0x3F; + unsigned num; + + p->count += size; + + num = 64 - pos; + if (num > size) + { + memcpy(p->buffer + pos, data, size); + return; + } + + size -= num; + memcpy(p->buffer + pos, data, num); + data += num; + } + + for (;;) + { + Sha256_WriteByteBlock(p); + if (size < 64) + break; + size -= 64; + memcpy(p->buffer, data, 64); + data += 64; + } + + if (size != 0) + memcpy(p->buffer, data, size); +} + +void Sha256_Final(CSha256 *p, Byte *digest) +{ + unsigned pos = (unsigned)p->count & 0x3F; + unsigned i; + + p->buffer[pos++] = 0x80; + + while (pos != (64 - 8)) + { + pos &= 0x3F; + if (pos == 0) + Sha256_WriteByteBlock(p); + p->buffer[pos++] = 0; + } + + { + UInt64 numBits = (p->count << 3); + SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32)); + SetBe32(p->buffer + 64 - 4, (UInt32)(numBits)); + } + + Sha256_WriteByteBlock(p); + + for (i = 0; i < 8; i += 2) + { + UInt32 v0 = p->state[i]; + UInt32 v1 = p->state[i + 1]; + SetBe32(digest , v0); + SetBe32(digest + 4, v1); + digest += 8; + } + + Sha256_Init(p); +} diff --git a/other-licenses/7zstub/src/C/Sha256.h b/other-licenses/7zstub/src/C/Sha256.h new file mode 100644 index 0000000000..7f17ccf9c9 --- /dev/null +++ b/other-licenses/7zstub/src/C/Sha256.h @@ -0,0 +1,26 @@ +/* Sha256.h -- SHA-256 Hash +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __CRYPTO_SHA256_H +#define __CRYPTO_SHA256_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define SHA256_DIGEST_SIZE 32 + +typedef struct +{ + UInt32 state[8]; + UInt64 count; + Byte buffer[64]; +} CSha256; + +void Sha256_Init(CSha256 *p); +void Sha256_Update(CSha256 *p, const Byte *data, size_t size); +void Sha256_Final(CSha256 *p, Byte *digest); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Sort.c b/other-licenses/7zstub/src/C/Sort.c new file mode 100644 index 0000000000..73dcbf0596 --- /dev/null +++ b/other-licenses/7zstub/src/C/Sort.c @@ -0,0 +1,141 @@ +/* Sort.c -- Sort functions +2014-04-05 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Sort.h" + +#define HeapSortDown(p, k, size, temp) \ + { for (;;) { \ + size_t s = (k << 1); \ + if (s > size) break; \ + if (s < size && p[s + 1] > p[s]) s++; \ + if (temp >= p[s]) break; \ + p[k] = p[s]; k = s; \ + } p[k] = temp; } + +void HeapSort(UInt32 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt32 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt32 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt32 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt32 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + +void HeapSort64(UInt64 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt64 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt64 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt64 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt64 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + +/* +#define HeapSortRefDown(p, vals, n, size, temp) \ + { size_t k = n; UInt32 val = vals[temp]; for (;;) { \ + size_t s = (k << 1); \ + if (s > size) break; \ + if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ + if (val >= vals[p[s]]) break; \ + p[k] = p[s]; k = s; \ + } p[k] = temp; } + +void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt32 temp = p[i]; + HeapSortRefDown(p, vals, i, size, temp); + } + while (--i != 0); + } + do + { + UInt32 temp = p[size]; + p[size--] = p[1]; + HeapSortRefDown(p, vals, 1, size, temp); + } + while (size > 1); +} +*/ diff --git a/other-licenses/7zstub/src/C/Sort.h b/other-licenses/7zstub/src/C/Sort.h new file mode 100644 index 0000000000..7209d7824d --- /dev/null +++ b/other-licenses/7zstub/src/C/Sort.h @@ -0,0 +1,18 @@ +/* Sort.h -- Sort functions +2014-04-05 : Igor Pavlov : Public domain */ + +#ifndef __7Z_SORT_H +#define __7Z_SORT_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void HeapSort(UInt32 *p, size_t size); +void HeapSort64(UInt64 *p, size_t size); + +/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */ + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Threads.c b/other-licenses/7zstub/src/C/Threads.c new file mode 100644 index 0000000000..8fd86f224b --- /dev/null +++ b/other-licenses/7zstub/src/C/Threads.c @@ -0,0 +1,95 @@ +/* Threads.c -- multithreading library +2017-06-26 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifndef UNDER_CE +#include +#endif + +#include "Threads.h" + +static WRes GetError() +{ + DWORD res = GetLastError(); + return res ? (WRes)res : 1; +} + +static WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); } +static WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } + +WRes HandlePtr_Close(HANDLE *p) +{ + if (*p != NULL) + { + if (!CloseHandle(*p)) + return GetError(); + *p = NULL; + } + return 0; +} + +WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) +{ + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + + #ifdef UNDER_CE + + DWORD threadId; + *p = CreateThread(0, 0, func, param, 0, &threadId); + + #else + + unsigned threadId; + *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); + + #endif + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return HandleToWRes(*p); +} + +static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) +{ + *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); + return HandleToWRes(*p); +} + +WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); } +WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); + return HandleToWRes(*p); +} + +static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) + { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) + { return Semaphore_Release(p, (LONG)num, NULL); } +WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } + +WRes CriticalSection_Init(CCriticalSection *p) +{ + /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ + #ifdef _MSC_VER + __try + #endif + { + InitializeCriticalSection(p); + /* InitializeCriticalSectionAndSpinCount(p, 0); */ + } + #ifdef _MSC_VER + __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } + #endif + return 0; +} diff --git a/other-licenses/7zstub/src/C/Threads.h b/other-licenses/7zstub/src/C/Threads.h new file mode 100644 index 0000000000..f913241aea --- /dev/null +++ b/other-licenses/7zstub/src/C/Threads.h @@ -0,0 +1,68 @@ +/* Threads.h -- multithreading library +2017-06-18 : Igor Pavlov : Public domain */ + +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H + +#ifdef _WIN32 +#include +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +WRes HandlePtr_Close(HANDLE *h); +WRes Handle_WaitObject(HANDLE h); + +typedef HANDLE CThread; +#define Thread_Construct(p) *(p) = NULL +#define Thread_WasCreated(p) (*(p) != NULL) +#define Thread_Close(p) HandlePtr_Close(p) +#define Thread_Wait(p) Handle_WaitObject(*(p)) + +typedef +#ifdef UNDER_CE + DWORD +#else + unsigned +#endif + THREAD_FUNC_RET_TYPE; + +#define THREAD_FUNC_CALL_TYPE MY_STD_CALL +#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE +typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); + +typedef HANDLE CEvent; +typedef CEvent CAutoResetEvent; +typedef CEvent CManualResetEvent; +#define Event_Construct(p) *(p) = NULL +#define Event_IsCreated(p) (*(p) != NULL) +#define Event_Close(p) HandlePtr_Close(p) +#define Event_Wait(p) Handle_WaitObject(*(p)) +WRes Event_Set(CEvent *p); +WRes Event_Reset(CEvent *p); +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); + +typedef HANDLE CSemaphore; +#define Semaphore_Construct(p) *(p) = NULL +#define Semaphore_IsCreated(p) (*(p) != NULL) +#define Semaphore_Close(p) HandlePtr_Close(p) +#define Semaphore_Wait(p) Handle_WaitObject(*(p)) +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); +WRes Semaphore_Release1(CSemaphore *p); + +typedef CRITICAL_SECTION CCriticalSection; +WRes CriticalSection_Init(CCriticalSection *p); +#define CriticalSection_Delete(p) DeleteCriticalSection(p) +#define CriticalSection_Enter(p) EnterCriticalSection(p) +#define CriticalSection_Leave(p) LeaveCriticalSection(p) + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/Util/7z/7z.dsp b/other-licenses/7zstub/src/C/Util/7z/7z.dsp new file mode 100644 index 0000000000..d3bf0fe00d --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/7z/7z.dsp @@ -0,0 +1,241 @@ +# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=7z - 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 "7z.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 "7z.mak" CFG="7z - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "7z - 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)" == "7z - 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 /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAcs /Yu"Precomp.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# 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\7zDec.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "7z - 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 /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.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\7zDec.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "7z - Win32 Release" +# Name "7z - Win32 Debug" +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\7z.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zArcIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrcOpt.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zDec.c +# ADD CPP /D "_7ZIP_PPMD_SUPPPORT" +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra86.c +# End Source File +# Begin Source File + +SOURCE=..\..\BraIA64.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\Delta.c +# End Source File +# Begin Source File + +SOURCE=..\..\Delta.h +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.c +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7.c +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7Dec.c +# End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compiler.h +# End Source File +# Begin Source File + +SOURCE=.\Precomp.c +# ADD CPP /Yc"Precomp.h" +# End Source File +# Begin Source File + +SOURCE=.\Precomp.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\7zMain.c +# End Source File +# End Target +# End Project diff --git a/other-licenses/7zstub/src/C/Util/7z/7z.dsw b/other-licenses/7zstub/src/C/Util/7z/7z.dsw new file mode 100644 index 0000000000..23089fb79f --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/7z/7z.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "7z"=.\7z.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/other-licenses/7zstub/src/C/Util/7z/7zMain.c b/other-licenses/7zstub/src/C/Util/7z/7zMain.c new file mode 100644 index 0000000000..82aac89eb6 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/7z/7zMain.c @@ -0,0 +1,686 @@ +/* 7zMain.c - Test application for 7z Decoder +2018-04-19 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include +#include + +#include "../../CpuArch.h" + +#include "../../7z.h" +#include "../../7zAlloc.h" +#include "../../7zBuf.h" +#include "../../7zCrc.h" +#include "../../7zFile.h" +#include "../../7zVersion.h" + +#ifndef USE_WINDOWS_FILE +/* for mkdir */ +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#endif + + +#define kInputBufSize ((size_t)1 << 18) + +static const ISzAlloc g_Alloc = { SzAlloc, SzFree }; + + +static void Print(const char *s) +{ + fputs(s, stdout); +} + + +static int Buf_EnsureSize(CBuf *dest, size_t size) +{ + if (dest->size >= size) + return 1; + Buf_Free(dest, &g_Alloc); + return Buf_Create(dest, size, &g_Alloc); +} + +#ifndef _WIN32 +#define _USE_UTF8 +#endif + +/* #define _USE_UTF8 */ + +#ifdef _USE_UTF8 + +#define _UTF8_START(n) (0x100 - (1 << (7 - (n)))) + +#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) + +#define _UTF8_HEAD(n, val) ((Byte)(_UTF8_START(n) + (val >> (6 * (n))))) +#define _UTF8_CHAR(n, val) ((Byte)(0x80 + (((val) >> (6 * (n))) & 0x3F))) + +static size_t Utf16_To_Utf8_Calc(const UInt16 *src, const UInt16 *srcLim) +{ + size_t size = 0; + for (;;) + { + UInt32 val; + if (src == srcLim) + return size; + + size++; + val = *src++; + + if (val < 0x80) + continue; + + if (val < _UTF8_RANGE(1)) + { + size++; + continue; + } + + if (val >= 0xD800 && val < 0xDC00 && src != srcLim) + { + UInt32 c2 = *src; + if (c2 >= 0xDC00 && c2 < 0xE000) + { + src++; + size += 3; + continue; + } + } + + size += 2; + } +} + +static Byte *Utf16_To_Utf8(Byte *dest, const UInt16 *src, const UInt16 *srcLim) +{ + for (;;) + { + UInt32 val; + if (src == srcLim) + return dest; + + val = *src++; + + if (val < 0x80) + { + *dest++ = (char)val; + continue; + } + + if (val < _UTF8_RANGE(1)) + { + dest[0] = _UTF8_HEAD(1, val); + dest[1] = _UTF8_CHAR(0, val); + dest += 2; + continue; + } + + if (val >= 0xD800 && val < 0xDC00 && src != srcLim) + { + UInt32 c2 = *src; + if (c2 >= 0xDC00 && c2 < 0xE000) + { + src++; + val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; + dest[0] = _UTF8_HEAD(3, val); + dest[1] = _UTF8_CHAR(2, val); + dest[2] = _UTF8_CHAR(1, val); + dest[3] = _UTF8_CHAR(0, val); + dest += 4; + continue; + } + } + + dest[0] = _UTF8_HEAD(2, val); + dest[1] = _UTF8_CHAR(1, val); + dest[2] = _UTF8_CHAR(0, val); + dest += 3; + } +} + +static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen) +{ + size_t destLen = Utf16_To_Utf8_Calc(src, src + srcLen); + destLen += 1; + if (!Buf_EnsureSize(dest, destLen)) + return SZ_ERROR_MEM; + *Utf16_To_Utf8(dest->data, src, src + srcLen) = 0; + return SZ_OK; +} + +#endif + +static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s + #ifndef _USE_UTF8 + , UINT codePage + #endif + ) +{ + unsigned len = 0; + for (len = 0; s[len] != 0; len++); + + #ifndef _USE_UTF8 + { + unsigned size = len * 3 + 100; + if (!Buf_EnsureSize(buf, size)) + return SZ_ERROR_MEM; + { + buf->data[0] = 0; + if (len != 0) + { + char defaultChar = '_'; + BOOL defUsed; + unsigned numChars = 0; + numChars = WideCharToMultiByte(codePage, 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed); + if (numChars == 0 || numChars >= size) + return SZ_ERROR_FAIL; + buf->data[numChars] = 0; + } + return SZ_OK; + } + } + #else + return Utf16_To_Utf8Buf(buf, s, len); + #endif +} + +#ifdef _WIN32 + #ifndef USE_WINDOWS_FILE + static UINT g_FileCodePage = CP_ACP; + #endif + #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage +#else + #define MY_FILE_CODE_PAGE_PARAM +#endif + +static WRes MyCreateDir(const UInt16 *name) +{ + #ifdef USE_WINDOWS_FILE + + return CreateDirectoryW(name, NULL) ? 0 : GetLastError(); + + #else + + CBuf buf; + WRes res; + Buf_Init(&buf); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); + + res = + #ifdef _WIN32 + _mkdir((const char *)buf.data) + #else + mkdir((const char *)buf.data, 0777) + #endif + == 0 ? 0 : errno; + Buf_Free(&buf, &g_Alloc); + return res; + + #endif +} + +static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name) +{ + #ifdef USE_WINDOWS_FILE + return OutFile_OpenW(p, name); + #else + CBuf buf; + WRes res; + Buf_Init(&buf); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); + res = OutFile_Open(p, (const char *)buf.data); + Buf_Free(&buf, &g_Alloc); + return res; + #endif +} + + +static SRes PrintString(const UInt16 *s) +{ + CBuf buf; + SRes res; + Buf_Init(&buf); + res = Utf16_To_Char(&buf, s + #ifndef _USE_UTF8 + , CP_OEMCP + #endif + ); + if (res == SZ_OK) + Print((const char *)buf.data); + Buf_Free(&buf, &g_Alloc); + return res; +} + +static void UInt64ToStr(UInt64 value, char *s, int numDigits) +{ + char temp[32]; + int pos = 0; + do + { + temp[pos++] = (char)('0' + (unsigned)(value % 10)); + value /= 10; + } + while (value != 0); + + for (numDigits -= pos; numDigits > 0; numDigits--) + *s++ = ' '; + + do + *s++ = temp[--pos]; + while (pos); + *s = '\0'; +} + +static char *UIntToStr(char *s, unsigned value, int numDigits) +{ + char temp[16]; + int pos = 0; + do + temp[pos++] = (char)('0' + (value % 10)); + while (value /= 10); + + for (numDigits -= pos; numDigits > 0; numDigits--) + *s++ = '0'; + + do + *s++ = temp[--pos]; + while (pos); + *s = '\0'; + return s; +} + +static void UIntToStr_2(char *s, unsigned value) +{ + s[0] = (char)('0' + (value / 10)); + s[1] = (char)('0' + (value % 10)); +} + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + +static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s) +{ + unsigned year, mon, hour, min, sec; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned t; + UInt32 v; + UInt64 v64 = nt->Low | ((UInt64)nt->High << 32); + v64 /= 10000000; + sec = (unsigned)(v64 % 60); v64 /= 60; + min = (unsigned)(v64 % 60); v64 /= 60; + hour = (unsigned)(v64 % 24); v64 /= 24; + + v = (UInt32)v64; + + year = (unsigned)(1601 + v / PERIOD_400 * 400); + v %= PERIOD_400; + + t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100; + t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4; + t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 0;; mon++) + { + unsigned d = ms[mon]; + if (v < d) + break; + v -= d; + } + s = UIntToStr(s, year, 4); *s++ = '-'; + UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3; + UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3; + UIntToStr_2(s, hour); s[2] = ':'; s += 3; + UIntToStr_2(s, min); s[2] = ':'; s += 3; + UIntToStr_2(s, sec); s[2] = 0; +} + +static void PrintLF() +{ + Print("\n"); +} + +static void PrintError(char *s) +{ + Print("\nERROR: "); + Print(s); + PrintLF(); +} + +static void GetAttribString(UInt32 wa, Bool isDir, char *s) +{ + #ifdef USE_WINDOWS_FILE + s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.'); + s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.'); + s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.'); + s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.'); + s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.'); + s[5] = 0; + #else + s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.'); + s[1] = 0; + #endif +} + + +// #define NUM_PARENTS_MAX 128 + +int MY_CDECL main(int numargs, char *args[]) +{ + ISzAlloc allocImp; + ISzAlloc allocTempImp; + + CFileInStream archiveStream; + CLookToRead2 lookStream; + CSzArEx db; + SRes res; + UInt16 *temp = NULL; + size_t tempSize = 0; + // UInt32 parents[NUM_PARENTS_MAX]; + + Print("\n7z Decoder " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"); + + if (numargs == 1) + { + Print( + "Usage: 7zDec \n\n" + "\n" + " e: Extract files from archive (without using directory names)\n" + " l: List contents of archive\n" + " t: Test integrity of archive\n" + " x: eXtract files with full paths\n"); + return 0; + } + + if (numargs < 3) + { + PrintError("incorrect command"); + return 1; + } + + #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE) + g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif + + + allocImp = g_Alloc; + allocTempImp = g_Alloc; + + #ifdef UNDER_CE + if (InFile_OpenW(&archiveStream.file, L"\test.7z")) + #else + if (InFile_Open(&archiveStream.file, args[2])) + #endif + { + PrintError("can not open input file"); + return 1; + } + + FileInStream_CreateVTable(&archiveStream); + LookToRead2_CreateVTable(&lookStream, False); + lookStream.buf = NULL; + + res = SZ_OK; + + { + lookStream.buf = ISzAlloc_Alloc(&allocImp, kInputBufSize); + if (!lookStream.buf) + res = SZ_ERROR_MEM; + else + { + lookStream.bufSize = kInputBufSize; + lookStream.realStream = &archiveStream.vt; + LookToRead2_Init(&lookStream); + } + } + + CrcGenerateTable(); + + SzArEx_Init(&db); + + if (res == SZ_OK) + { + res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp); + } + + if (res == SZ_OK) + { + char *command = args[1]; + int listCommand = 0, testCommand = 0, fullPaths = 0; + + if (strcmp(command, "l") == 0) listCommand = 1; + else if (strcmp(command, "t") == 0) testCommand = 1; + else if (strcmp(command, "e") == 0) { } + else if (strcmp(command, "x") == 0) { fullPaths = 1; } + else + { + PrintError("incorrect command"); + res = SZ_ERROR_FAIL; + } + + if (res == SZ_OK) + { + UInt32 i; + + /* + if you need cache, use these 3 variables. + if you use external function, you can make these variable as static. + */ + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ + + for (i = 0; i < db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + // const CSzFileItem *f = db.Files + i; + size_t len; + unsigned isDir = SzArEx_IsDir(&db, i); + if (listCommand == 0 && isDir && !fullPaths) + continue; + len = SzArEx_GetFileNameUtf16(&db, i, NULL); + // len = SzArEx_GetFullNameLen(&db, i); + + if (len > tempSize) + { + SzFree(NULL, temp); + tempSize = len; + temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); + if (!temp) + { + res = SZ_ERROR_MEM; + break; + } + } + + SzArEx_GetFileNameUtf16(&db, i, temp); + /* + if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp) + { + res = SZ_ERROR_FAIL; + break; + } + */ + + if (listCommand) + { + char attr[8], s[32], t[32]; + UInt64 fileSize; + + GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); + + fileSize = SzArEx_GetFileSize(&db, i); + UInt64ToStr(fileSize, s, 10); + + if (SzBitWithVals_Check(&db.MTime, i)) + ConvertFileTimeToString(&db.MTime.Vals[i], t); + else + { + size_t j; + for (j = 0; j < 19; j++) + t[j] = ' '; + t[j] = '\0'; + } + + Print(t); + Print(" "); + Print(attr); + Print(" "); + Print(s); + Print(" "); + res = PrintString(temp); + if (res != SZ_OK) + break; + if (isDir) + Print("/"); + PrintLF(); + continue; + } + + Print(testCommand ? + "Testing ": + "Extracting "); + res = PrintString(temp); + if (res != SZ_OK) + break; + + if (isDir) + Print("/"); + else + { + res = SzArEx_Extract(&db, &lookStream.vt, i, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + if (res != SZ_OK) + break; + } + + if (!testCommand) + { + CSzFile outFile; + size_t processedSize; + size_t j; + UInt16 *name = (UInt16 *)temp; + const UInt16 *destPath = (const UInt16 *)name; + + for (j = 0; name[j] != 0; j++) + if (name[j] == '/') + { + if (fullPaths) + { + name[j] = 0; + MyCreateDir(name); + name[j] = CHAR_PATH_SEPARATOR; + } + else + destPath = name + j + 1; + } + + if (isDir) + { + MyCreateDir(destPath); + PrintLF(); + continue; + } + else if (OutFile_OpenUtf16(&outFile, destPath)) + { + PrintError("can not open output file"); + res = SZ_ERROR_FAIL; + break; + } + + processedSize = outSizeProcessed; + + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) + { + PrintError("can not write output file"); + res = SZ_ERROR_FAIL; + break; + } + + #ifdef USE_WINDOWS_FILE + { + FILETIME mtime, ctime; + FILETIME *mtimePtr = NULL; + FILETIME *ctimePtr = NULL; + + if (SzBitWithVals_Check(&db.MTime, i)) + { + const CNtfsFileTime *t = &db.MTime.Vals[i]; + mtime.dwLowDateTime = (DWORD)(t->Low); + mtime.dwHighDateTime = (DWORD)(t->High); + mtimePtr = &mtime; + } + if (SzBitWithVals_Check(&db.CTime, i)) + { + const CNtfsFileTime *t = &db.CTime.Vals[i]; + ctime.dwLowDateTime = (DWORD)(t->Low); + ctime.dwHighDateTime = (DWORD)(t->High); + ctimePtr = &ctime; + } + if (mtimePtr || ctimePtr) + SetFileTime(outFile.handle, ctimePtr, NULL, mtimePtr); + } + #endif + + if (File_Close(&outFile)) + { + PrintError("can not close output file"); + res = SZ_ERROR_FAIL; + break; + } + + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.Attribs, i)) + { + UInt32 attrib = db.Attribs.Vals[i]; + /* p7zip stores posix attributes in high 16 bits and adds 0x8000 as marker. + We remove posix bits, if we detect posix mode field */ + if ((attrib & 0xF0000000) != 0) + attrib &= 0x7FFF; + SetFileAttributesW(destPath, attrib); + } + #endif + } + PrintLF(); + } + ISzAlloc_Free(&allocImp, outBuffer); + } + } + + SzFree(NULL, temp); + SzArEx_Free(&db, &allocImp); + ISzAlloc_Free(&allocImp, lookStream.buf); + + File_Close(&archiveStream.file); + + if (res == SZ_OK) + { + Print("\nEverything is Ok\n"); + return 0; + } + + if (res == SZ_ERROR_UNSUPPORTED) + PrintError("decoder doesn't support this archive"); + else if (res == SZ_ERROR_MEM) + PrintError("can not allocate memory"); + else if (res == SZ_ERROR_CRC) + PrintError("CRC error"); + else + { + char s[32]; + UInt64ToStr(res, s, 0); + PrintError(s); + } + + return 1; +} diff --git a/other-licenses/7zstub/src/C/Util/7z/Precomp.c b/other-licenses/7zstub/src/C/Util/7z/Precomp.c new file mode 100644 index 0000000000..34b60f8fc1 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/7z/Precomp.c @@ -0,0 +1,4 @@ +/* Precomp.c -- StdAfx +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" diff --git a/other-licenses/7zstub/src/C/Util/7z/Precomp.h b/other-licenses/7zstub/src/C/Util/7z/Precomp.h new file mode 100644 index 0000000000..9f398d08fd --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/7z/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-06-16 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "../../Compiler.h" +#include "../../7zTypes.h" + +#endif diff --git a/other-licenses/7zstub/src/C/Util/7z/makefile b/other-licenses/7zstub/src/C/Util/7z/makefile new file mode 100644 index 0000000000..f4a54af73e --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/7z/makefile @@ -0,0 +1,40 @@ +CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT + +PROG = 7zDec.exe + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuf.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zArcIn.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + +7Z_OBJS = \ + $O\7zMain.obj \ + +OBJS = \ + $O\Precomp.obj \ + $(7Z_OBJS) \ + $(C_OBJS) \ + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(CCOMPL_USE) +$(C_OBJS): ../../$(*B).c + $(CCOMPL_USE) +$O\Precomp.obj: Precomp.c + $(CCOMPL_PCH) diff --git a/other-licenses/7zstub/src/C/Util/7z/makefile.gcc b/other-licenses/7zstub/src/C/Util/7z/makefile.gcc new file mode 100644 index 0000000000..f707935aa9 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/7z/makefile.gcc @@ -0,0 +1,75 @@ +PROG = 7zDec +CXX = gcc +LIB = +RM = rm -f +CFLAGS = -c -O2 -Wall + +OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o Delta.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o BraIA64.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o + +all: $(PROG) + +$(PROG): $(OBJS) + $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) + +7zMain.o: 7zMain.c + $(CXX) $(CFLAGS) 7zMain.c + +7zAlloc.o: ../../7zAlloc.c + $(CXX) $(CFLAGS) ../../7zAlloc.c + +7zArcIn.o: ../../7zArcIn.c + $(CXX) $(CFLAGS) ../../7zArcIn.c + +7zBuf.o: ../../7zBuf.c + $(CXX) $(CFLAGS) ../../7zBuf.c + +7zBuf2.o: ../../7zBuf2.c + $(CXX) $(CFLAGS) ../../7zBuf2.c + +7zCrc.o: ../../7zCrc.c + $(CXX) $(CFLAGS) ../../7zCrc.c + +7zCrcOpt.o: ../../7zCrc.c + $(CXX) $(CFLAGS) ../../7zCrcOpt.c + +7zDec.o: ../../7zDec.c + $(CXX) $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT ../../7zDec.c + +CpuArch.o: ../../CpuArch.c + $(CXX) $(CFLAGS) ../../CpuArch.c + +Delta.o: ../../Delta.c + $(CXX) $(CFLAGS) ../../Delta.c + +LzmaDec.o: ../../LzmaDec.c + $(CXX) $(CFLAGS) ../../LzmaDec.c + +Lzma2Dec.o: ../../Lzma2Dec.c + $(CXX) $(CFLAGS) ../../Lzma2Dec.c + +Bra.o: ../../Bra.c + $(CXX) $(CFLAGS) ../../Bra.c + +Bra86.o: ../../Bra86.c + $(CXX) $(CFLAGS) ../../Bra86.c + +BraIA64.o: ../../BraIA64.c + $(CXX) $(CFLAGS) ../../BraIA64.c + +Bcj2.o: ../../Bcj2.c + $(CXX) $(CFLAGS) ../../Bcj2.c + +Ppmd7.o: ../../Ppmd7.c + $(CXX) $(CFLAGS) ../../Ppmd7.c + +Ppmd7Dec.o: ../../Ppmd7Dec.c + $(CXX) $(CFLAGS) ../../Ppmd7Dec.c + +7zFile.o: ../../7zFile.c + $(CXX) $(CFLAGS) ../../7zFile.c + +7zStream.o: ../../7zStream.c + $(CXX) $(CFLAGS) ../../7zStream.c + +clean: + -$(RM) $(PROG) $(OBJS) diff --git a/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.c b/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.c new file mode 100644 index 0000000000..cf88c7778f --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.c @@ -0,0 +1,258 @@ +/* LzmaUtil.c -- Test application for LZMA compression +2017-04-27 : Igor Pavlov : Public domain */ + +#include "../../Precomp.h" + +#include +#include +#include + +#include "../../CpuArch.h" + +#include "../../Alloc.h" +#include "../../7zFile.h" +#include "../../7zVersion.h" +#include "../../LzmaDec.h" +#include "../../LzmaEnc.h" + +static const char * const kCantReadMessage = "Can not read input file"; +static const char * const kCantWriteMessage = "Can not write output file"; +static const char * const kCantAllocateMessage = "Can not allocate memory"; +static const char * const kDataErrorMessage = "Data error"; + +static void PrintHelp(char *buffer) +{ + strcat(buffer, + "\nLZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n" + "Usage: lzma inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n"); +} + +static int PrintError(char *buffer, const char *message) +{ + strcat(buffer, "\nError: "); + strcat(buffer, message); + strcat(buffer, "\n"); + return 1; +} + +static int PrintErrorNumber(char *buffer, SRes val) +{ + sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); + return 1; +} + +static int PrintUserError(char *buffer) +{ + return PrintError(buffer, "Incorrect command"); +} + + +#define IN_BUF_SIZE (1 << 16) +#define OUT_BUF_SIZE (1 << 16) + + +static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, + UInt64 unpackSize) +{ + int thereIsSize = (unpackSize != (UInt64)(Int64)-1); + Byte inBuf[IN_BUF_SIZE]; + Byte outBuf[OUT_BUF_SIZE]; + size_t inPos = 0, inSize = 0, outPos = 0; + LzmaDec_Init(state); + for (;;) + { + if (inPos == inSize) + { + inSize = IN_BUF_SIZE; + RINOK(inStream->Read(inStream, inBuf, &inSize)); + inPos = 0; + } + { + SRes res; + SizeT inProcessed = inSize - inPos; + SizeT outProcessed = OUT_BUF_SIZE - outPos; + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + ELzmaStatus status; + if (thereIsSize && outProcessed > unpackSize) + { + outProcessed = (SizeT)unpackSize; + finishMode = LZMA_FINISH_END; + } + + res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, + inBuf + inPos, &inProcessed, finishMode, &status); + inPos += inProcessed; + outPos += outProcessed; + unpackSize -= outProcessed; + + if (outStream) + if (outStream->Write(outStream, outBuf, outPos) != outPos) + return SZ_ERROR_WRITE; + + outPos = 0; + + if (res != SZ_OK || (thereIsSize && unpackSize == 0)) + return res; + + if (inProcessed == 0 && outProcessed == 0) + { + if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) + return SZ_ERROR_DATA; + return res; + } + } + } +} + + +static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) +{ + UInt64 unpackSize; + int i; + SRes res = 0; + + CLzmaDec state; + + /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ + unsigned char header[LZMA_PROPS_SIZE + 8]; + + /* Read and parse header */ + + RINOK(SeqInStream_Read(inStream, header, sizeof(header))); + + unpackSize = 0; + for (i = 0; i < 8; i++) + unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); + + LzmaDec_Construct(&state); + RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); + res = Decode2(&state, outStream, inStream, unpackSize); + LzmaDec_Free(&state, &g_Alloc); + return res; +} + +static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) +{ + CLzmaEncHandle enc; + SRes res; + CLzmaEncProps props; + + UNUSED_VAR(rs); + + enc = LzmaEnc_Create(&g_Alloc); + if (enc == 0) + return SZ_ERROR_MEM; + + LzmaEncProps_Init(&props); + res = LzmaEnc_SetProps(enc, &props); + + if (res == SZ_OK) + { + Byte header[LZMA_PROPS_SIZE + 8]; + size_t headerSize = LZMA_PROPS_SIZE; + int i; + + res = LzmaEnc_WriteProperties(enc, header, &headerSize); + for (i = 0; i < 8; i++) + header[headerSize++] = (Byte)(fileSize >> (8 * i)); + if (outStream->Write(outStream, header, headerSize) != headerSize) + res = SZ_ERROR_WRITE; + else + { + if (res == SZ_OK) + res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); + } + } + LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); + return res; +} + + +static int main2(int numArgs, const char *args[], char *rs) +{ + CFileSeqInStream inStream; + CFileOutStream outStream; + char c; + int res; + int encodeMode; + Bool useOutFile = False; + + FileSeqInStream_CreateVTable(&inStream); + File_Construct(&inStream.file); + + FileOutStream_CreateVTable(&outStream); + File_Construct(&outStream.file); + + if (numArgs == 1) + { + PrintHelp(rs); + return 0; + } + + if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) + return PrintUserError(rs); + + c = args[1][0]; + encodeMode = (c == 'e' || c == 'E'); + if (!encodeMode && c != 'd' && c != 'D') + return PrintUserError(rs); + + { + size_t t4 = sizeof(UInt32); + size_t t8 = sizeof(UInt64); + if (t4 != 4 || t8 != 8) + return PrintError(rs, "Incorrect UInt32 or UInt64"); + } + + if (InFile_Open(&inStream.file, args[2]) != 0) + return PrintError(rs, "Can not open input file"); + + if (numArgs > 3) + { + useOutFile = True; + if (OutFile_Open(&outStream.file, args[3]) != 0) + return PrintError(rs, "Can not open output file"); + } + else if (encodeMode) + PrintUserError(rs); + + if (encodeMode) + { + UInt64 fileSize; + File_GetLength(&inStream.file, &fileSize); + res = Encode(&outStream.vt, &inStream.vt, fileSize, rs); + } + else + { + res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL); + } + + if (useOutFile) + File_Close(&outStream.file); + File_Close(&inStream.file); + + if (res != SZ_OK) + { + if (res == SZ_ERROR_MEM) + return PrintError(rs, kCantAllocateMessage); + else if (res == SZ_ERROR_DATA) + return PrintError(rs, kDataErrorMessage); + else if (res == SZ_ERROR_WRITE) + return PrintError(rs, kCantWriteMessage); + else if (res == SZ_ERROR_READ) + return PrintError(rs, kCantReadMessage); + return PrintErrorNumber(rs, res); + } + return 0; +} + + +int MY_CDECL main(int numArgs, const char *args[]) +{ + char rs[800] = { 0 }; + int res = main2(numArgs, args, rs); + fputs(rs, stdout); + return res; +} diff --git a/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsp b/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsp new file mode 100644 index 0000000000..eedde07d89 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsp @@ -0,0 +1,168 @@ +# Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=LzmaUtil - 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 "LzmaUtil.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 "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "LzmaUtil - 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)" == "LzmaUtil - 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 /MT /W4 /WX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# 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\7lzma.exe" + +!ELSEIF "$(CFG)" == "LzmaUtil - 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 /MTd /W4 /WX /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX +# 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\7lzma.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "LzmaUtil - Win32 Release" +# Name "LzmaUtil - Win32 Debug" +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zVersion.h +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=.\LzmaUtil.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.h +# End Source File +# End Target +# End Project diff --git a/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsw b/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsw new file mode 100644 index 0000000000..f43548752f --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/Lzma/LzmaUtil.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/other-licenses/7zstub/src/C/Util/Lzma/makefile b/other-licenses/7zstub/src/C/Util/Lzma/makefile new file mode 100644 index 0000000000..3b825f21ac --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/Lzma/makefile @@ -0,0 +1,28 @@ +# MY_STATIC_LINK=1 +PROG = LZMAc.exe + +CFLAGS = $(CFLAGS) \ + +LIB_OBJS = \ + $O\LzmaUtil.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\7zFile.obj \ + $O\7zStream.obj \ + $O\Threads.obj \ + +OBJS = \ + $(LIB_OBJS) \ + $(C_OBJS) \ + +!include "../../../CPP/Build.mak" + +$(LIB_OBJS): $(*B).c + $(COMPL_O2) +$(C_OBJS): ../../$(*B).c + $(COMPL_O2) diff --git a/other-licenses/7zstub/src/C/Util/Lzma/makefile.gcc b/other-licenses/7zstub/src/C/Util/Lzma/makefile.gcc new file mode 100644 index 0000000000..12a72bb8b9 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/Lzma/makefile.gcc @@ -0,0 +1,44 @@ +PROG = lzma +CXX = g++ +LIB = +RM = rm -f +CFLAGS = -c -O2 -Wall -D_7ZIP_ST + +OBJS = \ + LzmaUtil.o \ + Alloc.o \ + LzFind.o \ + LzmaDec.o \ + LzmaEnc.o \ + 7zFile.o \ + 7zStream.o \ + + +all: $(PROG) + +$(PROG): $(OBJS) + $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) + +LzmaUtil.o: LzmaUtil.c + $(CXX) $(CFLAGS) LzmaUtil.c + +Alloc.o: ../../Alloc.c + $(CXX) $(CFLAGS) ../../Alloc.c + +LzFind.o: ../../LzFind.c + $(CXX) $(CFLAGS) ../../LzFind.c + +LzmaDec.o: ../../LzmaDec.c + $(CXX) $(CFLAGS) ../../LzmaDec.c + +LzmaEnc.o: ../../LzmaEnc.c + $(CXX) $(CFLAGS) ../../LzmaEnc.c + +7zFile.o: ../../7zFile.c + $(CXX) $(CFLAGS) ../../7zFile.c + +7zStream.o: ../../7zStream.c + $(CXX) $(CFLAGS) ../../7zStream.c + +clean: + -$(RM) $(PROG) $(OBJS) diff --git a/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.def b/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.def new file mode 100644 index 0000000000..43b9597781 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.def @@ -0,0 +1,4 @@ +EXPORTS + LzmaCompress + LzmaUncompress + diff --git a/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.dsp b/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.dsp new file mode 100644 index 0000000000..0d4c981c4c --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.dsp @@ -0,0 +1,178 @@ +# Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=LzmaLib - 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 "LzmaLib.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 "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LzmaLib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "LzmaLib - Win32 Release" +# Name "LzmaLib - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\LzmaLib.def +# End Source File +# Begin Source File + +SOURCE=.\LzmaLibExports.c +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\IStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaLib.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaLib.h +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.h +# End Source File +# End Target +# End Project diff --git a/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.dsw b/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.dsw new file mode 100644 index 0000000000..f6c55593f5 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLib.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLibExports.c b/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLibExports.c new file mode 100644 index 0000000000..02600c724f --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/LzmaLib/LzmaLibExports.c @@ -0,0 +1,14 @@ +/* LzmaLibExports.c -- LZMA library DLL Entry point +2015-11-08 : Igor Pavlov : Public domain */ + +#include "../../Precomp.h" + +#include + +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + UNUSED_VAR(hInstance); + UNUSED_VAR(dwReason); + UNUSED_VAR(lpReserved); + return TRUE; +} diff --git a/other-licenses/7zstub/src/C/Util/LzmaLib/makefile b/other-licenses/7zstub/src/C/Util/LzmaLib/makefile new file mode 100644 index 0000000000..e0f311471a --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/LzmaLib/makefile @@ -0,0 +1,34 @@ +MY_STATIC_LINK=1 +SLIB = sLZMA.lib +PROG = LZMA.dll +SLIBPATH = $O\$(SLIB) + +DEF_FILE = LzmaLib.def +CFLAGS = $(CFLAGS) \ + +LIB_OBJS = \ + $O\LzmaLibExports.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\LzmaLib.obj \ + $O\Threads.obj \ + +OBJS = \ + $(LIB_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(SLIBPATH): $O $(OBJS) + lib -out:$(SLIBPATH) $(OBJS) $(LIBS) + +$(LIB_OBJS): $(*B).c + $(COMPL_O2) +$(C_OBJS): ../../$(*B).c + $(COMPL_O2) diff --git a/other-licenses/7zstub/src/C/Util/LzmaLib/resource.rc b/other-licenses/7zstub/src/C/Util/LzmaLib/resource.rc new file mode 100644 index 0000000000..d95e3f3583 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/LzmaLib/resource.rc @@ -0,0 +1,3 @@ +#include "../../7zVersion.rc" + +MY_VERSION_INFO_DLL("LZMA library", "LZMA") diff --git a/other-licenses/7zstub/src/C/Util/SfxSetup/Precomp.c b/other-licenses/7zstub/src/C/Util/SfxSetup/Precomp.c new file mode 100644 index 0000000000..34b60f8fc1 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/SfxSetup/Precomp.c @@ -0,0 +1,4 @@ +/* Precomp.c -- StdAfx +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" diff --git a/other-licenses/7zstub/src/C/Util/SfxSetup/Precomp.h b/other-licenses/7zstub/src/C/Util/SfxSetup/Precomp.h new file mode 100644 index 0000000000..9f398d08fd --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/SfxSetup/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-06-16 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "../../Compiler.h" +#include "../../7zTypes.h" + +#endif diff --git a/other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.c b/other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.c new file mode 100644 index 0000000000..bfbf430251 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.c @@ -0,0 +1,640 @@ +/* SfxSetup.c - 7z SFX Setup +2017-04-04 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef _UNICODE +#define _UNICODE +#endif + +#ifdef _CONSOLE +#include +#endif + +#include "../../7z.h" +#include "../../7zAlloc.h" +#include "../../7zCrc.h" +#include "../../7zFile.h" +#include "../../CpuArch.h" +#include "../../DllSecur.h" + +#define k_EXE_ExtIndex 2 + +#define kInputBufSize ((size_t)1 << 18) + +static const char * const kExts[] = +{ + "bat" + , "cmd" + , "exe" + , "inf" + , "msi" + #ifdef UNDER_CE + , "cab" + #endif + , "html" + , "htm" +}; + +static const char * const kNames[] = +{ + "setup" + , "install" + , "run" + , "start" +}; + +static unsigned FindExt(const wchar_t *s, unsigned *extLen) +{ + unsigned len = (unsigned)wcslen(s); + unsigned i; + for (i = len; i > 0; i--) + { + if (s[i - 1] == '.') + { + *extLen = len - i; + return i - 1; + } + } + *extLen = 0; + return len; +} + +#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c))) + +static unsigned FindItem(const char * const *items, unsigned num, const wchar_t *s, unsigned len) +{ + unsigned i; + for (i = 0; i < num; i++) + { + const char *item = items[i]; + unsigned itemLen = (unsigned)strlen(item); + unsigned j; + if (len != itemLen) + continue; + for (j = 0; j < len; j++) + { + unsigned c = (Byte)item[j]; + if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j]) + break; + } + if (j == len) + return i; + } + return i; +} + +#ifdef _CONSOLE +static BOOL WINAPI HandlerRoutine(DWORD ctrlType) +{ + UNUSED_VAR(ctrlType); + return TRUE; +} +#endif + +static void PrintErrorMessage(const char *message) +{ + #ifdef _CONSOLE + printf("\n7-Zip Error: %s\n", message); + #else + #ifdef UNDER_CE + WCHAR messageW[256 + 4]; + unsigned i; + for (i = 0; i < 256 && message[i] != 0; i++) + messageW[i] = message[i]; + messageW[i] = 0; + MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR); + #else + MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR); + #endif + #endif +} + +static WRes MyCreateDir(const WCHAR *name) +{ + return CreateDirectoryW(name, NULL) ? 0 : GetLastError(); +} + +#ifdef UNDER_CE +#define kBufferSize (1 << 13) +#else +#define kBufferSize (1 << 15) +#endif + +#define kSignatureSearchLimit (1 << 22) + +static Bool FindSignature(CSzFile *stream, UInt64 *resPos) +{ + Byte buf[kBufferSize]; + size_t numPrevBytes = 0; + *resPos = 0; + for (;;) + { + size_t processed, pos; + if (*resPos > kSignatureSearchLimit) + return False; + processed = kBufferSize - numPrevBytes; + if (File_Read(stream, buf + numPrevBytes, &processed) != 0) + return False; + processed += numPrevBytes; + if (processed < k7zStartHeaderSize || + (processed == k7zStartHeaderSize && numPrevBytes != 0)) + return False; + processed -= k7zStartHeaderSize; + for (pos = 0; pos <= processed; pos++) + { + for (; pos <= processed && buf[pos] != '7'; pos++); + if (pos > processed) + break; + if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) + if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) + { + *resPos += pos; + return True; + } + } + *resPos += processed; + numPrevBytes = k7zStartHeaderSize; + memmove(buf, buf + processed, k7zStartHeaderSize); + } +} + +static Bool DoesFileOrDirExist(const WCHAR *path) +{ + WIN32_FIND_DATAW fd; + HANDLE handle; + handle = FindFirstFileW(path, &fd); + if (handle == INVALID_HANDLE_VALUE) + return False; + FindClose(handle); + return True; +} + +static WRes RemoveDirWithSubItems(WCHAR *path) +{ + WIN32_FIND_DATAW fd; + HANDLE handle; + WRes res = 0; + size_t len = wcslen(path); + wcscpy(path + len, L"*"); + handle = FindFirstFileW(path, &fd); + path[len] = L'\0'; + if (handle == INVALID_HANDLE_VALUE) + return GetLastError(); + + for (;;) + { + if (wcscmp(fd.cFileName, L".") != 0 && + wcscmp(fd.cFileName, L"..") != 0) + { + wcscpy(path + len, fd.cFileName); + if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + wcscat(path, WSTRING_PATH_SEPARATOR); + res = RemoveDirWithSubItems(path); + } + else + { + SetFileAttributesW(path, 0); + if (DeleteFileW(path) == 0) + res = GetLastError(); + } + + if (res != 0) + break; + } + + if (!FindNextFileW(handle, &fd)) + { + res = GetLastError(); + if (res == ERROR_NO_MORE_FILES) + res = 0; + break; + } + } + + path[len] = L'\0'; + FindClose(handle); + if (res == 0) + { + if (!RemoveDirectoryW(path)) + res = GetLastError(); + } + return res; +} + +#ifdef _CONSOLE +int MY_CDECL main() +#else +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + lpCmdLine, int nCmdShow) +#endif +{ + CFileInStream archiveStream; + CLookToRead2 lookStream; + CSzArEx db; + SRes res = SZ_OK; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + WCHAR sfxPath[MAX_PATH + 2]; + WCHAR path[MAX_PATH * 3 + 2]; + #ifndef UNDER_CE + WCHAR workCurDir[MAX_PATH + 32]; + #endif + size_t pathLen; + DWORD winRes; + const wchar_t *cmdLineParams; + const char *errorMessage = NULL; + Bool useShellExecute = True; + DWORD exitCode = 0; + + LoadSecurityDlls(); + + #ifdef _CONSOLE + SetConsoleCtrlHandler(HandlerRoutine, TRUE); + #else + UNUSED_VAR(hInstance); + UNUSED_VAR(hPrevInstance); + UNUSED_VAR(lpCmdLine); + UNUSED_VAR(nCmdShow); + #endif + + CrcGenerateTable(); + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + FileInStream_CreateVTable(&archiveStream); + LookToRead2_CreateVTable(&lookStream, False); + lookStream.buf = NULL; + + winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH); + if (winRes == 0 || winRes > MAX_PATH) + return 1; + { + cmdLineParams = GetCommandLineW(); + #ifndef UNDER_CE + { + Bool quoteMode = False; + for (;; cmdLineParams++) + { + wchar_t c = *cmdLineParams; + if (c == L'\"') + quoteMode = !quoteMode; + else if (c == 0 || (c == L' ' && !quoteMode)) + break; + } + } + #endif + } + + { + unsigned i; + DWORD d; + winRes = GetTempPathW(MAX_PATH, path); + if (winRes == 0 || winRes > MAX_PATH) + return 1; + pathLen = wcslen(path); + d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + + for (i = 0;; i++, d += GetTickCount()) + { + if (i >= 100) + { + res = SZ_ERROR_FAIL; + break; + } + wcscpy(path + pathLen, L"7z"); + + { + wchar_t *s = path + wcslen(path); + UInt32 value = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = value & 0xF; + value >>= 4; + s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + } + + if (DoesFileOrDirExist(path)) + continue; + if (CreateDirectoryW(path, NULL)) + { + wcscat(path, WSTRING_PATH_SEPARATOR); + pathLen = wcslen(path); + break; + } + if (GetLastError() != ERROR_ALREADY_EXISTS) + { + res = SZ_ERROR_FAIL; + break; + } + } + + #ifndef UNDER_CE + wcscpy(workCurDir, path); + #endif + if (res != SZ_OK) + errorMessage = "Can't create temp folder"; + } + + if (res != SZ_OK) + { + if (!errorMessage) + errorMessage = "Error"; + PrintErrorMessage(errorMessage); + return 1; + } + + if (InFile_OpenW(&archiveStream.file, sfxPath) != 0) + { + errorMessage = "can not open input file"; + res = SZ_ERROR_FAIL; + } + else + { + UInt64 pos = 0; + if (!FindSignature(&archiveStream.file, &pos)) + res = SZ_ERROR_FAIL; + else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0) + res = SZ_ERROR_FAIL; + if (res != 0) + errorMessage = "Can't find 7z archive"; + } + + if (res == SZ_OK) + { + lookStream.buf = ISzAlloc_Alloc(&allocImp, kInputBufSize); + if (!lookStream.buf) + res = SZ_ERROR_MEM; + else + { + lookStream.bufSize = kInputBufSize; + lookStream.realStream = &archiveStream.vt; + LookToRead2_Init(&lookStream); + } + } + + SzArEx_Init(&db); + + if (res == SZ_OK) + { + res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp); + } + + if (res == SZ_OK) + { + UInt32 executeFileIndex = (UInt32)(Int32)-1; + UInt32 minPrice = 1 << 30; + UInt32 i; + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ + + for (i = 0; i < db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + WCHAR *temp; + + if (SzArEx_GetFileNameUtf16(&db, i, NULL) >= MAX_PATH) + { + res = SZ_ERROR_FAIL; + break; + } + + temp = path + pathLen; + + SzArEx_GetFileNameUtf16(&db, i, temp); + { + res = SzArEx_Extract(&db, &lookStream.vt, i, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + if (res != SZ_OK) + break; + } + { + CSzFile outFile; + size_t processedSize; + size_t j; + size_t nameStartPos = 0; + for (j = 0; temp[j] != 0; j++) + { + if (temp[j] == '/') + { + temp[j] = 0; + MyCreateDir(path); + temp[j] = CHAR_PATH_SEPARATOR; + nameStartPos = j + 1; + } + } + + if (SzArEx_IsDir(&db, i)) + { + MyCreateDir(path); + continue; + } + else + { + unsigned extLen; + const WCHAR *name = temp + nameStartPos; + unsigned len = (unsigned)wcslen(name); + unsigned nameLen = FindExt(temp + nameStartPos, &extLen); + unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen); + unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen); + + unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12)); + if (minPrice > price) + { + minPrice = price; + executeFileIndex = i; + useShellExecute = (extPrice != k_EXE_ExtIndex); + } + + if (DoesFileOrDirExist(path)) + { + errorMessage = "Duplicate file"; + res = SZ_ERROR_FAIL; + break; + } + if (OutFile_OpenW(&outFile, path)) + { + errorMessage = "Can't open output file"; + res = SZ_ERROR_FAIL; + break; + } + } + + processedSize = outSizeProcessed; + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) + { + errorMessage = "Can't write output file"; + res = SZ_ERROR_FAIL; + } + + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.MTime, i)) + { + const CNtfsFileTime *t = db.MTime.Vals + i; + FILETIME mTime; + mTime.dwLowDateTime = t->Low; + mTime.dwHighDateTime = t->High; + SetFileTime(outFile.handle, NULL, NULL, &mTime); + } + #endif + + { + SRes res2 = File_Close(&outFile); + if (res != SZ_OK) + break; + if (res2 != SZ_OK) + { + res = res2; + break; + } + } + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.Attribs, i)) + SetFileAttributesW(path, db.Attribs.Vals[i]); + #endif + } + } + + if (res == SZ_OK) + { + if (executeFileIndex == (UInt32)(Int32)-1) + { + errorMessage = "There is no file to execute"; + res = SZ_ERROR_FAIL; + } + else + { + WCHAR *temp = path + pathLen; + UInt32 j; + SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp); + for (j = 0; temp[j] != 0; j++) + if (temp[j] == '/') + temp[j] = CHAR_PATH_SEPARATOR; + } + } + ISzAlloc_Free(&allocImp, outBuffer); + } + + SzArEx_Free(&db, &allocImp); + + ISzAlloc_Free(&allocImp, lookStream.buf); + + File_Close(&archiveStream.file); + + if (res == SZ_OK) + { + HANDLE hProcess = 0; + + #ifndef UNDER_CE + WCHAR oldCurDir[MAX_PATH + 2]; + oldCurDir[0] = 0; + { + DWORD needLen = GetCurrentDirectory(MAX_PATH + 1, oldCurDir); + if (needLen == 0 || needLen > MAX_PATH) + oldCurDir[0] = 0; + SetCurrentDirectory(workCurDir); + } + #endif + + if (useShellExecute) + { + SHELLEXECUTEINFO ei; + UINT32 executeRes; + BOOL success; + + memset(&ei, 0, sizeof(ei)); + ei.cbSize = sizeof(ei); + ei.lpFile = path; + ei.fMask = SEE_MASK_NOCLOSEPROCESS + #ifndef UNDER_CE + | SEE_MASK_FLAG_DDEWAIT + #endif + /* | SEE_MASK_NO_CONSOLE */ + ; + if (wcslen(cmdLineParams) != 0) + ei.lpParameters = cmdLineParams; + ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */ + success = ShellExecuteEx(&ei); + executeRes = (UINT32)(UINT_PTR)ei.hInstApp; + if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */ + res = SZ_ERROR_FAIL; + else + hProcess = ei.hProcess; + } + else + { + STARTUPINFOW si; + PROCESS_INFORMATION pi; + WCHAR cmdLine[MAX_PATH * 3]; + + wcscpy(cmdLine, path); + wcscat(cmdLine, cmdLineParams); + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0) + res = SZ_ERROR_FAIL; + else + { + CloseHandle(pi.hThread); + hProcess = pi.hProcess; + } + } + + if (hProcess != 0) + { + WaitForSingleObject(hProcess, INFINITE); + if (!GetExitCodeProcess(hProcess, &exitCode)) + exitCode = 1; + CloseHandle(hProcess); + } + + #ifndef UNDER_CE + SetCurrentDirectory(oldCurDir); + #endif + } + + path[pathLen] = L'\0'; + RemoveDirWithSubItems(path); + + if (res == SZ_OK) + return (int)exitCode; + + { + if (res == SZ_ERROR_UNSUPPORTED) + errorMessage = "Decoder doesn't support this archive"; + else if (res == SZ_ERROR_MEM) + errorMessage = "Can't allocate required memory"; + else if (res == SZ_ERROR_CRC) + errorMessage = "CRC error"; + else + { + if (!errorMessage) + errorMessage = "ERROR"; + } + + if (errorMessage) + PrintErrorMessage(errorMessage); + } + return 1; +} diff --git a/other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.dsp b/other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.dsp new file mode 100644 index 0000000000..be9de6dec7 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.dsp @@ -0,0 +1,231 @@ +# 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 + +# 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 Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "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 /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "SfxSetup - Win32 Release" +# Name "SfxSetup - Win32 Debug" +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\7z.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zArcIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrcOpt.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra86.c +# End Source File +# Begin Source File + +SOURCE=..\..\BraIA64.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\Delta.c +# End Source File +# Begin Source File + +SOURCE=..\..\Delta.h +# End Source File +# Begin Source File + +SOURCE=..\..\DllSecur.c +# End Source File +# Begin Source File + +SOURCE=..\..\DllSecur.h +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.c +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Precomp.c +# ADD CPP /Yc"Precomp.h" +# End Source File +# Begin Source File + +SOURCE=.\Precomp.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\SfxSetup.c +# End Source File +# End Target +# End Project diff --git a/other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.dsw b/other-licenses/7zstub/src/C/Util/SfxSetup/SfxSetup.dsw new file mode 100644 index 0000000000..128fcdd3e0 --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/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/C/Util/SfxSetup/makefile b/other-licenses/7zstub/src/C/Util/SfxSetup/makefile new file mode 100644 index 0000000000..c9f59ccd3e --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/SfxSetup/makefile @@ -0,0 +1,37 @@ +PROG = 7zS2.sfx +MY_FIXED = 1 + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zArcIn.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\DllSecur.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + +7Z_OBJS = \ + $O\SfxSetup.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O1) diff --git a/other-licenses/7zstub/src/C/Util/SfxSetup/makefile_con b/other-licenses/7zstub/src/C/Util/SfxSetup/makefile_con new file mode 100644 index 0000000000..6f604ed81e --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/SfxSetup/makefile_con @@ -0,0 +1,38 @@ +PROG = 7zS2con.sfx +MY_FIXED = 1 +CFLAGS = $(CFLAGS) -D_CONSOLE + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zArcIn.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\DllSecur.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + +7Z_OBJS = \ + $O\SfxSetup.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O1) diff --git a/other-licenses/7zstub/src/C/Util/SfxSetup/resource.rc b/other-licenses/7zstub/src/C/Util/SfxSetup/resource.rc new file mode 100644 index 0000000000..64f4e2ce7a --- /dev/null +++ b/other-licenses/7zstub/src/C/Util/SfxSetup/resource.rc @@ -0,0 +1,5 @@ +#include "../../7zVersion.rc" + +MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx") + +1 ICON "setup.ico" diff --git a/other-licenses/7zstub/src/C/Util/SfxSetup/setup.ico b/other-licenses/7zstub/src/C/Util/SfxSetup/setup.ico new file mode 100644 index 0000000000..dbb6ca8b47 Binary files /dev/null and b/other-licenses/7zstub/src/C/Util/SfxSetup/setup.ico differ diff --git a/other-licenses/7zstub/src/C/Xz.c b/other-licenses/7zstub/src/C/Xz.c new file mode 100644 index 0000000000..7e061d6e7d --- /dev/null +++ b/other-licenses/7zstub/src/C/Xz.c @@ -0,0 +1,90 @@ +/* Xz.c - Xz +2017-05-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" +#include "XzCrc64.h" + +const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 }; +/* const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; */ + +unsigned Xz_WriteVarInt(Byte *buf, UInt64 v) +{ + unsigned i = 0; + do + { + buf[i++] = (Byte)((v & 0x7F) | 0x80); + v >>= 7; + } + while (v != 0); + buf[(size_t)i - 1] &= 0x7F; + return i; +} + +void Xz_Construct(CXzStream *p) +{ + p->numBlocks = 0; + p->blocks = NULL; + p->flags = 0; +} + +void Xz_Free(CXzStream *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->blocks); + p->numBlocks = 0; + p->blocks = NULL; +} + +unsigned XzFlags_GetCheckSize(CXzStreamFlags f) +{ + unsigned t = XzFlags_GetCheckType(f); + return (t == 0) ? 0 : (4 << ((t - 1) / 3)); +} + +void XzCheck_Init(CXzCheck *p, unsigned mode) +{ + p->mode = mode; + switch (mode) + { + case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break; + case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break; + case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break; + } +} + +void XzCheck_Update(CXzCheck *p, const void *data, size_t size) +{ + switch (p->mode) + { + case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break; + case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break; + case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break; + } +} + +int XzCheck_Final(CXzCheck *p, Byte *digest) +{ + switch (p->mode) + { + case XZ_CHECK_CRC32: + SetUi32(digest, CRC_GET_DIGEST(p->crc)); + break; + case XZ_CHECK_CRC64: + { + int i; + UInt64 v = CRC64_GET_DIGEST(p->crc64); + for (i = 0; i < 8; i++, v >>= 8) + digest[i] = (Byte)(v & 0xFF); + break; + } + case XZ_CHECK_SHA256: + Sha256_Final(&p->sha, digest); + break; + default: + return 0; + } + return 1; +} diff --git a/other-licenses/7zstub/src/C/Xz.h b/other-licenses/7zstub/src/C/Xz.h new file mode 100644 index 0000000000..7b88f516ac --- /dev/null +++ b/other-licenses/7zstub/src/C/Xz.h @@ -0,0 +1,460 @@ +/* Xz.h - Xz interface +2018-02-28 : Igor Pavlov : Public domain */ + +#ifndef __XZ_H +#define __XZ_H + +#include "Sha256.h" + +EXTERN_C_BEGIN + +#define XZ_ID_Subblock 1 +#define XZ_ID_Delta 3 +#define XZ_ID_X86 4 +#define XZ_ID_PPC 5 +#define XZ_ID_IA64 6 +#define XZ_ID_ARM 7 +#define XZ_ID_ARMT 8 +#define XZ_ID_SPARC 9 +#define XZ_ID_LZMA2 0x21 + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value); +unsigned Xz_WriteVarInt(Byte *buf, UInt64 v); + +/* ---------- xz block ---------- */ + +#define XZ_BLOCK_HEADER_SIZE_MAX 1024 + +#define XZ_NUM_FILTERS_MAX 4 +#define XZ_BF_NUM_FILTERS_MASK 3 +#define XZ_BF_PACK_SIZE (1 << 6) +#define XZ_BF_UNPACK_SIZE (1 << 7) + +#define XZ_FILTER_PROPS_SIZE_MAX 20 + +typedef struct +{ + UInt64 id; + UInt32 propsSize; + Byte props[XZ_FILTER_PROPS_SIZE_MAX]; +} CXzFilter; + +typedef struct +{ + UInt64 packSize; + UInt64 unpackSize; + Byte flags; + CXzFilter filters[XZ_NUM_FILTERS_MAX]; +} CXzBlock; + +#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1) +#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0) +#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0) +#define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0) + +SRes XzBlock_Parse(CXzBlock *p, const Byte *header); +SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes); + +/* ---------- xz stream ---------- */ + +#define XZ_SIG_SIZE 6 +#define XZ_FOOTER_SIG_SIZE 2 + +extern const Byte XZ_SIG[XZ_SIG_SIZE]; + +/* +extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE]; +*/ + +#define XZ_FOOTER_SIG_0 'Y' +#define XZ_FOOTER_SIG_1 'Z' + +#define XZ_STREAM_FLAGS_SIZE 2 +#define XZ_STREAM_CRC_SIZE 4 + +#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE) +#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4) + +#define XZ_CHECK_MASK 0xF +#define XZ_CHECK_NO 0 +#define XZ_CHECK_CRC32 1 +#define XZ_CHECK_CRC64 4 +#define XZ_CHECK_SHA256 10 + +typedef struct +{ + unsigned mode; + UInt32 crc; + UInt64 crc64; + CSha256 sha; +} CXzCheck; + +void XzCheck_Init(CXzCheck *p, unsigned mode); +void XzCheck_Update(CXzCheck *p, const void *data, size_t size); +int XzCheck_Final(CXzCheck *p, Byte *digest); + +typedef UInt16 CXzStreamFlags; + +#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK) +#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK) +#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32) +unsigned XzFlags_GetCheckSize(CXzStreamFlags f); + +SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf); +SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream); + +typedef struct +{ + UInt64 unpackSize; + UInt64 totalSize; +} CXzBlockSizes; + +typedef struct +{ + CXzStreamFlags flags; + size_t numBlocks; + CXzBlockSizes *blocks; + UInt64 startOffset; +} CXzStream; + +void Xz_Construct(CXzStream *p); +void Xz_Free(CXzStream *p, ISzAllocPtr alloc); + +#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1) + +UInt64 Xz_GetUnpackSize(const CXzStream *p); +UInt64 Xz_GetPackSize(const CXzStream *p); + +typedef struct +{ + size_t num; + size_t numAllocated; + CXzStream *streams; +} CXzs; + +void Xzs_Construct(CXzs *p); +void Xzs_Free(CXzs *p, ISzAllocPtr alloc); +SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAllocPtr alloc); + +UInt64 Xzs_GetNumBlocks(const CXzs *p); +UInt64 Xzs_GetUnpackSize(const CXzs *p); + + +// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder + +typedef enum +{ + CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */ + CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + CODER_STATUS_NOT_FINISHED, /* stream was not finished */ + CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */ +} ECoderStatus; + + +// ECoderFinishMode values are identical to ELzmaFinishMode + +typedef enum +{ + CODER_FINISH_ANY, /* finish at any point */ + CODER_FINISH_END /* block must be finished at the end */ +} ECoderFinishMode; + + +typedef struct _IStateCoder +{ + void *p; + void (*Free)(void *p, ISzAllocPtr alloc); + SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc); + void (*Init)(void *p); + SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished, + ECoderStatus *status); + SizeT (*Filter)(void *p, Byte *data, SizeT size); +} IStateCoder; + + + +#define MIXCODER_NUM_FILTERS_MAX 4 + +typedef struct +{ + ISzAllocPtr alloc; + Byte *buf; + unsigned numCoders; + + Byte *outBuf; + size_t outBufSize; + size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode) + Bool wasFinished; + SRes res; + ECoderStatus status; + // Bool SingleBufMode; + + int finished[MIXCODER_NUM_FILTERS_MAX - 1]; + size_t pos[MIXCODER_NUM_FILTERS_MAX - 1]; + size_t size[MIXCODER_NUM_FILTERS_MAX - 1]; + UInt64 ids[MIXCODER_NUM_FILTERS_MAX]; + SRes results[MIXCODER_NUM_FILTERS_MAX]; + IStateCoder coders[MIXCODER_NUM_FILTERS_MAX]; +} CMixCoder; + + +typedef enum +{ + XZ_STATE_STREAM_HEADER, + XZ_STATE_STREAM_INDEX, + XZ_STATE_STREAM_INDEX_CRC, + XZ_STATE_STREAM_FOOTER, + XZ_STATE_STREAM_PADDING, + XZ_STATE_BLOCK_HEADER, + XZ_STATE_BLOCK, + XZ_STATE_BLOCK_FOOTER +} EXzState; + + +typedef struct +{ + EXzState state; + UInt32 pos; + unsigned alignPos; + unsigned indexPreSize; + + CXzStreamFlags streamFlags; + + UInt32 blockHeaderSize; + UInt64 packSize; + UInt64 unpackSize; + + UInt64 numBlocks; // number of finished blocks in current stream + UInt64 indexSize; + UInt64 indexPos; + UInt64 padSize; + + UInt64 numStartedStreams; + UInt64 numFinishedStreams; + UInt64 numTotalBlocks; + + UInt32 crc; + CMixCoder decoder; + CXzBlock block; + CXzCheck check; + CSha256 sha; + + Bool parseMode; + Bool headerParsedOk; + Bool decodeToStreamSignature; + unsigned decodeOnlyOneBlock; + + Byte *outBuf; + size_t outBufSize; + size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked + + Byte shaDigest[SHA256_DIGEST_SIZE]; + Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; +} CXzUnpacker; + +/* alloc : aligned for cache line allocation is better */ +void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc); +void XzUnpacker_Init(CXzUnpacker *p); +void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize); +void XzUnpacker_Free(CXzUnpacker *p); + +/* + XzUnpacker + The sequence for decoding functions: + { + XzUnpacker_Construct() + [Decoding_Calls] + XzUnpacker_Free() + } + + [Decoding_Calls] + + There are 3 types of interfaces for [Decoding_Calls] calls: + + Interface-1 : Partial output buffers: + { + XzUnpacker_Init() + for() + XzUnpacker_Code(); + } + + Interface-2 : Direct output buffer: + Use it, if you know exact size of decoded data, and you need + whole xz unpacked data in one output buffer. + xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode. + { + XzUnpacker_Init() + XzUnpacker_SetOutBufMode(); // to set output buffer and size + for() + XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code() + } + + Interface-3 : Direct output buffer : One call full decoding + It unpacks whole input buffer to output buffer in one call. + It uses Interface-2 internally. + { + XzUnpacker_CodeFull() + } +*/ + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + CODER_FINISH_ANY - use smallest number of input bytes + CODER_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + CODER_STATUS_NOT_FINISHED, + CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams, + call XzUnpacker_IsStreamWasFinished to check that current stream was finished + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_DATA - Data error + SZ_ERROR_UNSUPPORTED - Unsupported method or method properties + SZ_ERROR_CRC - CRC error + // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons: + - xz Stream Signature failure + - CRC32 of xz Stream Header is failed + - The size of Stream padding is not multiple of four bytes. + It's possible to get that error, if xz stream was finished and the stream + contains some another data. In that case you can call XzUnpacker_GetExtraSize() + function to get real size of xz stream. +*/ + + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcFinished, + ECoderFinishMode finishMode, ECoderStatus *status); + +SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, + ECoderFinishMode finishMode, ECoderStatus *status); + +Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p); + +/* +XzUnpacker_GetExtraSize() returns then number of uncofirmed bytes, + if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state. +These bytes can be some bytes after xz archive, or +it can be start of new xz stream. + +Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of +xz stream in two cases, if XzUnpacker_Code() returns: + res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT + res == SZ_ERROR_NO_ARCHIVE +*/ + +UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p); + + +/* + for random block decoding: + XzUnpacker_Init(); + set CXzUnpacker::streamFlags + XzUnpacker_PrepareToRandomBlockDecoding() + loop + { + XzUnpacker_Code() + XzUnpacker_IsBlockFinished() + } +*/ + +void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p); +Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p); + +#define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags)) + + + +/* ---------- Multi Threading Decoding ---------- */ + + +typedef struct +{ + size_t inBufSize_ST; + size_t outStep_ST; + Bool ignoreErrors; + + #ifndef _7ZIP_ST + unsigned numThreads; + size_t inBufSize_MT; + size_t memUseMax; + #endif +} CXzDecMtProps; + +void XzDecMtProps_Init(CXzDecMtProps *p); + + +typedef void * CXzDecMtHandle; + +/* + alloc : XzDecMt uses CAlignOffsetAlloc for addresses allocated by (alloc). + allocMid : for big allocations, aligned allocation is better +*/ + +CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid); +void XzDecMt_Destroy(CXzDecMtHandle p); + + +typedef struct +{ + Byte UnpackSize_Defined; + Byte NumStreams_Defined; + Byte NumBlocks_Defined; + + Byte DataAfterEnd; + Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data + + UInt64 InSize; // pack size processed + UInt64 OutSize; + + UInt64 NumStreams; + UInt64 NumBlocks; + + SRes DecodeRes; + SRes ReadRes; + SRes ProgressRes; + SRes CombinedRes; + SRes CombinedRes_Type; + +} CXzStatInfo; + +void XzStatInfo_Clear(CXzStatInfo *p); + +/* +XzDecMt_Decode() +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_NO_ARCHIVE - is not xz archive + SZ_ERROR_ARCHIVE - Headers error + SZ_ERROR_DATA - Data Error + SZ_ERROR_CRC - CRC Error + SZ_ERROR_INPUT_EOF - it needs more input data + SZ_ERROR_WRITE - ISeqOutStream error + (SZ_ERROR_READ) - ISeqInStream errors + (SZ_ERROR_PROGRESS) - ICompressProgress errors + // SZ_ERROR_THREAD - error in multi-threading functions + MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function +*/ + +SRes XzDecMt_Decode(CXzDecMtHandle p, + const CXzDecMtProps *props, + const UInt64 *outDataSize, // NULL means undefined + int finishMode, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished + ISeqOutStream *outStream, + // Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + // const Byte *inData, size_t inDataSize, + CXzStatInfo *stat, + int *isMT, // 0 means that ST (Single-Thread) version was used + ICompressProgress *progress); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/XzCrc64.c b/other-licenses/7zstub/src/C/XzCrc64.c new file mode 100644 index 0000000000..e9ca9ec265 --- /dev/null +++ b/other-licenses/7zstub/src/C/XzCrc64.c @@ -0,0 +1,86 @@ +/* XzCrc64.c -- CRC64 calculation +2017-05-23 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "XzCrc64.h" +#include "CpuArch.h" + +#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) + +#ifdef MY_CPU_LE + #define CRC64_NUM_TABLES 4 +#else + #define CRC64_NUM_TABLES 5 + #define CRC_UINT64_SWAP(v) \ + ((v >> 56) \ + | ((v >> 40) & ((UInt64)0xFF << 8)) \ + | ((v >> 24) & ((UInt64)0xFF << 16)) \ + | ((v >> 8) & ((UInt64)0xFF << 24)) \ + | ((v << 8) & ((UInt64)0xFF << 32)) \ + | ((v << 24) & ((UInt64)0xFF << 40)) \ + | ((v << 40) & ((UInt64)0xFF << 48)) \ + | ((v << 56))) + + UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +#ifndef MY_CPU_BE + UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +typedef UInt64 (MY_FAST_CALL *CRC64_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); + +static CRC64_FUNC g_Crc64Update; +UInt64 g_Crc64Table[256 * CRC64_NUM_TABLES]; + +UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size) +{ + return g_Crc64Update(v, data, size, g_Crc64Table); +} + +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size) +{ + return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL; +} + +void MY_FAST_CALL Crc64GenerateTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt64 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1))); + g_Crc64Table[i] = r; + } + for (i = 256; i < 256 * CRC64_NUM_TABLES; i++) + { + UInt64 r = g_Crc64Table[(size_t)i - 256]; + g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); + } + + #ifdef MY_CPU_LE + + g_Crc64Update = XzCrc64UpdateT4; + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_Crc64Update = XzCrc64UpdateT4; + else + #endif + { + for (i = 256 * CRC64_NUM_TABLES - 1; i >= 256; i--) + { + UInt64 x = g_Crc64Table[(size_t)i - 256]; + g_Crc64Table[i] = CRC_UINT64_SWAP(x); + } + g_Crc64Update = XzCrc64UpdateT1_BeT4; + } + } + #endif +} diff --git a/other-licenses/7zstub/src/C/XzCrc64.h b/other-licenses/7zstub/src/C/XzCrc64.h new file mode 100644 index 0000000000..71b10d57e5 --- /dev/null +++ b/other-licenses/7zstub/src/C/XzCrc64.h @@ -0,0 +1,26 @@ +/* XzCrc64.h -- CRC64 calculation +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __XZ_CRC64_H +#define __XZ_CRC64_H + +#include + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +extern UInt64 g_Crc64Table[]; + +void MY_FAST_CALL Crc64GenerateTable(void); + +#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF) +#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL) +#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size); +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/XzCrc64Opt.c b/other-licenses/7zstub/src/C/XzCrc64Opt.c new file mode 100644 index 0000000000..9273465d47 --- /dev/null +++ b/other-licenses/7zstub/src/C/XzCrc64Opt.c @@ -0,0 +1,69 @@ +/* XzCrc64Opt.c -- CRC64 calculation +2017-06-30 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifndef MY_CPU_BE + +#define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC64_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)v ^ *(const UInt32 *)p; + v = (v >> 32) + ^ (table + 0x300)[((d ) & 0xFF)] + ^ (table + 0x200)[((d >> 8) & 0xFF)] + ^ (table + 0x100)[((d >> 16) & 0xFF)] + ^ (table + 0x000)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC64_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT64_SWAP(v) \ + ((v >> 56) \ + | ((v >> 40) & ((UInt64)0xFF << 8)) \ + | ((v >> 24) & ((UInt64)0xFF << 16)) \ + | ((v >> 8) & ((UInt64)0xFF << 24)) \ + | ((v << 8) & ((UInt64)0xFF << 32)) \ + | ((v << 24) & ((UInt64)0xFF << 40)) \ + | ((v << 40) & ((UInt64)0xFF << 48)) \ + | ((v << 56))) + +#define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8)) + +UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + table += 0x100; + v = CRC_UINT64_SWAP(v); + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC64_UPDATE_BYTE_2_BE(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p; + v = (v << 32) + ^ (table + 0x000)[((d ) & 0xFF)] + ^ (table + 0x100)[((d >> 8) & 0xFF)] + ^ (table + 0x200)[((d >> 16) & 0xFF)] + ^ (table + 0x300)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC64_UPDATE_BYTE_2_BE(v, *p); + return CRC_UINT64_SWAP(v); +} + +#endif diff --git a/other-licenses/7zstub/src/C/XzDec.c b/other-licenses/7zstub/src/C/XzDec.c new file mode 100644 index 0000000000..ebf198336c --- /dev/null +++ b/other-licenses/7zstub/src/C/XzDec.c @@ -0,0 +1,2773 @@ +/* XzDec.c -- Xz Decode +2018-04-24 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #include + +// #define XZ_DUMP + +/* #define XZ_DUMP */ + +#ifdef XZ_DUMP +#include +#endif + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#define PRF_STR(s) PRF(printf("\n" s "\n")) +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) + +#include +#include + +#include "7zCrc.h" +#include "Alloc.h" +#include "Bra.h" +#include "CpuArch.h" +#include "Delta.h" +#include "Lzma2Dec.h" + +// #define USE_SUBBLOCK + +#ifdef USE_SUBBLOCK +#include "Bcj3Dec.c" +#include "SbDec.h" +#endif + +#include "Xz.h" + +#define XZ_CHECK_SIZE_MAX 64 + +#define CODER_BUF_SIZE ((size_t)1 << 17) + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) +{ + unsigned i, limit; + *value = 0; + limit = (maxSize > 9) ? 9 : (unsigned)maxSize; + + for (i = 0; i < limit;) + { + Byte b = p[i]; + *value |= (UInt64)(b & 0x7F) << (7 * i++); + if ((b & 0x80) == 0) + return (b == 0 && i != 1) ? 0 : i; + } + return 0; +} + +/* ---------- BraState ---------- */ + +#define BRA_BUF_SIZE (1 << 14) + +typedef struct +{ + size_t bufPos; + size_t bufConv; + size_t bufTotal; + + int encodeMode; + + UInt32 methodId; + UInt32 delta; + UInt32 ip; + UInt32 x86State; + Byte deltaState[DELTA_STATE_SIZE]; + + Byte buf[BRA_BUF_SIZE]; +} CBraState; + +static void BraState_Free(void *pp, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, pp); +} + +static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + CBraState *p = ((CBraState *)pp); + UNUSED_VAR(alloc); + p->ip = 0; + if (p->methodId == XZ_ID_Delta) + { + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + p->delta = (unsigned)props[0] + 1; + } + else + { + if (propSize == 4) + { + UInt32 v = GetUi32(props); + switch (p->methodId) + { + case XZ_ID_PPC: + case XZ_ID_ARM: + case XZ_ID_SPARC: + if ((v & 3) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + case XZ_ID_ARMT: + if ((v & 1) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + case XZ_ID_IA64: + if ((v & 0xF) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + } + p->ip = v; + } + else if (propSize != 0) + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; +} + +static void BraState_Init(void *pp) +{ + CBraState *p = ((CBraState *)pp); + p->bufPos = p->bufConv = p->bufTotal = 0; + x86_Convert_Init(p->x86State); + if (p->methodId == XZ_ID_Delta) + Delta_Init(p->deltaState); +} + + +#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break; + +static SizeT BraState_Filter(void *pp, Byte *data, SizeT size) +{ + CBraState *p = ((CBraState *)pp); + switch (p->methodId) + { + case XZ_ID_Delta: + if (p->encodeMode) + Delta_Encode(p->deltaState, p->delta, data, size); + else + Delta_Decode(p->deltaState, p->delta, data, size); + break; + case XZ_ID_X86: + size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode); + break; + CASE_BRA_CONV(PPC) + CASE_BRA_CONV(IA64) + CASE_BRA_CONV(ARM) + CASE_BRA_CONV(ARMT) + CASE_BRA_CONV(SPARC) + } + p->ip += (UInt32)size; + return size; +} + + +static SRes BraState_Code2(void *pp, + Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode, + // int *wasFinished + ECoderStatus *status) +{ + CBraState *p = ((CBraState *)pp); + SizeT destRem = *destLen; + SizeT srcRem = *srcLen; + UNUSED_VAR(finishMode); + + *destLen = 0; + *srcLen = 0; + // *wasFinished = False; + *status = CODER_STATUS_NOT_FINISHED; + + while (destRem > 0) + { + if (p->bufPos != p->bufConv) + { + size_t size = p->bufConv - p->bufPos; + if (size > destRem) + size = destRem; + memcpy(dest, p->buf + p->bufPos, size); + p->bufPos += size; + *destLen += size; + dest += size; + destRem -= size; + continue; + } + + p->bufTotal -= p->bufPos; + memmove(p->buf, p->buf + p->bufPos, p->bufTotal); + p->bufPos = 0; + p->bufConv = 0; + { + size_t size = BRA_BUF_SIZE - p->bufTotal; + if (size > srcRem) + size = srcRem; + memcpy(p->buf + p->bufTotal, src, size); + *srcLen += size; + src += size; + srcRem -= size; + p->bufTotal += size; + } + if (p->bufTotal == 0) + break; + + p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal); + + if (p->bufConv == 0) + { + if (!srcWasFinished) + break; + p->bufConv = p->bufTotal; + } + } + + if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished) + { + *status = CODER_STATUS_FINISHED_WITH_MARK; + // *wasFinished = 1; + } + + return SZ_OK; +} + + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc) +{ + CBraState *decoder; + if (id < XZ_ID_Delta || id > XZ_ID_SPARC) + return SZ_ERROR_UNSUPPORTED; + decoder = p->p; + if (!decoder) + { + decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState)); + if (!decoder) + return SZ_ERROR_MEM; + p->p = decoder; + p->Free = BraState_Free; + p->SetProps = BraState_SetProps; + p->Init = BraState_Init; + p->Code2 = BraState_Code2; + p->Filter = BraState_Filter; + } + decoder->methodId = (UInt32)id; + decoder->encodeMode = encodeMode; + return SZ_OK; +} + + + +/* ---------- SbState ---------- */ + +#ifdef USE_SUBBLOCK + +static void SbState_Free(void *pp, ISzAllocPtr alloc) +{ + CSbDec *p = (CSbDec *)pp; + SbDec_Free(p); + ISzAlloc_Free(alloc, pp); +} + +static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + UNUSED_VAR(pp); + UNUSED_VAR(props); + UNUSED_VAR(alloc); + return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static void SbState_Init(void *pp) +{ + SbDec_Init((CSbDec *)pp); +} + +static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished + ECoderStatus *status) +{ + CSbDec *p = (CSbDec *)pp; + SRes res; + UNUSED_VAR(srcWasFinished); + p->dest = dest; + p->destLen = *destLen; + p->src = src; + p->srcLen = *srcLen; + p->finish = finishMode; /* change it */ + res = SbDec_Decode((CSbDec *)pp); + *destLen -= p->destLen; + *srcLen -= p->srcLen; + // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */ + *status = (*destLen == 0 && *srcLen == 0) ? + CODER_STATUS_FINISHED_WITH_MARK : + CODER_STATUS_NOT_FINISHED; + return res; +} + +static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc) +{ + CSbDec *decoder = (CSbDec *)p->p; + if (!decoder) + { + decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec)); + if (!decoder) + return SZ_ERROR_MEM; + p->p = decoder; + p->Free = SbState_Free; + p->SetProps = SbState_SetProps; + p->Init = SbState_Init; + p->Code2 = SbState_Code2; + p->Filter = NULL; + } + SbDec_Construct(decoder); + SbDec_SetAlloc(decoder, alloc); + return SZ_OK; +} + +#endif + + + +/* ---------- Lzma2 ---------- */ + +typedef struct +{ + CLzma2Dec decoder; + Bool outBufMode; +} CLzma2Dec_Spec; + + +static void Lzma2State_Free(void *pp, ISzAllocPtr alloc) +{ + CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; + if (p->outBufMode) + Lzma2Dec_FreeProbs(&p->decoder, alloc); + else + Lzma2Dec_Free(&p->decoder, alloc); + ISzAlloc_Free(alloc, pp); +} + +static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + { + CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; + if (p->outBufMode) + return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc); + else + return Lzma2Dec_Allocate(&p->decoder, props[0], alloc); + } +} + +static void Lzma2State_Init(void *pp) +{ + Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder); +} + + +/* + if (outBufMode), then (dest) is not used. Use NULL. + Data is unpacked to (spec->decoder.decoder.dic) output buffer. +*/ + +static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished, + ECoderStatus *status) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp; + ELzmaStatus status2; + /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ + SRes res; + UNUSED_VAR(srcWasFinished); + if (spec->outBufMode) + { + SizeT dicPos = spec->decoder.decoder.dicPos; + SizeT dicLimit = dicPos + *destLen; + res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2); + *destLen = spec->decoder.decoder.dicPos - dicPos; + } + else + res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2); + // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK); + // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder + *status = status2; + return res; +} + + +static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; + if (!spec) + { + spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec)); + if (!spec) + return SZ_ERROR_MEM; + p->p = spec; + p->Free = Lzma2State_Free; + p->SetProps = Lzma2State_SetProps; + p->Init = Lzma2State_Init; + p->Code2 = Lzma2State_Code2; + p->Filter = NULL; + Lzma2Dec_Construct(&spec->decoder); + } + spec->outBufMode = False; + if (outBuf) + { + spec->outBufMode = True; + spec->decoder.decoder.dic = outBuf; + spec->decoder.decoder.dicBufSize = outBufSize; + } + return SZ_OK; +} + + +static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; + if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf)) + return SZ_ERROR_FAIL; + if (outBuf) + { + spec->decoder.decoder.dic = outBuf; + spec->decoder.decoder.dicBufSize = outBufSize; + } + return SZ_OK; +} + + + +static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc) +{ + unsigned i; + p->alloc = alloc; + p->buf = NULL; + p->numCoders = 0; + + p->outBufSize = 0; + p->outBuf = NULL; + // p->SingleBufMode = False; + + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) + p->coders[i].p = NULL; +} + + +static void MixCoder_Free(CMixCoder *p) +{ + unsigned i; + p->numCoders = 0; + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) + { + IStateCoder *sc = &p->coders[i]; + if (sc->p) + { + sc->Free(sc->p, p->alloc); + sc->p = NULL; + } + } + if (p->buf) + { + ISzAlloc_Free(p->alloc, p->buf); + p->buf = NULL; /* 9.31: the BUG was fixed */ + } +} + +static void MixCoder_Init(CMixCoder *p) +{ + unsigned i; + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++) + { + p->size[i] = 0; + p->pos[i] = 0; + p->finished[i] = 0; + } + for (i = 0; i < p->numCoders; i++) + { + IStateCoder *coder = &p->coders[i]; + coder->Init(coder->p); + p->results[i] = SZ_OK; + } + p->outWritten = 0; + p->wasFinished = False; + p->res = SZ_OK; + p->status = CODER_STATUS_NOT_SPECIFIED; +} + + +static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) +{ + IStateCoder *sc = &p->coders[coderIndex]; + p->ids[coderIndex] = methodId; + switch (methodId) + { + case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc); + #ifdef USE_SUBBLOCK + case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc); + #endif + } + if (coderIndex == 0) + return SZ_ERROR_UNSUPPORTED; + return BraState_SetFromMethod(sc, methodId, 0, p->alloc); +} + + +static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) +{ + IStateCoder *sc = &p->coders[coderIndex]; + switch (methodId) + { + case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize); + } + return SZ_ERROR_UNSUPPORTED; +} + + + +/* + if (destFinish) - then unpack data block is finished at (*destLen) position, + and we can return data that were not processed by filter + +output (status) can be : + CODER_STATUS_NOT_FINISHED + CODER_STATUS_FINISHED_WITH_MARK + CODER_STATUS_NEEDS_MORE_INPUT - not implemented still +*/ + +static SRes MixCoder_Code(CMixCoder *p, + Byte *dest, SizeT *destLen, int destFinish, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + + *destLen = 0; + *srcLen = 0; + + if (p->wasFinished) + return p->res; + + p->status = CODER_STATUS_NOT_FINISHED; + + // if (p->SingleBufMode) + if (p->outBuf) + { + SRes res; + SizeT destLen2, srcLen2; + int wasFinished; + + PRF_STR("------- MixCoder Single ----------"); + + srcLen2 = srcLenOrig; + destLen2 = destLenOrig; + + { + IStateCoder *coder = &p->coders[0]; + res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode, + // &wasFinished, + &p->status); + wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK); + } + + p->res = res; + + /* + if (wasFinished) + p->status = CODER_STATUS_FINISHED_WITH_MARK; + else + { + if (res == SZ_OK) + if (destLen2 != destLenOrig) + p->status = CODER_STATUS_NEEDS_MORE_INPUT; + } + */ + + + *srcLen = srcLen2; + src += srcLen2; + p->outWritten += destLen2; + + if (res != SZ_OK || srcWasFinished || wasFinished) + p->wasFinished = True; + + if (p->numCoders == 1) + *destLen = destLen2; + else if (p->wasFinished) + { + unsigned i; + size_t processed = p->outWritten; + + for (i = 1; i < p->numCoders; i++) + { + IStateCoder *coder = &p->coders[i]; + processed = coder->Filter(coder->p, p->outBuf, processed); + if (wasFinished || (destFinish && p->outWritten == destLenOrig)) + processed = p->outWritten; + PRF_STR_INT("filter", i); + } + *destLen = processed; + } + return res; + } + + PRF_STR("standard mix"); + + if (p->numCoders != 1) + { + if (!p->buf) + { + p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); + if (!p->buf) + return SZ_ERROR_MEM; + } + + finishMode = CODER_FINISH_ANY; + } + + for (;;) + { + Bool processed = False; + Bool allFinished = True; + SRes resMain = SZ_OK; + unsigned i; + + p->status = CODER_STATUS_NOT_FINISHED; + /* + if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) + break; + */ + + for (i = 0; i < p->numCoders; i++) + { + SRes res; + IStateCoder *coder = &p->coders[i]; + Byte *dest2; + SizeT destLen2, srcLen2; // destLen2_Orig; + const Byte *src2; + int srcFinished2; + int encodingWasFinished; + ECoderStatus status2; + + if (i == 0) + { + src2 = src; + srcLen2 = srcLenOrig - *srcLen; + srcFinished2 = srcWasFinished; + } + else + { + size_t k = i - 1; + src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k]; + srcLen2 = p->size[k] - p->pos[k]; + srcFinished2 = p->finished[k]; + } + + if (i == p->numCoders - 1) + { + dest2 = dest; + destLen2 = destLenOrig - *destLen; + } + else + { + if (p->pos[i] != p->size[i]) + continue; + dest2 = p->buf + (CODER_BUF_SIZE * i); + destLen2 = CODER_BUF_SIZE; + } + + // destLen2_Orig = destLen2; + + if (p->results[i] != SZ_OK) + { + if (resMain == SZ_OK) + resMain = p->results[i]; + continue; + } + + res = coder->Code2(coder->p, + dest2, &destLen2, + src2, &srcLen2, srcFinished2, + finishMode, + // &encodingWasFinished, + &status2); + + if (res != SZ_OK) + { + p->results[i] = res; + if (resMain == SZ_OK) + resMain = res; + } + + encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK); + + if (!encodingWasFinished) + { + allFinished = False; + if (p->numCoders == 1 && res == SZ_OK) + p->status = status2; + } + + if (i == 0) + { + *srcLen += srcLen2; + src += srcLen2; + } + else + p->pos[(size_t)i - 1] += srcLen2; + + if (i == p->numCoders - 1) + { + *destLen += destLen2; + dest += destLen2; + } + else + { + p->size[i] = destLen2; + p->pos[i] = 0; + p->finished[i] = encodingWasFinished; + } + + if (destLen2 != 0 || srcLen2 != 0) + processed = True; + } + + if (!processed) + { + if (allFinished) + p->status = CODER_STATUS_FINISHED_WITH_MARK; + return resMain; + } + } +} + + +SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf) +{ + *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE); + if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) != + GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE)) + return SZ_ERROR_NO_ARCHIVE; + return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) +{ + return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) + && GetUi32(buf) == CrcCalc(buf + 4, 6) + && flags == GetBe16(buf + 8) + && buf[10] == XZ_FOOTER_SIG_0 + && buf[11] == XZ_FOOTER_SIG_1; +} + +#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ + { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ + if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } + + +static Bool XzBlock_AreSupportedFilters(const CXzBlock *p) +{ + unsigned numFilters = XzBlock_GetNumFilters(p) - 1; + unsigned i; + { + const CXzFilter *f = &p->filters[numFilters]; + if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40) + return False; + } + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &p->filters[i]; + if (f->id == XZ_ID_Delta) + { + if (f->propsSize != 1) + return False; + } + else if (f->id < XZ_ID_Delta + || f->id > XZ_ID_SPARC + || (f->propsSize != 0 && f->propsSize != 4)) + return False; + } + return True; +} + + +SRes XzBlock_Parse(CXzBlock *p, const Byte *header) +{ + unsigned pos; + unsigned numFilters, i; + unsigned headerSize = (unsigned)header[0] << 2; + + /* (headerSize != 0) : another code checks */ + + if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) + return SZ_ERROR_ARCHIVE; + + pos = 1; + p->flags = header[pos++]; + + p->packSize = (UInt64)(Int64)-1; + if (XzBlock_HasPackSize(p)) + { + READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize); + if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63) + return SZ_ERROR_ARCHIVE; + } + + p->unpackSize = (UInt64)(Int64)-1; + if (XzBlock_HasUnpackSize(p)) + READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize); + + numFilters = XzBlock_GetNumFilters(p); + for (i = 0; i < numFilters; i++) + { + CXzFilter *filter = p->filters + i; + UInt64 size; + READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id); + READ_VARINT_AND_CHECK(header, pos, headerSize, &size); + if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX) + return SZ_ERROR_ARCHIVE; + filter->propsSize = (UInt32)size; + memcpy(filter->props, header + pos, (size_t)size); + pos += (unsigned)size; + + #ifdef XZ_DUMP + printf("\nf[%u] = %2X: ", i, (unsigned)filter->id); + { + unsigned i; + for (i = 0; i < size; i++) + printf(" %2X", filter->props[i]); + } + #endif + } + + if (XzBlock_HasUnsupportedFlags(p)) + return SZ_ERROR_UNSUPPORTED; + + while (pos < headerSize) + if (header[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return SZ_OK; +} + + + + +static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize) +{ + unsigned i; + Bool needReInit = True; + unsigned numFilters = XzBlock_GetNumFilters(block); + + if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf))) + { + needReInit = False; + for (i = 0; i < numFilters; i++) + if (p->ids[i] != block->filters[numFilters - 1 - i].id) + { + needReInit = True; + break; + } + } + + // p->SingleBufMode = (outBuf != NULL); + p->outBuf = outBuf; + p->outBufSize = outBufSize; + + // p->SingleBufMode = False; + // outBuf = NULL; + + if (needReInit) + { + MixCoder_Free(p); + for (i = 0; i < numFilters; i++) + { + RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize)); + } + p->numCoders = numFilters; + } + else + { + RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize)); + } + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &block->filters[numFilters - 1 - i]; + IStateCoder *sc = &p->coders[i]; + RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)); + } + + MixCoder_Init(p); + return SZ_OK; +} + + + +void XzUnpacker_Init(CXzUnpacker *p) +{ + p->state = XZ_STATE_STREAM_HEADER; + p->pos = 0; + p->numStartedStreams = 0; + p->numFinishedStreams = 0; + p->numTotalBlocks = 0; + p->padSize = 0; + p->decodeOnlyOneBlock = 0; + + p->parseMode = False; + p->decodeToStreamSignature = False; + + // p->outBuf = NULL; + // p->outBufSize = 0; + p->outDataWritten = 0; +} + + +void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize) +{ + p->outBuf = outBuf; + p->outBufSize = outBufSize; +} + + +void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc) +{ + MixCoder_Construct(&p->decoder, alloc); + p->outBuf = NULL; + p->outBufSize = 0; + XzUnpacker_Init(p); +} + + +void XzUnpacker_Free(CXzUnpacker *p) +{ + MixCoder_Free(&p->decoder); +} + + +void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p) +{ + p->indexSize = 0; + p->numBlocks = 0; + Sha256_Init(&p->sha); + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + p->decodeOnlyOneBlock = 1; +} + + +static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize) +{ + Byte temp[32]; + unsigned num = Xz_WriteVarInt(temp, packSize); + num += Xz_WriteVarInt(temp + num, unpackSize); + Sha256_Update(&p->sha, temp, num); + p->indexSize += num; + p->numBlocks++; +} + + + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcFinished, + ECoderFinishMode finishMode, ECoderStatus *status) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + *destLen = 0; + *srcLen = 0; + *status = CODER_STATUS_NOT_SPECIFIED; + + for (;;) + { + SizeT srcRem; + + if (p->state == XZ_STATE_BLOCK) + { + SizeT destLen2 = destLenOrig - *destLen; + SizeT srcLen2 = srcLenOrig - *srcLen; + SRes res; + + ECoderFinishMode finishMode2 = finishMode; + Bool srcFinished2 = srcFinished; + Bool destFinish = False; + + if (p->block.packSize != (UInt64)(Int64)-1) + { + UInt64 rem = p->block.packSize - p->packSize; + if (srcLen2 >= rem) + { + srcFinished2 = True; + srcLen2 = (SizeT)rem; + } + if (rem == 0 && p->block.unpackSize == p->unpackSize) + return SZ_ERROR_DATA; + } + + if (p->block.unpackSize != (UInt64)(Int64)-1) + { + UInt64 rem = p->block.unpackSize - p->unpackSize; + if (destLen2 >= rem) + { + destFinish = True; + finishMode2 = CODER_FINISH_END; + destLen2 = (SizeT)rem; + } + } + + /* + if (srcLen2 == 0 && destLen2 == 0) + { + *status = CODER_STATUS_NOT_FINISHED; + return SZ_OK; + } + */ + + { + res = MixCoder_Code(&p->decoder, + (p->outBuf ? NULL : dest), &destLen2, destFinish, + src, &srcLen2, srcFinished2, + finishMode2); + + *status = p->decoder.status; + XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2); + if (!p->outBuf) + dest += destLen2; + p->outDataWritten += destLen2; + } + + (*srcLen) += srcLen2; + src += srcLen2; + p->packSize += srcLen2; + (*destLen) += destLen2; + p->unpackSize += destLen2; + + RINOK(res); + + if (*status != CODER_STATUS_FINISHED_WITH_MARK) + { + if (p->block.packSize == p->packSize + && *status == CODER_STATUS_NEEDS_MORE_INPUT) + { + PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT"); + *status = CODER_STATUS_NOT_SPECIFIED; + return SZ_ERROR_DATA; + } + + return SZ_OK; + } + { + XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize); + p->state = XZ_STATE_BLOCK_FOOTER; + p->pos = 0; + p->alignPos = 0; + *status = CODER_STATUS_NOT_SPECIFIED; + + if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize) + || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize)) + { + PRF_STR("ERROR: block.size mismatch"); + return SZ_ERROR_DATA; + } + } + // continue; + } + + srcRem = srcLenOrig - *srcLen; + + // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes + if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + switch (p->state) + { + case XZ_STATE_STREAM_HEADER: + { + if (p->pos < XZ_STREAM_HEADER_SIZE) + { + if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos]) + return SZ_ERROR_NO_ARCHIVE; + if (p->decodeToStreamSignature) + return SZ_OK; + p->buf[p->pos++] = *src++; + (*srcLen)++; + } + else + { + RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); + p->numStartedStreams++; + p->indexSize = 0; + p->numBlocks = 0; + Sha256_Init(&p->sha); + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + } + break; + } + + case XZ_STATE_BLOCK_HEADER: + { + if (p->pos == 0) + { + p->buf[p->pos++] = *src++; + (*srcLen)++; + if (p->buf[0] == 0) + { + if (p->decodeOnlyOneBlock) + return SZ_ERROR_DATA; + p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); + p->indexPos = p->indexPreSize; + p->indexSize += p->indexPreSize; + Sha256_Final(&p->sha, p->shaDigest); + Sha256_Init(&p->sha); + p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); + p->state = XZ_STATE_STREAM_INDEX; + break; + } + p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; + break; + } + + if (p->pos != p->blockHeaderSize) + { + UInt32 cur = p->blockHeaderSize - p->pos; + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + } + else + { + RINOK(XzBlock_Parse(&p->block, p->buf)); + if (!XzBlock_AreSupportedFilters(&p->block)) + return SZ_ERROR_UNSUPPORTED; + p->numTotalBlocks++; + p->state = XZ_STATE_BLOCK; + p->packSize = 0; + p->unpackSize = 0; + XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); + if (p->parseMode) + { + p->headerParsedOk = True; + return SZ_OK; + } + RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize)); + } + break; + } + + case XZ_STATE_BLOCK_FOOTER: + { + if ((((unsigned)p->packSize + p->alignPos) & 3) != 0) + { + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->alignPos++; + if (*src++ != 0) + return SZ_ERROR_CRC; + } + else + { + UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); + UInt32 cur = checkSize - p->pos; + if (cur != 0) + { + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + if (checkSize != p->pos) + break; + } + { + Byte digest[XZ_CHECK_SIZE_MAX]; + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) + return SZ_ERROR_CRC; + if (p->decodeOnlyOneBlock) + { + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + } + } + } + break; + } + + case XZ_STATE_STREAM_INDEX: + { + if (p->pos < p->indexPreSize) + { + (*srcLen)++; + if (*src++ != p->buf[p->pos++]) + return SZ_ERROR_CRC; + } + else + { + if (p->indexPos < p->indexSize) + { + UInt64 cur = p->indexSize - p->indexPos; + if (srcRem > cur) + srcRem = (SizeT)cur; + p->crc = CrcUpdate(p->crc, src, srcRem); + Sha256_Update(&p->sha, src, srcRem); + (*srcLen) += srcRem; + src += srcRem; + p->indexPos += srcRem; + } + else if ((p->indexPos & 3) != 0) + { + Byte b = *src++; + p->crc = CRC_UPDATE_BYTE(p->crc, b); + (*srcLen)++; + p->indexPos++; + p->indexSize++; + if (b != 0) + return SZ_ERROR_CRC; + } + else + { + Byte digest[SHA256_DIGEST_SIZE]; + p->state = XZ_STATE_STREAM_INDEX_CRC; + p->indexSize += 4; + p->pos = 0; + Sha256_Final(&p->sha, digest); + if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) + return SZ_ERROR_CRC; + } + } + break; + } + + case XZ_STATE_STREAM_INDEX_CRC: + { + if (p->pos < 4) + { + (*srcLen)++; + p->buf[p->pos++] = *src++; + } + else + { + p->state = XZ_STATE_STREAM_FOOTER; + p->pos = 0; + if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf)) + return SZ_ERROR_CRC; + } + break; + } + + case XZ_STATE_STREAM_FOOTER: + { + UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + if (p->pos == XZ_STREAM_FOOTER_SIZE) + { + p->state = XZ_STATE_STREAM_PADDING; + p->numFinishedStreams++; + p->padSize = 0; + if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) + return SZ_ERROR_CRC; + } + break; + } + + case XZ_STATE_STREAM_PADDING: + { + if (*src != 0) + { + if (((UInt32)p->padSize & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + p->pos = 0; + p->state = XZ_STATE_STREAM_HEADER; + } + else + { + (*srcLen)++; + src++; + p->padSize++; + } + break; + } + + case XZ_STATE_BLOCK: break; /* to disable GCC warning */ + } + } + /* + if (p->state == XZ_STATE_FINISHED) + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + */ +} + + +SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, + ECoderFinishMode finishMode, ECoderStatus *status) +{ + XzUnpacker_Init(p); + XzUnpacker_SetOutBuf(p, dest, *destLen); + + return XzUnpacker_Code(p, + NULL, destLen, + src, srcLen, True, + finishMode, status); +} + + +Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p) +{ + return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0); +} + +Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p) +{ + return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); +} + +UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p) +{ + UInt64 num = 0; + if (p->state == XZ_STATE_STREAM_PADDING) + num = p->padSize; + else if (p->state == XZ_STATE_STREAM_HEADER) + num = p->padSize + p->pos; + return num; +} + + + + + + + + + + + + + + + + + + + + + +#ifndef _7ZIP_ST +#include "MtDec.h" +#endif + + +void XzDecMtProps_Init(CXzDecMtProps *p) +{ + p->inBufSize_ST = 1 << 18; + p->outStep_ST = 1 << 20; + p->ignoreErrors = False; + + #ifndef _7ZIP_ST + p->numThreads = 1; + p->inBufSize_MT = 1 << 18; + p->memUseMax = sizeof(size_t) << 28; + #endif +} + + + +#ifndef _7ZIP_ST + +/* ---------- CXzDecMtThread ---------- */ + +typedef struct +{ + Byte *outBuf; + size_t outBufSize; + size_t outPreSize; + size_t inPreSize; + size_t inPreHeaderSize; + size_t blockPackSize_for_Index; // including block header and checksum. + size_t blockPackTotal; // including stream header, block header and checksum. + size_t inCodeSize; + size_t outCodeSize; + ECoderStatus status; + SRes codeRes; + Bool skipMode; + // Bool finishedWithMark; + EMtDecParseState parseState; + Bool parsing_Truncated; + Bool atBlockHeader; + CXzStreamFlags streamFlags; + // UInt64 numFinishedStreams + UInt64 numStreams; + UInt64 numTotalBlocks; + UInt64 numBlocks; + + Bool dec_created; + CXzUnpacker dec; + + Byte mtPad[1 << 7]; +} CXzDecMtThread; + +#endif + + +/* ---------- CXzDecMt ---------- */ + +typedef struct +{ + CAlignOffsetAlloc alignOffsetAlloc; + ISzAllocPtr allocMid; + + CXzDecMtProps props; + size_t unpackBlockMaxSize; + + ISeqInStream *inStream; + ISeqOutStream *outStream; + ICompressProgress *progress; + // CXzStatInfo *stat; + + Bool finishMode; + Bool outSize_Defined; + UInt64 outSize; + + UInt64 outProcessed; + UInt64 inProcessed; + UInt64 readProcessed; + Bool readWasFinished; + SRes readRes; + SRes writeRes; + + Byte *outBuf; + size_t outBufSize; + Byte *inBuf; + size_t inBufSize; + Bool dec_created; + CXzUnpacker dec; + + ECoderStatus status; + SRes codeRes; + + #ifndef _7ZIP_ST + Bool mainDecoderWasCalled; + // int statErrorDefined; + int finishedDecoderIndex; + + // global values that are used in Parse stage + CXzStreamFlags streamFlags; + // UInt64 numFinishedStreams + UInt64 numStreams; + UInt64 numTotalBlocks; + UInt64 numBlocks; + + // UInt64 numBadBlocks; + SRes mainErrorCode; + + Bool isBlockHeaderState_Parse; + Bool isBlockHeaderState_Write; + UInt64 outProcessed_Parse; + Bool parsing_Truncated; + + Bool mtc_WasConstructed; + CMtDec mtc; + CXzDecMtThread coders[MTDEC__THREADS_MAX]; + #endif + +} CXzDecMt; + + + +CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) +{ + CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt)); + if (!p) + return NULL; + + AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); + p->alignOffsetAlloc.baseAlloc = alloc; + p->alignOffsetAlloc.numAlignBits = 7; + p->alignOffsetAlloc.offset = 0; + + p->allocMid = allocMid; + + p->outBuf = NULL; + p->outBufSize = 0; + p->inBuf = NULL; + p->inBufSize = 0; + p->dec_created = False; + + p->unpackBlockMaxSize = 0; + + XzDecMtProps_Init(&p->props); + + #ifndef _7ZIP_ST + p->mtc_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CXzDecMtThread *coder = &p->coders[i]; + coder->dec_created = False; + coder->outBuf = NULL; + coder->outBufSize = 0; + } + } + #endif + + return p; +} + + +#ifndef _7ZIP_ST + +static void XzDecMt_FreeOutBufs(CXzDecMt *p) +{ + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CXzDecMtThread *coder = &p->coders[i]; + if (coder->outBuf) + { + ISzAlloc_Free(p->allocMid, coder->outBuf); + coder->outBuf = NULL; + coder->outBufSize = 0; + } + } + p->unpackBlockMaxSize = 0; +} + +#endif + + + +static void XzDecMt_FreeSt(CXzDecMt *p) +{ + if (p->dec_created) + { + XzUnpacker_Free(&p->dec); + p->dec_created = False; + } + + if (p->outBuf) + { + ISzAlloc_Free(p->allocMid, p->outBuf); + p->outBuf = NULL; + } + p->outBufSize = 0; + + if (p->inBuf) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBuf = NULL; + } + p->inBufSize = 0; +} + + +void XzDecMt_Destroy(CXzDecMtHandle pp) +{ + CXzDecMt *p = (CXzDecMt *)pp; + + XzDecMt_FreeSt(p); + + #ifndef _7ZIP_ST + + if (p->mtc_WasConstructed) + { + MtDec_Destruct(&p->mtc); + p->mtc_WasConstructed = False; + } + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CXzDecMtThread *t = &p->coders[i]; + if (t->dec_created) + { + // we don't need to free dict here + XzUnpacker_Free(&t->dec); + t->dec_created = False; + } + } + } + XzDecMt_FreeOutBufs(p); + + #endif + + ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp); +} + + + +#ifndef _7ZIP_ST + +static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) +{ + CXzDecMt *me = (CXzDecMt *)obj; + CXzDecMtThread *coder = &me->coders[coderIndex]; + size_t srcSize = cc->srcSize; + + cc->srcSize = 0; + cc->outPos = 0; + cc->state = MTDEC_PARSE_CONTINUE; + + cc->canCreateNewThread = True; + + if (cc->startCall) + { + coder->outPreSize = 0; + coder->inPreSize = 0; + coder->inPreHeaderSize = 0; + coder->parseState = MTDEC_PARSE_CONTINUE; + coder->parsing_Truncated = False; + coder->skipMode = False; + coder->codeRes = SZ_OK; + coder->status = CODER_STATUS_NOT_SPECIFIED; + coder->inCodeSize = 0; + coder->outCodeSize = 0; + + coder->numStreams = me->numStreams; + coder->numTotalBlocks = me->numTotalBlocks; + coder->numBlocks = me->numBlocks; + + if (!coder->dec_created) + { + XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt); + coder->dec_created = True; + } + + XzUnpacker_Init(&coder->dec); + + if (me->isBlockHeaderState_Parse) + { + coder->dec.streamFlags = me->streamFlags; + coder->atBlockHeader = True; + XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec); + } + else + { + coder->atBlockHeader = False; + me->isBlockHeaderState_Parse = True; + } + + coder->dec.numStartedStreams = me->numStreams; + coder->dec.numTotalBlocks = me->numTotalBlocks; + coder->dec.numBlocks = me->numBlocks; + } + + while (!coder->skipMode) + { + ECoderStatus status; + SRes res; + size_t srcSize2 = srcSize; + size_t destSize = (size_t)0 - 1; + + coder->dec.parseMode = True; + coder->dec.headerParsedOk = False; + + PRF_STR_INT("Parse", srcSize2); + + res = XzUnpacker_Code(&coder->dec, + NULL, &destSize, + cc->src, &srcSize2, cc->srcFinished, + CODER_FINISH_END, &status); + + // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2)); + + coder->codeRes = res; + coder->status = status; + cc->srcSize += srcSize2; + srcSize -= srcSize2; + coder->inPreHeaderSize += srcSize2; + coder->inPreSize = coder->inPreHeaderSize; + + if (res != SZ_OK) + { + cc->state = + coder->parseState = MTDEC_PARSE_END; + /* + if (res == SZ_ERROR_MEM) + return res; + return SZ_OK; + */ + return; // res; + } + + if (coder->dec.headerParsedOk) + { + const CXzBlock *block = &coder->dec.block; + if (XzBlock_HasUnpackSize(block) + // && block->unpackSize <= me->props.outBlockMax + && XzBlock_HasPackSize(block)) + { + { + if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax) + { + cc->state = MTDEC_PARSE_OVERFLOW; + return; // SZ_OK; + } + } + { + UInt64 packSize = block->packSize; + UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); + UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags); + UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize; + // if (blockPackSum <= me->props.inBlockMax) + // unpackBlockMaxSize + { + coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize); + coder->blockPackTotal = (size_t)blockPackSum; + coder->outPreSize = (size_t)block->unpackSize; + coder->streamFlags = coder->dec.streamFlags; + me->streamFlags = coder->dec.streamFlags; + coder->skipMode = True; + break; + } + } + } + } + else + // if (coder->inPreSize <= me->props.inBlockMax) + { + if (!cc->srcFinished) + return; // SZ_OK; + cc->state = + coder->parseState = MTDEC_PARSE_END; + return; // SZ_OK; + } + cc->state = MTDEC_PARSE_OVERFLOW; + return; // SZ_OK; + } + + // ---------- skipMode ---------- + { + UInt64 rem = coder->blockPackTotal - coder->inPreSize; + size_t cur = srcSize; + if (cur > rem) + cur = (size_t)rem; + cc->srcSize += cur; + coder->inPreSize += cur; + srcSize -= cur; + + if (coder->inPreSize == coder->blockPackTotal) + { + if (srcSize == 0) + { + if (!cc->srcFinished) + return; // SZ_OK; + cc->state = MTDEC_PARSE_END; + } + else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block + cc->state = MTDEC_PARSE_END; + else + { + cc->state = MTDEC_PARSE_NEW; + + { + size_t blockMax = me->unpackBlockMaxSize; + if (blockMax < coder->outPreSize) + blockMax = coder->outPreSize; + { + UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2; + if (me->props.memUseMax < required) + cc->canCreateNewThread = False; + } + } + + if (me->outSize_Defined) + { + // next block can be zero size + const UInt64 rem2 = me->outSize - me->outProcessed_Parse; + if (rem2 < coder->outPreSize) + { + coder->parsing_Truncated = True; + cc->state = MTDEC_PARSE_END; + } + me->outProcessed_Parse += coder->outPreSize; + } + } + } + else if (cc->srcFinished) + cc->state = MTDEC_PARSE_END; + else + return; // SZ_OK; + + coder->parseState = cc->state; + cc->outPos = coder->outPreSize; + + me->numStreams = coder->dec.numStartedStreams; + me->numTotalBlocks = coder->dec.numTotalBlocks; + me->numBlocks = coder->dec.numBlocks + 1; + return; // SZ_OK; + } +} + + +static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex) +{ + CXzDecMt *me = (CXzDecMt *)pp; + CXzDecMtThread *coder = &me->coders[coderIndex]; + Byte *dest; + + if (!coder->dec.headerParsedOk) + return SZ_OK; + + dest = coder->outBuf; + + if (!dest || coder->outBufSize < coder->outPreSize) + { + if (dest) + { + ISzAlloc_Free(me->allocMid, dest); + coder->outBuf = NULL; + coder->outBufSize = 0; + } + { + size_t outPreSize = coder->outPreSize; + if (outPreSize == 0) + outPreSize = 1; + dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize); + } + if (!dest) + return SZ_ERROR_MEM; + coder->outBuf = dest; + coder->outBufSize = coder->outPreSize; + + if (coder->outBufSize > me->unpackBlockMaxSize) + me->unpackBlockMaxSize = coder->outBufSize; + } + + // return SZ_ERROR_MEM; + + XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize); + + { + SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize); + // res = SZ_ERROR_UNSUPPORTED; // to test + coder->codeRes = res; + if (res != SZ_OK) + { + // if (res == SZ_ERROR_MEM) return res; + if (me->props.ignoreErrors && res != SZ_ERROR_MEM) + return S_OK; + return res; + } + } + + return SZ_OK; +} + + +static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + // int finished, int blockFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop) +{ + CXzDecMt *me = (CXzDecMt *)pp; + CXzDecMtThread *coder = &me->coders[coderIndex]; + + *inCodePos = coder->inCodeSize; + *outCodePos = coder->outCodeSize; + *stop = True; + + if (coder->inCodeSize < coder->inPreHeaderSize) + { + UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize; + size_t step = srcSize; + if (step > rem) + step = (size_t)rem; + src += step; + srcSize -= step; + coder->inCodeSize += step; + if (coder->inCodeSize < coder->inPreHeaderSize) + { + *stop = False; + return SZ_OK; + } + } + + if (!coder->dec.headerParsedOk) + return SZ_OK; + if (!coder->outBuf) + return SZ_OK; + + if (coder->codeRes == SZ_OK) + { + ECoderStatus status; + SRes res; + size_t srcProcessed = srcSize; + size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten; + + // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur)); + + res = XzUnpacker_Code(&coder->dec, + NULL, &outSizeCur, + src, &srcProcessed, srcFinished, + // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY, + CODER_FINISH_END, + &status); + + // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur)); + + coder->codeRes = res; + coder->status = status; + coder->inCodeSize += srcProcessed; + coder->outCodeSize = coder->dec.outDataWritten; + *inCodePos = coder->inCodeSize; + *outCodePos = coder->outCodeSize; + + if (res == SZ_OK) + { + if (srcProcessed == srcSize) + *stop = False; + return SZ_OK; + } + } + + if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM) + { + *inCodePos = coder->inPreSize; + *outCodePos = coder->outPreSize; + return S_OK; + } + return coder->codeRes; +} + + +#define XZDECMT_STREAM_WRITE_STEP (1 << 24) + +static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex, + Bool needWriteToStream, + const Byte *src, size_t srcSize, + // int srcFinished, + Bool *needContinue, + Bool *canRecode) +{ + CXzDecMt *me = (CXzDecMt *)pp; + const CXzDecMtThread *coder = &me->coders[coderIndex]; + + // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize)); + + *needContinue = False; + *canRecode = True; + + if (!needWriteToStream) + return SZ_OK; + + if (!coder->dec.headerParsedOk || !coder->outBuf) + { + if (me->finishedDecoderIndex < 0) + me->finishedDecoderIndex = coderIndex; + return SZ_OK; + } + + if (me->finishedDecoderIndex >= 0) + return SZ_OK; + + me->mtc.inProcessed += coder->inCodeSize; + + *canRecode = False; + + { + SRes res; + size_t size = coder->outCodeSize; + Byte *data = coder->outBuf; + + // we use in me->dec: sha, numBlocks, indexSize + + if (!me->isBlockHeaderState_Write) + { + XzUnpacker_PrepareToRandomBlockDecoding(&me->dec); + me->dec.decodeOnlyOneBlock = False; + me->dec.numStartedStreams = coder->dec.numStartedStreams; + me->dec.streamFlags = coder->streamFlags; + + me->isBlockHeaderState_Write = True; + } + + me->dec.numTotalBlocks = coder->dec.numTotalBlocks; + XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize); + + if (coder->outPreSize != size) + { + if (me->props.ignoreErrors) + { + memset(data + size, 0, coder->outPreSize - size); + size = coder->outPreSize; + } + // me->numBadBlocks++; + if (me->mainErrorCode == SZ_OK) + { + if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT) + me->mainErrorCode = SZ_ERROR_INPUT_EOF; + else + me->mainErrorCode = SZ_ERROR_DATA; + } + } + + if (me->writeRes != SZ_OK) + return me->writeRes; + + res = SZ_OK; + { + if (me->outSize_Defined) + { + const UInt64 rem = me->outSize - me->outProcessed; + if (size > rem) + size = (SizeT)rem; + } + + for (;;) + { + size_t cur = size; + size_t written; + if (cur > XZDECMT_STREAM_WRITE_STEP) + cur = XZDECMT_STREAM_WRITE_STEP; + + written = ISeqOutStream_Write(me->outStream, data, cur); + + // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written)); + + me->outProcessed += written; + if (written != cur) + { + me->writeRes = SZ_ERROR_WRITE; + res = me->writeRes; + break; + } + data += cur; + size -= cur; + // PRF_STR_INT("Written size =", size); + if (size == 0) + break; + res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0); + if (res != SZ_OK) + break; + } + } + + if (coder->codeRes != SZ_OK) + if (!me->props.ignoreErrors) + { + me->finishedDecoderIndex = coderIndex; + return res; + } + + RINOK(res); + + if (coder->inPreSize != coder->inCodeSize + || coder->blockPackTotal != coder->inCodeSize) + { + me->finishedDecoderIndex = coderIndex; + return SZ_OK; + } + + if (coder->parseState != MTDEC_PARSE_END) + { + *needContinue = True; + return SZ_OK; + } + } + + // (coder->state == MTDEC_PARSE_END) means that there are no other working threads + // so we can use mtc variables without lock + + PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed); + + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + { + CXzUnpacker *dec = &me->dec; + + PRF_STR_INT("PostSingle", srcSize); + + { + size_t srcProcessed = srcSize; + ECoderStatus status; + size_t outSizeCur = 0; + SRes res; + + // dec->decodeOnlyOneBlock = False; + dec->decodeToStreamSignature = True; + + me->mainDecoderWasCalled = True; + + if (coder->parsing_Truncated) + { + me->parsing_Truncated = True; + return SZ_OK; + } + + res = XzUnpacker_Code(dec, + NULL, &outSizeCur, + src, &srcProcessed, + me->mtc.readWasFinished, // srcFinished + CODER_FINISH_END, // CODER_FINISH_ANY, + &status); + + me->status = status; + me->codeRes = res; + + me->mtc.inProcessed += srcProcessed; + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + + if (res != SZ_OK) + { + return S_OK; + // return res; + } + + if (dec->state == XZ_STATE_STREAM_HEADER) + { + *needContinue = True; + me->isBlockHeaderState_Parse = False; + me->isBlockHeaderState_Write = False; + { + Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); + if (!crossBuf) + return SZ_ERROR_MEM; + memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed); + } + me->mtc.crossStart = 0; + me->mtc.crossEnd = srcSize - srcProcessed; + return SZ_OK; + } + + if (status != CODER_STATUS_NEEDS_MORE_INPUT) + { + return E_FAIL; + } + + if (me->mtc.readWasFinished) + { + return SZ_OK; + } + } + + { + size_t inPos; + size_t inLim; + const Byte *inData; + UInt64 inProgressPrev = me->mtc.inProcessed; + + // XzDecMt_Prepare_InBuf_ST(p); + Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); + if (!crossBuf) + return SZ_ERROR_MEM; + + inPos = 0; + inLim = 0; + // outProcessed = 0; + + inData = crossBuf; + + for (;;) + { + SizeT inProcessed; + SizeT outProcessed; + ECoderStatus status; + SRes res; + + if (inPos == inLim) + { + if (!me->mtc.readWasFinished) + { + inPos = 0; + inLim = me->mtc.inBufSize; + me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim); + me->mtc.readProcessed += inLim; + if (inLim == 0 || me->mtc.readRes != SZ_OK) + me->mtc.readWasFinished = True; + } + } + + inProcessed = inLim - inPos; + outProcessed = 0; + + res = XzUnpacker_Code(dec, + NULL, &outProcessed, + inData + inPos, &inProcessed, + (inProcessed == 0), // srcFinished + CODER_FINISH_END, &status); + + me->codeRes = res; + me->status = status; + inPos += inProcessed; + me->mtc.inProcessed += inProcessed; + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + + if (res != SZ_OK) + { + return S_OK; + // return res; + } + + if (dec->state == XZ_STATE_STREAM_HEADER) + { + *needContinue = True; + me->mtc.crossStart = inPos; + me->mtc.crossEnd = inLim; + me->isBlockHeaderState_Parse = False; + me->isBlockHeaderState_Write = False; + return SZ_OK; + } + + if (status != CODER_STATUS_NEEDS_MORE_INPUT) + return E_FAIL; + + if (me->mtc.progress) + { + UInt64 inDelta = me->mtc.inProcessed - inProgressPrev; + if (inDelta >= (1 << 22)) + { + RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress)); + inProgressPrev = me->mtc.inProcessed; + } + } + if (me->mtc.readWasFinished) + return SZ_OK; + } + } + } +} + + +#endif + + + +void XzStatInfo_Clear(CXzStatInfo *p) +{ + p->InSize = 0; + p->OutSize = 0; + + p->NumStreams = 0; + p->NumBlocks = 0; + + p->UnpackSize_Defined = False; + + p->NumStreams_Defined = False; + p->NumBlocks_Defined = False; + + // p->IsArc = False; + // p->UnexpectedEnd = False; + // p->Unsupported = False; + // p->HeadersError = False; + // p->DataError = False; + // p->CrcError = False; + + p->DataAfterEnd = False; + p->DecodingTruncated = False; + + p->DecodeRes = SZ_OK; + p->ReadRes = SZ_OK; + p->ProgressRes = SZ_OK; + + p->CombinedRes = SZ_OK; + p->CombinedRes_Type = SZ_OK; +} + + + + +static SRes XzDecMt_Decode_ST(CXzDecMt *p + #ifndef _7ZIP_ST + , Bool tMode + #endif + , CXzStatInfo *stat) +{ + size_t outPos; + size_t inPos, inLim; + const Byte *inData; + UInt64 inPrev, outPrev; + + CXzUnpacker *dec; + + #ifndef _7ZIP_ST + if (tMode) + { + XzDecMt_FreeOutBufs(p); + tMode = MtDec_PrepareRead(&p->mtc); + } + #endif + + if (!p->outBuf || p->outBufSize != p->props.outStep_ST) + { + ISzAlloc_Free(p->allocMid, p->outBuf); + p->outBufSize = 0; + p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST); + if (!p->outBuf) + return SZ_ERROR_MEM; + p->outBufSize = p->props.outStep_ST; + } + + if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBufSize = 0; + p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); + if (!p->inBuf) + return SZ_ERROR_MEM; + p->inBufSize = p->props.inBufSize_ST; + } + + dec = &p->dec; + dec->decodeToStreamSignature = False; + // dec->decodeOnlyOneBlock = False; + + XzUnpacker_SetOutBuf(dec, NULL, 0); + + inPrev = p->inProcessed; + outPrev = p->outProcessed; + + inPos = 0; + inLim = 0; + inData = NULL; + outPos = 0; + + for (;;) + { + SizeT outSize; + Bool finished; + ECoderFinishMode finishMode; + SizeT inProcessed; + ECoderStatus status; + SRes res; + + SizeT outProcessed; + + + + if (inPos == inLim) + { + #ifndef _7ZIP_ST + if (tMode) + { + inData = MtDec_Read(&p->mtc, &inLim); + inPos = 0; + if (inData) + continue; + tMode = False; + inLim = 0; + } + #endif + + if (!p->readWasFinished) + { + inPos = 0; + inLim = p->inBufSize; + inData = p->inBuf; + p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim); + p->readProcessed += inLim; + if (inLim == 0 || p->readRes != SZ_OK) + p->readWasFinished = True; + } + } + + outSize = p->props.outStep_ST - outPos; + + finishMode = CODER_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (outSize >= rem) + { + outSize = (SizeT)rem; + if (p->finishMode) + finishMode = CODER_FINISH_END; + } + } + + inProcessed = inLim - inPos; + outProcessed = outSize; + + res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed, + inData + inPos, &inProcessed, + (inPos == inLim), // srcFinished + finishMode, &status); + + p->codeRes = res; + p->status = status; + + inPos += inProcessed; + outPos += outProcessed; + p->inProcessed += inProcessed; + p->outProcessed += outProcessed; + + finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK); + + if (finished || outProcessed >= outSize) + if (outPos != 0) + { + size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos); + p->outProcessed += written; + if (written != outPos) + { + stat->CombinedRes_Type = SZ_ERROR_WRITE; + return SZ_ERROR_WRITE; + } + outPos = 0; + } + + if (p->progress && res == SZ_OK) + { + UInt64 inDelta = p->inProcessed - inPrev; + UInt64 outDelta = p->outProcessed - outPrev; + if (inDelta >= (1 << 22) || outDelta >= (1 << 22)) + { + res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed); + if (res != SZ_OK) + { + stat->CombinedRes_Type = SZ_ERROR_PROGRESS; + stat->ProgressRes = res; + return res; + } + inPrev = p->inProcessed; + outPrev = p->outProcessed; + } + } + + if (finished) + return res; + } +} + +static SRes XzStatInfo_SetStat(const CXzUnpacker *dec, + int finishMode, + UInt64 readProcessed, UInt64 inProcessed, + SRes res, ECoderStatus status, + Bool decodingTruncated, + CXzStatInfo *stat) +{ + UInt64 extraSize; + + stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0); + stat->InSize = inProcessed; + stat->NumStreams = dec->numStartedStreams; + stat->NumBlocks = dec->numTotalBlocks; + + stat->UnpackSize_Defined = True; + stat->NumStreams_Defined = True; + stat->NumBlocks_Defined = True; + + extraSize = XzUnpacker_GetExtraSize(dec); + + if (res == SZ_OK) + { + if (status == CODER_STATUS_NEEDS_MORE_INPUT) + { + // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams + extraSize = 0; + if (!XzUnpacker_IsStreamWasFinished(dec)) + res = SZ_ERROR_INPUT_EOF; + } + else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED) + res = SZ_ERROR_DATA; + } + else if (res == SZ_ERROR_NO_ARCHIVE) + { + /* + SZ_ERROR_NO_ARCHIVE is possible for 2 states: + XZ_STATE_STREAM_HEADER - if bad signature or bad CRC + XZ_STATE_STREAM_PADDING - if non-zero padding data + extraSize / inProcessed don't include "bad" byte + */ + if (inProcessed != extraSize) // if good streams before error + if (extraSize != 0 || readProcessed != inProcessed) + { + stat->DataAfterEnd = True; + // there is some good xz stream before. So we set SZ_OK + res = SZ_OK; + } + } + + stat->DecodeRes = res; + + stat->InSize -= extraSize; + return res; +} + + +SRes XzDecMt_Decode(CXzDecMtHandle pp, + const CXzDecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqOutStream *outStream, + // Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + // const Byte *inData, size_t inDataSize, + CXzStatInfo *stat, + int *isMT, + ICompressProgress *progress) +{ + CXzDecMt *p = (CXzDecMt *)pp; + #ifndef _7ZIP_ST + Bool tMode; + #endif + + XzStatInfo_Clear(stat); + + p->props = *props; + + p->inStream = inStream; + p->outStream = outStream; + p->progress = progress; + // p->stat = stat; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + + p->finishMode = finishMode; + + // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test + + p->writeRes = SZ_OK; + p->outProcessed = 0; + p->inProcessed = 0; + p->readProcessed = 0; + p->readWasFinished = False; + + p->codeRes = 0; + p->status = CODER_STATUS_NOT_SPECIFIED; + + if (!p->dec_created) + { + XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt); + p->dec_created = True; + } + XzUnpacker_Init(&p->dec); + + + *isMT = False; + + /* + p->outBuf = NULL; + p->outBufSize = 0; + if (!outStream) + { + p->outBuf = outBuf; + p->outBufSize = *outBufSize; + *outBufSize = 0; + } + */ + + + #ifndef _7ZIP_ST + + p->isBlockHeaderState_Parse = False; + p->isBlockHeaderState_Write = False; + // p->numBadBlocks = 0; + p->mainErrorCode = SZ_OK; + p->mainDecoderWasCalled = False; + + tMode = False; + + if (p->props.numThreads > 1) + { + IMtDecCallback vt; + + XzDecMt_FreeSt(p); + + p->outProcessed_Parse = 0; + p->parsing_Truncated = False; + + p->numStreams = 0; + p->numTotalBlocks = 0; + p->numBlocks = 0; + p->finishedDecoderIndex = -1; + + if (!p->mtc_WasConstructed) + { + p->mtc_WasConstructed = True; + MtDec_Construct(&p->mtc); + } + + p->mtc.mtCallback = &vt; + p->mtc.mtCallbackObject = p; + + p->mtc.progress = progress; + p->mtc.inStream = inStream; + p->mtc.alloc = &p->alignOffsetAlloc.vt; + // p->mtc.inData = inData; + // p->mtc.inDataSize = inDataSize; + p->mtc.inBufSize = p->props.inBufSize_MT; + // p->mtc.inBlockMax = p->props.inBlockMax; + p->mtc.numThreadsMax = p->props.numThreads; + + *isMT = True; + + vt.Parse = XzDecMt_Callback_Parse; + vt.PreCode = XzDecMt_Callback_PreCode; + vt.Code = XzDecMt_Callback_Code; + vt.Write = XzDecMt_Callback_Write; + + { + Bool needContinue; + + SRes res = MtDec_Code(&p->mtc); + + stat->InSize = p->mtc.inProcessed; + + p->inProcessed = p->mtc.inProcessed; + p->readRes = p->mtc.readRes; + p->readWasFinished = p->mtc.readWasFinished; + p->readProcessed = p->mtc.readProcessed; + + tMode = True; + needContinue = False; + + if (res == SZ_OK) + { + if (p->mtc.mtProgress.res != SZ_OK) + { + res = p->mtc.mtProgress.res; + stat->ProgressRes = res; + stat->CombinedRes_Type = SZ_ERROR_PROGRESS; + } + else + needContinue = p->mtc.needContinue; + } + + if (!needContinue) + { + SRes codeRes; + Bool truncated = False; + ECoderStatus status; + CXzUnpacker *dec; + + stat->OutSize = p->outProcessed; + + if (p->finishedDecoderIndex >= 0) + { + CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex]; + codeRes = coder->codeRes; + dec = &coder->dec; + status = coder->status; + } + else if (p->mainDecoderWasCalled) + { + codeRes = p->codeRes; + dec = &p->dec; + status = p->status; + truncated = p->parsing_Truncated; + } + else + return E_FAIL; + + XzStatInfo_SetStat(dec, p->finishMode, + p->mtc.readProcessed, p->mtc.inProcessed, + codeRes, status, + truncated, + stat); + + if (res == SZ_OK) + { + if (p->writeRes != SZ_OK) + { + res = p->writeRes; + stat->CombinedRes_Type = SZ_ERROR_WRITE; + } + else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed) + { + res = p->mtc.readRes; + stat->ReadRes = res; + stat->CombinedRes_Type = SZ_ERROR_READ; + } + else if (p->mainErrorCode != SZ_OK) + { + res = p->mainErrorCode; + } + } + + stat->CombinedRes = res; + if (stat->CombinedRes_Type == SZ_OK) + stat->CombinedRes_Type = res; + return res; + } + + PRF_STR("----- decoding ST -----"); + } + } + + #endif + + + *isMT = False; + + { + SRes res = XzDecMt_Decode_ST(p + #ifndef _7ZIP_ST + , tMode + #endif + , stat + ); + + XzStatInfo_SetStat(&p->dec, + p->finishMode, + p->readProcessed, p->inProcessed, + p->codeRes, p->status, + False, // truncated + stat); + + if (res == SZ_OK) + { + /* + if (p->writeRes != SZ_OK) + { + res = p->writeRes; + stat->CombinedRes_Type = SZ_ERROR_WRITE; + } + else + */ + if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed) + { + res = p->readRes; + stat->ReadRes = res; + stat->CombinedRes_Type = SZ_ERROR_READ; + } + #ifndef _7ZIP_ST + else if (p->mainErrorCode != SZ_OK) + res = p->mainErrorCode; + #endif + } + + stat->CombinedRes = res; + if (stat->CombinedRes_Type == SZ_OK) + stat->CombinedRes_Type = res; + return res; + } +} diff --git a/other-licenses/7zstub/src/C/XzEnc.c b/other-licenses/7zstub/src/C/XzEnc.c new file mode 100644 index 0000000000..432cbfe79c --- /dev/null +++ b/other-licenses/7zstub/src/C/XzEnc.c @@ -0,0 +1,1329 @@ +/* XzEnc.c -- Xz Encode +2018-04-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include +#include + +#include "7zCrc.h" +#include "Bra.h" +#include "CpuArch.h" + +#ifdef USE_SUBBLOCK +#include "Bcj3Enc.c" +#include "SbFind.c" +#include "SbEnc.c" +#endif + +#include "XzEnc.h" + +// #define _7ZIP_ST + +#ifndef _7ZIP_ST +#include "MtCoder.h" +#else +#define MTCODER__THREADS_MAX 1 +#define MTCODER__BLOCKS_MAX 1 +#endif + +#define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3) + +/* max pack size for LZMA2 block + check-64bytrs: */ +#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + 64) + +#define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize)) + + +#define XzBlock_ClearFlags(p) (p)->flags = 0; +#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1); +#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE; +#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE; + + +static SRes WriteBytes(ISeqOutStream *s, const void *buf, size_t size) +{ + return (ISeqOutStream_Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE; +} + +static SRes WriteBytesUpdateCrc(ISeqOutStream *s, const void *buf, size_t size, UInt32 *crc) +{ + *crc = CrcUpdate(*crc, buf, size); + return WriteBytes(s, buf, size); +} + + +static SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s) +{ + UInt32 crc; + Byte header[XZ_STREAM_HEADER_SIZE]; + memcpy(header, XZ_SIG, XZ_SIG_SIZE); + header[XZ_SIG_SIZE] = (Byte)(f >> 8); + header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF); + crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE); + SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc); + return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE); +} + + +static SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + + unsigned pos = 1; + unsigned numFilters, i; + header[pos++] = p->flags; + + if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize); + if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize); + numFilters = XzBlock_GetNumFilters(p); + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &p->filters[i]; + pos += Xz_WriteVarInt(header + pos, f->id); + pos += Xz_WriteVarInt(header + pos, f->propsSize); + memcpy(header + pos, f->props, f->propsSize); + pos += f->propsSize; + } + + while ((pos & 3) != 0) + header[pos++] = 0; + + header[0] = (Byte)(pos >> 2); + SetUi32(header + pos, CrcCalc(header, pos)); + return WriteBytes(s, header, pos + 4); +} + + + + +typedef struct +{ + size_t numBlocks; + size_t size; + size_t allocated; + Byte *blocks; +} CXzEncIndex; + + +static void XzEncIndex_Construct(CXzEncIndex *p) +{ + p->numBlocks = 0; + p->size = 0; + p->allocated = 0; + p->blocks = NULL; +} + +static void XzEncIndex_Init(CXzEncIndex *p) +{ + p->numBlocks = 0; + p->size = 0; +} + +static void XzEncIndex_Free(CXzEncIndex *p, ISzAllocPtr alloc) +{ + if (p->blocks) + { + ISzAlloc_Free(alloc, p->blocks); + p->blocks = NULL; + } + p->numBlocks = 0; + p->size = 0; + p->allocated = 0; +} + + +static SRes XzEncIndex_ReAlloc(CXzEncIndex *p, size_t newSize, ISzAllocPtr alloc) +{ + Byte *blocks = (Byte *)ISzAlloc_Alloc(alloc, newSize); + if (!blocks) + return SZ_ERROR_MEM; + if (p->size != 0) + memcpy(blocks, p->blocks, p->size); + if (p->blocks) + ISzAlloc_Free(alloc, p->blocks); + p->blocks = blocks; + p->allocated = newSize; + return SZ_OK; +} + + +static SRes XzEncIndex_PreAlloc(CXzEncIndex *p, UInt64 numBlocks, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc) +{ + UInt64 pos; + { + Byte buf[32]; + unsigned pos2 = Xz_WriteVarInt(buf, totalSize); + pos2 += Xz_WriteVarInt(buf + pos2, unpackSize); + pos = numBlocks * pos2; + } + + if (pos <= p->allocated - p->size) + return SZ_OK; + { + UInt64 newSize64 = p->size + pos; + size_t newSize = (size_t)newSize64; + if (newSize != newSize64) + return SZ_ERROR_MEM; + return XzEncIndex_ReAlloc(p, newSize, alloc); + } +} + + +static SRes XzEncIndex_AddIndexRecord(CXzEncIndex *p, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc) +{ + Byte buf[32]; + unsigned pos = Xz_WriteVarInt(buf, totalSize); + pos += Xz_WriteVarInt(buf + pos, unpackSize); + + if (pos > p->allocated - p->size) + { + size_t newSize = p->allocated * 2 + 16 * 2; + if (newSize < p->size + pos) + return SZ_ERROR_MEM; + RINOK(XzEncIndex_ReAlloc(p, newSize, alloc)); + } + memcpy(p->blocks + p->size, buf, pos); + p->size += pos; + p->numBlocks++; + return SZ_OK; +} + + +static SRes XzEncIndex_WriteFooter(const CXzEncIndex *p, CXzStreamFlags flags, ISeqOutStream *s) +{ + Byte buf[32]; + UInt64 globalPos; + UInt32 crc = CRC_INIT_VAL; + unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks); + + globalPos = pos; + buf[0] = 0; + RINOK(WriteBytesUpdateCrc(s, buf, pos, &crc)); + RINOK(WriteBytesUpdateCrc(s, p->blocks, p->size, &crc)); + globalPos += p->size; + + pos = XZ_GET_PAD_SIZE(globalPos); + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + globalPos += pos; + + crc = CrcUpdate(crc, buf + 4 - pos, pos); + SetUi32(buf + 4, CRC_GET_DIGEST(crc)); + + SetUi32(buf + 8 + 4, (UInt32)(globalPos >> 2)); + buf[8 + 8] = (Byte)(flags >> 8); + buf[8 + 9] = (Byte)(flags & 0xFF); + SetUi32(buf + 8, CrcCalc(buf + 8 + 4, 6)); + buf[8 + 10] = XZ_FOOTER_SIG_0; + buf[8 + 11] = XZ_FOOTER_SIG_1; + + return WriteBytes(s, buf + 4 - pos, pos + 4 + 12); +} + + + +/* ---------- CSeqCheckInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + ISeqInStream *realStream; + const Byte *data; + UInt64 limit; + UInt64 processed; + int realStreamFinished; + CXzCheck check; +} CSeqCheckInStream; + +static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned checkMode) +{ + p->limit = (UInt64)(Int64)-1; + p->processed = 0; + p->realStreamFinished = 0; + XzCheck_Init(&p->check, checkMode); +} + +static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest) +{ + XzCheck_Final(&p->check, digest); +} + +static SRes SeqCheckInStream_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CSeqCheckInStream *p = CONTAINER_FROM_VTBL(pp, CSeqCheckInStream, vt); + size_t size2 = *size; + SRes res = SZ_OK; + + if (p->limit != (UInt64)(Int64)-1) + { + UInt64 rem = p->limit - p->processed; + if (size2 > rem) + size2 = (size_t)rem; + } + if (size2 != 0) + { + if (p->realStream) + { + res = ISeqInStream_Read(p->realStream, data, &size2); + p->realStreamFinished = (size2 == 0) ? 1 : 0; + } + else + memcpy(data, p->data + (size_t)p->processed, size2); + XzCheck_Update(&p->check, data, size2); + p->processed += size2; + } + *size = size2; + return res; +} + + +/* ---------- CSeqSizeOutStream ---------- */ + +typedef struct +{ + ISeqOutStream vt; + ISeqOutStream *realStream; + Byte *outBuf; + size_t outBufLimit; + UInt64 processed; +} CSeqSizeOutStream; + +static size_t SeqSizeOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size) +{ + CSeqSizeOutStream *p = CONTAINER_FROM_VTBL(pp, CSeqSizeOutStream, vt); + if (p->realStream) + size = ISeqOutStream_Write(p->realStream, data, size); + else + { + if (size > p->outBufLimit - (size_t)p->processed) + return 0; + memcpy(p->outBuf + (size_t)p->processed, data, size); + } + p->processed += size; + return size; +} + + +/* ---------- CSeqInFilter ---------- */ + +#define FILTER_BUF_SIZE (1 << 20) + +typedef struct +{ + ISeqInStream p; + ISeqInStream *realStream; + IStateCoder StateCoder; + Byte *buf; + size_t curPos; + size_t endPos; + int srcWasFinished; +} CSeqInFilter; + + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc); + +static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props, ISzAllocPtr alloc) +{ + if (!p->buf) + { + p->buf = (Byte *)ISzAlloc_Alloc(alloc, FILTER_BUF_SIZE); + if (!p->buf) + return SZ_ERROR_MEM; + } + p->curPos = p->endPos = 0; + p->srcWasFinished = 0; + RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, alloc)); + RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, alloc)); + p->StateCoder.Init(p->StateCoder.p); + return SZ_OK; +} + + +static SRes SeqInFilter_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CSeqInFilter *p = CONTAINER_FROM_VTBL(pp, CSeqInFilter, p); + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return SZ_OK; + *size = 0; + + for (;;) + { + if (!p->srcWasFinished && p->curPos == p->endPos) + { + p->curPos = 0; + p->endPos = FILTER_BUF_SIZE; + RINOK(ISeqInStream_Read(p->realStream, p->buf, &p->endPos)); + if (p->endPos == 0) + p->srcWasFinished = 1; + } + { + SizeT srcLen = p->endPos - p->curPos; + ECoderStatus status; + SRes res; + *size = sizeOriginal; + res = p->StateCoder.Code2(p->StateCoder.p, + data, size, + p->buf + p->curPos, &srcLen, + p->srcWasFinished, CODER_FINISH_ANY, + &status); + p->curPos += srcLen; + if (*size != 0 || srcLen == 0 || res != SZ_OK) + return res; + } + } +} + +static void SeqInFilter_Construct(CSeqInFilter *p) +{ + p->buf = NULL; + p->StateCoder.p = NULL; + p->p.Read = SeqInFilter_Read; +} + +static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc) +{ + if (p->StateCoder.p) + { + p->StateCoder.Free(p->StateCoder.p, alloc); + p->StateCoder.p = NULL; + } + if (p->buf) + { + ISzAlloc_Free(alloc, p->buf); + p->buf = NULL; + } +} + + +/* ---------- CSbEncInStream ---------- */ + +#ifdef USE_SUBBLOCK + +typedef struct +{ + ISeqInStream vt; + ISeqInStream *inStream; + CSbEnc enc; +} CSbEncInStream; + +static SRes SbEncInStream_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CSbEncInStream *p = CONTAINER_FROM_VTBL(pp, CSbEncInStream, vt); + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return SZ_OK; + + for (;;) + { + if (p->enc.needRead && !p->enc.readWasFinished) + { + size_t processed = p->enc.needReadSizeMax; + RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed)); + p->enc.readPos += processed; + if (processed == 0) + { + p->enc.readWasFinished = True; + p->enc.isFinalFinished = True; + } + p->enc.needRead = False; + } + + *size = sizeOriginal; + RINOK(SbEnc_Read(&p->enc, data, size)); + if (*size != 0 || !p->enc.needRead) + return SZ_OK; + } +} + +void SbEncInStream_Construct(CSbEncInStream *p, ISzAllocPtr alloc) +{ + SbEnc_Construct(&p->enc, alloc); + p->vt.Read = SbEncInStream_Read; +} + +SRes SbEncInStream_Init(CSbEncInStream *p) +{ + return SbEnc_Init(&p->enc); +} + +void SbEncInStream_Free(CSbEncInStream *p) +{ + SbEnc_Free(&p->enc); +} + +#endif + + + +/* ---------- CXzProps ---------- */ + + +void XzFilterProps_Init(CXzFilterProps *p) +{ + p->id = 0; + p->delta = 0; + p->ip = 0; + p->ipDefined = False; +} + +void XzProps_Init(CXzProps *p) +{ + p->checkId = XZ_CHECK_CRC32; + p->blockSize = XZ_PROPS__BLOCK_SIZE__AUTO; + p->numBlockThreads_Reduced = -1; + p->numBlockThreads_Max = -1; + p->numTotalThreads = -1; + p->reduceSize = (UInt64)(Int64)-1; + p->forceWriteSizesInHeader = 0; + // p->forceWriteSizesInHeader = 1; + + XzFilterProps_Init(&p->filterProps); + Lzma2EncProps_Init(&p->lzma2Props); +} + + +static void XzEncProps_Normalize_Fixed(CXzProps *p) +{ + UInt64 fileSize; + int t1, t1n, t2, t2r, t3; + { + CLzma2EncProps tp = p->lzma2Props; + if (tp.numTotalThreads <= 0) + tp.numTotalThreads = p->numTotalThreads; + Lzma2EncProps_Normalize(&tp); + t1n = tp.numTotalThreads; + } + + t1 = p->lzma2Props.numTotalThreads; + t2 = p->numBlockThreads_Max; + t3 = p->numTotalThreads; + + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + + if (t3 <= 0) + { + if (t2 <= 0) + t2 = 1; + t3 = t1n * t2; + } + else if (t2 <= 0) + { + t2 = t3 / t1n; + if (t2 == 0) + { + t1 = 1; + t2 = t3; + } + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzma2Props.numTotalThreads = t1; + + t2r = t2; + + fileSize = p->reduceSize; + + if ((p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) + p->lzma2Props.lzmaProps.reduceSize = p->blockSize; + + Lzma2EncProps_Normalize(&p->lzma2Props); + + t1 = p->lzma2Props.numTotalThreads; + + { + if (t2 > 1 && fileSize != (UInt64)(Int64)-1) + { + UInt64 numBlocks = fileSize / p->blockSize; + if (numBlocks * p->blockSize != fileSize) + numBlocks++; + if (numBlocks < (unsigned)t2) + { + t2r = (unsigned)numBlocks; + if (t2r == 0) + t2r = 1; + t3 = t1 * t2r; + } + } + } + + p->numBlockThreads_Max = t2; + p->numBlockThreads_Reduced = t2r; + p->numTotalThreads = t3; +} + + +static void XzProps_Normalize(CXzProps *p) +{ + /* we normalize xzProps properties, but we normalize only some of CXzProps::lzma2Props properties. + Lzma2Enc_SetProps() will normalize lzma2Props later. */ + + if (p->blockSize == XZ_PROPS__BLOCK_SIZE__SOLID) + { + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + p->numBlockThreads_Reduced = 1; + p->numBlockThreads_Max = 1; + if (p->lzma2Props.numTotalThreads <= 0) + p->lzma2Props.numTotalThreads = p->numTotalThreads; + return; + } + else + { + CLzma2EncProps *lzma2 = &p->lzma2Props; + if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + { + // xz-auto + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + + if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + { + // if (xz-auto && lzma2-solid) - we use solid for both + p->blockSize = XZ_PROPS__BLOCK_SIZE__SOLID; + p->numBlockThreads_Reduced = 1; + p->numBlockThreads_Max = 1; + if (p->lzma2Props.numTotalThreads <= 0) + p->lzma2Props.numTotalThreads = p->numTotalThreads; + } + else + { + // if (xz-auto && (lzma2-auto || lzma2-fixed_) + // we calculate block size for lzma2 and use that block size for xz, lzma2 uses single-chunk per block + CLzma2EncProps tp = p->lzma2Props; + if (tp.numTotalThreads <= 0) + tp.numTotalThreads = p->numTotalThreads; + + Lzma2EncProps_Normalize(&tp); + + p->blockSize = tp.blockSize; // fixed or solid + p->numBlockThreads_Reduced = tp.numBlockThreads_Reduced; + p->numBlockThreads_Max = tp.numBlockThreads_Max; + if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + lzma2->blockSize = tp.blockSize; // fixed or solid, LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + if (lzma2->lzmaProps.reduceSize > tp.blockSize && tp.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + lzma2->lzmaProps.reduceSize = tp.blockSize; + lzma2->numBlockThreads_Reduced = 1; + lzma2->numBlockThreads_Max = 1; + return; + } + } + else + { + // xz-fixed + // we can use xz::reduceSize or xz::blockSize as base for lzmaProps::reduceSize + + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + { + UInt64 r = p->reduceSize; + if (r > p->blockSize || r == (UInt64)(Int64)-1) + r = p->blockSize; + lzma2->lzmaProps.reduceSize = r; + } + if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + lzma2->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID; + else if (lzma2->blockSize > p->blockSize && lzma2->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + lzma2->blockSize = p->blockSize; + + XzEncProps_Normalize_Fixed(p); + } + } +} + + +/* ---------- CLzma2WithFilters ---------- */ + +typedef struct +{ + CLzma2EncHandle lzma2; + CSeqInFilter filter; + + #ifdef USE_SUBBLOCK + CSbEncInStream sb; + #endif +} CLzma2WithFilters; + + +static void Lzma2WithFilters_Construct(CLzma2WithFilters *p) +{ + p->lzma2 = NULL; + SeqInFilter_Construct(&p->filter); + + #ifdef USE_SUBBLOCK + SbEncInStream_Construct(&p->sb, alloc); + #endif +} + + +static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p, ISzAllocPtr alloc, ISzAllocPtr bigAlloc) +{ + if (!p->lzma2) + { + p->lzma2 = Lzma2Enc_Create(alloc, bigAlloc); + if (!p->lzma2) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + + +static void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc) +{ + #ifdef USE_SUBBLOCK + SbEncInStream_Free(&p->sb); + #endif + + SeqInFilter_Free(&p->filter, alloc); + if (p->lzma2) + { + Lzma2Enc_Destroy(p->lzma2); + p->lzma2 = NULL; + } +} + + +typedef struct +{ + UInt64 unpackSize; + UInt64 totalSize; + size_t headerSize; +} CXzEncBlockInfo; + + +static SRes Xz_CompressBlock( + CLzma2WithFilters *lzmaf, + + ISeqOutStream *outStream, + Byte *outBufHeader, + Byte *outBufData, size_t outBufDataLimit, + + ISeqInStream *inStream, + // UInt64 expectedSize, + const Byte *inBuf, // used if (!inStream) + size_t inBufSize, // used if (!inStream), it's block size, props->blockSize is ignored + + const CXzProps *props, + ICompressProgress *progress, + int *inStreamFinished, /* only for inStream version */ + CXzEncBlockInfo *blockSizes, + ISzAllocPtr alloc, + ISzAllocPtr allocBig) +{ + CSeqCheckInStream checkInStream; + CSeqSizeOutStream seqSizeOutStream; + CXzBlock block; + unsigned filterIndex = 0; + CXzFilter *filter = NULL; + const CXzFilterProps *fp = &props->filterProps; + if (fp->id == 0) + fp = NULL; + + *inStreamFinished = False; + + RINOK(Lzma2WithFilters_Create(lzmaf, alloc, allocBig)); + + RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, &props->lzma2Props)); + + XzBlock_ClearFlags(&block); + XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0)); + + if (fp) + { + filter = &block.filters[filterIndex++]; + filter->id = fp->id; + filter->propsSize = 0; + + if (fp->id == XZ_ID_Delta) + { + filter->props[0] = (Byte)(fp->delta - 1); + filter->propsSize = 1; + } + else if (fp->ipDefined) + { + SetUi32(filter->props, fp->ip); + filter->propsSize = 4; + } + } + + { + CXzFilter *f = &block.filters[filterIndex++]; + f->id = XZ_ID_LZMA2; + f->propsSize = 1; + f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2); + } + + seqSizeOutStream.vt.Write = SeqSizeOutStream_Write; + seqSizeOutStream.realStream = outStream; + seqSizeOutStream.outBuf = outBufData; + seqSizeOutStream.outBufLimit = outBufDataLimit; + seqSizeOutStream.processed = 0; + + /* + if (expectedSize != (UInt64)(Int64)-1) + { + block.unpackSize = expectedSize; + if (props->blockSize != (UInt64)(Int64)-1) + if (expectedSize > props->blockSize) + block.unpackSize = props->blockSize; + XzBlock_SetHasUnpackSize(&block); + } + */ + + if (outStream) + { + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt)); + } + + checkInStream.vt.Read = SeqCheckInStream_Read; + SeqCheckInStream_Init(&checkInStream, props->checkId); + + checkInStream.realStream = inStream; + checkInStream.data = inBuf; + checkInStream.limit = props->blockSize; + if (!inStream) + checkInStream.limit = inBufSize; + + if (fp) + { + #ifdef USE_SUBBLOCK + if (fp->id == XZ_ID_Subblock) + { + lzmaf->sb.inStream = &checkInStream.vt; + RINOK(SbEncInStream_Init(&lzmaf->sb)); + } + else + #endif + { + lzmaf->filter.realStream = &checkInStream.vt; + RINOK(SeqInFilter_Init(&lzmaf->filter, filter, alloc)); + } + } + + { + SRes res; + Byte *outBuf = NULL; + size_t outSize = 0; + Bool useStream = (fp || inStream); + // useStream = True; + + if (!useStream) + { + XzCheck_Update(&checkInStream.check, inBuf, inBufSize); + checkInStream.processed = inBufSize; + } + + if (!outStream) + { + outBuf = seqSizeOutStream.outBuf; // + (size_t)seqSizeOutStream.processed; + outSize = seqSizeOutStream.outBufLimit; // - (size_t)seqSizeOutStream.processed; + } + + res = Lzma2Enc_Encode2(lzmaf->lzma2, + outBuf ? NULL : &seqSizeOutStream.vt, + outBuf, + outBuf ? &outSize : NULL, + + useStream ? + (fp ? + ( + #ifdef USE_SUBBLOCK + (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.vt: + #endif + &lzmaf->filter.p) : + &checkInStream.vt) : NULL, + + useStream ? NULL : inBuf, + useStream ? 0 : inBufSize, + + progress); + + if (outBuf) + seqSizeOutStream.processed += outSize; + + RINOK(res); + blockSizes->unpackSize = checkInStream.processed; + } + { + Byte buf[4 + 64]; + unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed); + UInt64 packSize = seqSizeOutStream.processed; + + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + + SeqCheckInStream_GetDigest(&checkInStream, buf + 4); + RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize), padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId))); + + blockSizes->totalSize = seqSizeOutStream.processed - padSize; + + if (!outStream) + { + seqSizeOutStream.outBuf = outBufHeader; + seqSizeOutStream.outBufLimit = XZ_BLOCK_HEADER_SIZE_MAX; + seqSizeOutStream.processed = 0; + + block.unpackSize = blockSizes->unpackSize; + XzBlock_SetHasUnpackSize(&block); + + block.packSize = packSize; + XzBlock_SetHasPackSize(&block); + + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt)); + + blockSizes->headerSize = (size_t)seqSizeOutStream.processed; + blockSizes->totalSize += seqSizeOutStream.processed; + } + } + + if (inStream) + *inStreamFinished = checkInStream.realStreamFinished; + else + { + *inStreamFinished = False; + if (checkInStream.processed != inBufSize) + return SZ_ERROR_FAIL; + } + + return SZ_OK; +} + + + +typedef struct +{ + ICompressProgress vt; + ICompressProgress *progress; + UInt64 inOffset; + UInt64 outOffset; +} CCompressProgress_XzEncOffset; + + +static SRes CompressProgress_XzEncOffset_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) +{ + const CCompressProgress_XzEncOffset *p = CONTAINER_FROM_VTBL(pp, CCompressProgress_XzEncOffset, vt); + inSize += p->inOffset; + outSize += p->outOffset; + return ICompressProgress_Progress(p->progress, inSize, outSize); +} + + + + +typedef struct +{ + ISzAllocPtr alloc; + ISzAllocPtr allocBig; + + CXzProps xzProps; + UInt64 expectedDataSize; + + CXzEncIndex xzIndex; + + CLzma2WithFilters lzmaf_Items[MTCODER__THREADS_MAX]; + + size_t outBufSize; /* size of allocated outBufs[i] */ + Byte *outBufs[MTCODER__BLOCKS_MAX]; + + #ifndef _7ZIP_ST + unsigned checkType; + ISeqOutStream *outStream; + Bool mtCoder_WasConstructed; + CMtCoder mtCoder; + CXzEncBlockInfo EncBlocks[MTCODER__BLOCKS_MAX]; + #endif + +} CXzEnc; + + +static void XzEnc_Construct(CXzEnc *p) +{ + unsigned i; + + XzEncIndex_Construct(&p->xzIndex); + + for (i = 0; i < MTCODER__THREADS_MAX; i++) + Lzma2WithFilters_Construct(&p->lzmaf_Items[i]); + + #ifndef _7ZIP_ST + p->mtCoder_WasConstructed = False; + { + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + p->outBufs[i] = NULL; + p->outBufSize = 0; + } + #endif +} + + +static void XzEnc_FreeOutBufs(CXzEnc *p) +{ + unsigned i; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + if (p->outBufs[i]) + { + ISzAlloc_Free(p->alloc, p->outBufs[i]); + p->outBufs[i] = NULL; + } + p->outBufSize = 0; +} + + +static void XzEnc_Free(CXzEnc *p, ISzAllocPtr alloc) +{ + unsigned i; + + XzEncIndex_Free(&p->xzIndex, alloc); + + for (i = 0; i < MTCODER__THREADS_MAX; i++) + Lzma2WithFilters_Free(&p->lzmaf_Items[i], alloc); + + #ifndef _7ZIP_ST + if (p->mtCoder_WasConstructed) + { + MtCoder_Destruct(&p->mtCoder); + p->mtCoder_WasConstructed = False; + } + XzEnc_FreeOutBufs(p); + #endif +} + + +CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CXzEnc *p = (CXzEnc *)ISzAlloc_Alloc(alloc, sizeof(CXzEnc)); + if (!p) + return NULL; + XzEnc_Construct(p); + XzProps_Init(&p->xzProps); + XzProps_Normalize(&p->xzProps); + p->expectedDataSize = (UInt64)(Int64)-1; + p->alloc = alloc; + p->allocBig = allocBig; + return p; +} + + +void XzEnc_Destroy(CXzEncHandle pp) +{ + CXzEnc *p = (CXzEnc *)pp; + XzEnc_Free(p, p->alloc); + ISzAlloc_Free(p->alloc, p); +} + + +SRes XzEnc_SetProps(CXzEncHandle pp, const CXzProps *props) +{ + CXzEnc *p = (CXzEnc *)pp; + p->xzProps = *props; + XzProps_Normalize(&p->xzProps); + return SZ_OK; +} + + +void XzEnc_SetDataSize(CXzEncHandle pp, UInt64 expectedDataSiize) +{ + CXzEnc *p = (CXzEnc *)pp; + p->expectedDataSize = expectedDataSiize; +} + + + + +#ifndef _7ZIP_ST + +static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished) +{ + CXzEnc *me = (CXzEnc *)pp; + SRes res; + CMtProgressThunk progressThunk; + + Byte *dest = me->outBufs[outBufIndex]; + + UNUSED_VAR(finished) + + { + CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; + bInfo->totalSize = 0; + bInfo->unpackSize = 0; + bInfo->headerSize = 0; + } + + if (!dest) + { + dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); + if (!dest) + return SZ_ERROR_MEM; + me->outBufs[outBufIndex] = dest; + } + + MtProgressThunk_CreateVTable(&progressThunk); + progressThunk.mtProgress = &me->mtCoder.mtProgress; + MtProgressThunk_Init(&progressThunk); + + { + CXzEncBlockInfo blockSizes; + int inStreamFinished; + + res = Xz_CompressBlock( + &me->lzmaf_Items[coderIndex], + + NULL, + dest, + dest + XZ_BLOCK_HEADER_SIZE_MAX, me->outBufSize - XZ_BLOCK_HEADER_SIZE_MAX, + + NULL, + // srcSize, // expectedSize + src, srcSize, + + &me->xzProps, + &progressThunk.vt, + &inStreamFinished, + &blockSizes, + me->alloc, + me->allocBig); + + if (res == SZ_OK) + me->EncBlocks[outBufIndex] = blockSizes; + + return res; + } +} + + +static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex) +{ + CXzEnc *me = (CXzEnc *)pp; + + const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; + const Byte *data = me->outBufs[outBufIndex]; + + RINOK(WriteBytes(me->outStream, data, bInfo->headerSize)); + + { + UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize); + RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize)); + } + + return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc); +} + +#endif + + + +SRes XzEnc_Encode(CXzEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress) +{ + CXzEnc *p = (CXzEnc *)pp; + + const CXzProps *props = &p->xzProps; + + XzEncIndex_Init(&p->xzIndex); + { + UInt64 numBlocks = 1; + UInt64 blockSize = props->blockSize; + + if (blockSize != XZ_PROPS__BLOCK_SIZE__SOLID + && props->reduceSize != (UInt64)(Int64)-1) + { + numBlocks = props->reduceSize / blockSize; + if (numBlocks * blockSize != props->reduceSize) + numBlocks++; + } + else + blockSize = (UInt64)1 << 62; + + RINOK(XzEncIndex_PreAlloc(&p->xzIndex, numBlocks, blockSize, XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(blockSize), p->alloc)); + } + + RINOK(Xz_WriteHeader((CXzStreamFlags)props->checkId, outStream)); + + + #ifndef _7ZIP_ST + if (props->numBlockThreads_Reduced > 1) + { + IMtCoderCallback2 vt; + + if (!p->mtCoder_WasConstructed) + { + p->mtCoder_WasConstructed = True; + MtCoder_Construct(&p->mtCoder); + } + + vt.Code = XzEnc_MtCallback_Code; + vt.Write = XzEnc_MtCallback_Write; + + p->checkType = props->checkId; + p->xzProps = *props; + + p->outStream = outStream; + + p->mtCoder.allocBig = p->allocBig; + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.inData = NULL; + p->mtCoder.inDataSize = 0; + p->mtCoder.mtCallback = &vt; + p->mtCoder.mtCallbackObject = p; + + if ( props->blockSize == XZ_PROPS__BLOCK_SIZE__SOLID + || props->blockSize == XZ_PROPS__BLOCK_SIZE__AUTO) + return SZ_ERROR_FAIL; + + p->mtCoder.blockSize = (size_t)props->blockSize; + if (p->mtCoder.blockSize != props->blockSize) + return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ + + { + size_t destBlockSize = XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(p->mtCoder.blockSize); + if (destBlockSize < p->mtCoder.blockSize) + return SZ_ERROR_PARAM; + if (p->outBufSize != destBlockSize) + XzEnc_FreeOutBufs(p); + p->outBufSize = destBlockSize; + } + + p->mtCoder.numThreadsMax = props->numBlockThreads_Max; + p->mtCoder.expectedDataSize = p->expectedDataSize; + + RINOK(MtCoder_Code(&p->mtCoder)); + } + else + #endif + { + int writeStartSizes; + CCompressProgress_XzEncOffset progress2; + Byte *bufData = NULL; + size_t bufSize = 0; + + progress2.vt.Progress = CompressProgress_XzEncOffset_Progress; + progress2.inOffset = 0; + progress2.outOffset = 0; + progress2.progress = progress; + + writeStartSizes = 0; + + if (props->blockSize != XZ_PROPS__BLOCK_SIZE__SOLID) + { + writeStartSizes = (props->forceWriteSizesInHeader > 0); + + if (writeStartSizes) + { + size_t t2; + size_t t = (size_t)props->blockSize; + if (t != props->blockSize) + return SZ_ERROR_PARAM; + t = XZ_GET_MAX_BLOCK_PACK_SIZE(t); + if (t < props->blockSize) + return SZ_ERROR_PARAM; + t2 = XZ_BLOCK_HEADER_SIZE_MAX + t; + if (!p->outBufs[0] || t2 != p->outBufSize) + { + XzEnc_FreeOutBufs(p); + p->outBufs[0] = (Byte *)ISzAlloc_Alloc(p->alloc, t2); + if (!p->outBufs[0]) + return SZ_ERROR_MEM; + p->outBufSize = t2; + } + bufData = p->outBufs[0] + XZ_BLOCK_HEADER_SIZE_MAX; + bufSize = t; + } + } + + for (;;) + { + CXzEncBlockInfo blockSizes; + int inStreamFinished; + + /* + UInt64 rem = (UInt64)(Int64)-1; + if (props->reduceSize != (UInt64)(Int64)-1 + && props->reduceSize >= progress2.inOffset) + rem = props->reduceSize - progress2.inOffset; + */ + + blockSizes.headerSize = 0; // for GCC + + RINOK(Xz_CompressBlock( + &p->lzmaf_Items[0], + + writeStartSizes ? NULL : outStream, + writeStartSizes ? p->outBufs[0] : NULL, + bufData, bufSize, + + inStream, + // rem, + NULL, 0, + + props, + progress ? &progress2.vt : NULL, + &inStreamFinished, + &blockSizes, + p->alloc, + p->allocBig)); + + { + UInt64 totalPackFull = blockSizes.totalSize + XZ_GET_PAD_SIZE(blockSizes.totalSize); + + if (writeStartSizes) + { + RINOK(WriteBytes(outStream, p->outBufs[0], blockSizes.headerSize)); + RINOK(WriteBytes(outStream, bufData, (size_t)totalPackFull - blockSizes.headerSize)); + } + + RINOK(XzEncIndex_AddIndexRecord(&p->xzIndex, blockSizes.unpackSize, blockSizes.totalSize, p->alloc)); + + progress2.inOffset += blockSizes.unpackSize; + progress2.outOffset += totalPackFull; + } + + if (inStreamFinished) + break; + } + } + + return XzEncIndex_WriteFooter(&p->xzIndex, (CXzStreamFlags)props->checkId, outStream); +} + + +#include "Alloc.h" + +SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress) +{ + SRes res; + CXzEncHandle xz = XzEnc_Create(&g_Alloc, &g_BigAlloc); + if (!xz) + return SZ_ERROR_MEM; + res = XzEnc_SetProps(xz, props); + if (res == SZ_OK) + res = XzEnc_Encode(xz, outStream, inStream, progress); + XzEnc_Destroy(xz); + return res; +} + + +SRes Xz_EncodeEmpty(ISeqOutStream *outStream) +{ + SRes res; + CXzEncIndex xzIndex; + XzEncIndex_Construct(&xzIndex); + res = Xz_WriteHeader((CXzStreamFlags)0, outStream); + if (res == SZ_OK) + res = XzEncIndex_WriteFooter(&xzIndex, (CXzStreamFlags)0, outStream); + XzEncIndex_Free(&xzIndex, NULL); // g_Alloc + return res; +} diff --git a/other-licenses/7zstub/src/C/XzEnc.h b/other-licenses/7zstub/src/C/XzEnc.h new file mode 100644 index 0000000000..529ac3fd8c --- /dev/null +++ b/other-licenses/7zstub/src/C/XzEnc.h @@ -0,0 +1,60 @@ +/* XzEnc.h -- Xz Encode +2017-06-27 : Igor Pavlov : Public domain */ + +#ifndef __XZ_ENC_H +#define __XZ_ENC_H + +#include "Lzma2Enc.h" + +#include "Xz.h" + +EXTERN_C_BEGIN + + +#define XZ_PROPS__BLOCK_SIZE__AUTO LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO +#define XZ_PROPS__BLOCK_SIZE__SOLID LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + + +typedef struct +{ + UInt32 id; + UInt32 delta; + UInt32 ip; + int ipDefined; +} CXzFilterProps; + +void XzFilterProps_Init(CXzFilterProps *p); + + +typedef struct +{ + CLzma2EncProps lzma2Props; + CXzFilterProps filterProps; + unsigned checkId; + UInt64 blockSize; + int numBlockThreads_Reduced; + int numBlockThreads_Max; + int numTotalThreads; + int forceWriteSizesInHeader; + UInt64 reduceSize; +} CXzProps; + +void XzProps_Init(CXzProps *p); + + +typedef void * CXzEncHandle; + +CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig); +void XzEnc_Destroy(CXzEncHandle p); +SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props); +void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize); +SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress); + +SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress); + +SRes Xz_EncodeEmpty(ISeqOutStream *outStream); + +EXTERN_C_END + +#endif diff --git a/other-licenses/7zstub/src/C/XzIn.c b/other-licenses/7zstub/src/C/XzIn.c new file mode 100644 index 0000000000..42da1dece6 --- /dev/null +++ b/other-licenses/7zstub/src/C/XzIn.c @@ -0,0 +1,319 @@ +/* XzIn.c - Xz input +2018-02-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" + +/* +#define XZ_FOOTER_SIG_CHECK(p) (memcmp((p), XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0) +*/ +#define XZ_FOOTER_SIG_CHECK(p) ((p)[0] == XZ_FOOTER_SIG_0 && (p)[1] == XZ_FOOTER_SIG_1) + + +SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream) +{ + Byte sig[XZ_STREAM_HEADER_SIZE]; + RINOK(SeqInStream_Read2(inStream, sig, XZ_STREAM_HEADER_SIZE, SZ_ERROR_NO_ARCHIVE)); + if (memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0) + return SZ_ERROR_NO_ARCHIVE; + return Xz_ParseHeader(p, sig); +} + +#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ + { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ + if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } + +SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + unsigned headerSize; + *headerSizeRes = 0; + RINOK(SeqInStream_ReadByte(inStream, &header[0])); + headerSize = (unsigned)header[0]; + if (headerSize == 0) + { + *headerSizeRes = 1; + *isIndex = True; + return SZ_OK; + } + + *isIndex = False; + headerSize = (headerSize << 2) + 4; + *headerSizeRes = headerSize; + RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1)); + return XzBlock_Parse(p, header); +} + +#define ADD_SIZE_CHECK(size, val) \ + { UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } + +UInt64 Xz_GetUnpackSize(const CXzStream *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->numBlocks; i++) + ADD_SIZE_CHECK(size, p->blocks[i].unpackSize); + return size; +} + +UInt64 Xz_GetPackSize(const CXzStream *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->numBlocks; i++) + ADD_SIZE_CHECK(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3); + return size; +} + +/* +SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream) +{ + return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f)); +} +*/ + +static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc) +{ + size_t numBlocks, pos = 1; + UInt32 crc; + + if (size < 5 || buf[0] != 0) + return SZ_ERROR_ARCHIVE; + + size -= 4; + crc = CrcCalc(buf, size); + if (crc != GetUi32(buf + size)) + return SZ_ERROR_ARCHIVE; + + { + UInt64 numBlocks64; + READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64); + numBlocks = (size_t)numBlocks64; + if (numBlocks != numBlocks64 || numBlocks * 2 > size) + return SZ_ERROR_ARCHIVE; + } + + Xz_Free(p, alloc); + if (numBlocks != 0) + { + size_t i; + p->numBlocks = numBlocks; + p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); + if (!p->blocks) + return SZ_ERROR_MEM; + for (i = 0; i < numBlocks; i++) + { + CXzBlockSizes *block = &p->blocks[i]; + READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize); + READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize); + if (block->totalSize == 0) + return SZ_ERROR_ARCHIVE; + } + } + while ((pos & 3) != 0) + if (buf[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAllocPtr alloc) +{ + SRes res; + size_t size; + Byte *buf; + if (indexSize > ((UInt32)1 << 31)) + return SZ_ERROR_UNSUPPORTED; + size = (size_t)indexSize; + if (size != indexSize) + return SZ_ERROR_UNSUPPORTED; + buf = (Byte *)ISzAlloc_Alloc(alloc, size); + if (!buf) + return SZ_ERROR_MEM; + res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); + if (res == SZ_OK) + res = Xz_ReadIndex2(p, buf, size, alloc); + ISzAlloc_Free(alloc, buf); + return res; +} + +static SRes LookInStream_SeekRead_ForArc(ILookInStream *stream, UInt64 offset, void *buf, size_t size) +{ + RINOK(LookInStream_SeekTo(stream, offset)); + return LookInStream_Read(stream, buf, size); + /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */ +} + +static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAllocPtr alloc) +{ + UInt64 indexSize; + Byte buf[XZ_STREAM_FOOTER_SIZE]; + UInt64 pos = *startOffset; + + if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + + pos -= XZ_STREAM_FOOTER_SIZE; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)); + + if (!XZ_FOOTER_SIG_CHECK(buf + 10)) + { + UInt32 total = 0; + pos += XZ_STREAM_FOOTER_SIZE; + + for (;;) + { + size_t i; + #define TEMP_BUF_SIZE (1 << 10) + Byte temp[TEMP_BUF_SIZE]; + + i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos; + pos -= i; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i)); + total += (UInt32)i; + for (; i != 0; i--) + if (temp[i - 1] != 0) + break; + if (i != 0) + { + if ((i & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + pos += i; + break; + } + if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) + return SZ_ERROR_NO_ARCHIVE; + } + + if (pos < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + pos -= XZ_STREAM_FOOTER_SIZE; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)); + if (!XZ_FOOTER_SIG_CHECK(buf + 10)) + return SZ_ERROR_NO_ARCHIVE; + } + + p->flags = (CXzStreamFlags)GetBe16(buf + 8); + + if (!XzFlags_IsSupported(p->flags)) + return SZ_ERROR_UNSUPPORTED; + + if (GetUi32(buf) != CrcCalc(buf + 4, 6)) + return SZ_ERROR_ARCHIVE; + + indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; + + if (pos < indexSize) + return SZ_ERROR_ARCHIVE; + + pos -= indexSize; + RINOK(LookInStream_SeekTo(stream, pos)); + RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)); + + { + UInt64 totalSize = Xz_GetPackSize(p); + if (totalSize == XZ_SIZE_OVERFLOW + || totalSize >= ((UInt64)1 << 63) + || pos < totalSize + XZ_STREAM_HEADER_SIZE) + return SZ_ERROR_ARCHIVE; + pos -= (totalSize + XZ_STREAM_HEADER_SIZE); + RINOK(LookInStream_SeekTo(stream, pos)); + *startOffset = pos; + } + { + CXzStreamFlags headerFlags; + CSecToRead secToRead; + SecToRead_CreateVTable(&secToRead); + secToRead.realStream = stream; + + RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt)); + return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; + } +} + + +/* ---------- Xz Streams ---------- */ + +void Xzs_Construct(CXzs *p) +{ + p->num = p->numAllocated = 0; + p->streams = 0; +} + +void Xzs_Free(CXzs *p, ISzAllocPtr alloc) +{ + size_t i; + for (i = 0; i < p->num; i++) + Xz_Free(&p->streams[i], alloc); + ISzAlloc_Free(alloc, p->streams); + p->num = p->numAllocated = 0; + p->streams = 0; +} + +UInt64 Xzs_GetNumBlocks(const CXzs *p) +{ + UInt64 num = 0; + size_t i; + for (i = 0; i < p->num; i++) + num += p->streams[i].numBlocks; + return num; +} + +UInt64 Xzs_GetUnpackSize(const CXzs *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->num; i++) + ADD_SIZE_CHECK(size, Xz_GetUnpackSize(&p->streams[i])); + return size; +} + +/* +UInt64 Xzs_GetPackSize(const CXzs *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->num; i++) + ADD_SIZE_CHECK(size, Xz_GetTotalSize(&p->streams[i])); + return size; +} +*/ + +SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAllocPtr alloc) +{ + Int64 endOffset = 0; + RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END)); + *startOffset = endOffset; + for (;;) + { + CXzStream st; + SRes res; + Xz_Construct(&st); + res = Xz_ReadBackward(&st, stream, startOffset, alloc); + st.startOffset = *startOffset; + RINOK(res); + if (p->num == p->numAllocated) + { + size_t newNum = p->num + p->num / 4 + 1; + Byte *data = (Byte *)ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream)); + if (!data) + return SZ_ERROR_MEM; + p->numAllocated = newNum; + if (p->num != 0) + memcpy(data, p->streams, p->num * sizeof(CXzStream)); + ISzAlloc_Free(alloc, p->streams); + p->streams = (CXzStream *)data; + } + p->streams[p->num++] = st; + if (*startOffset == 0) + break; + RINOK(LookInStream_SeekTo(stream, *startOffset)); + if (progress && ICompressProgress_Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK) + return SZ_ERROR_PROGRESS; + } + return SZ_OK; +} 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 Methods; + CRecordVector 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 _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 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 _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 _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 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 setCoderMt; + decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt); + if (setCoderMt) + { + mt_wasUsed = true; + RINOK(setCoderMt->SetNumberOfThreads(numThreads)); + } + } + // if (memUsage != 0) + { + CMyComPtr setMemLimit; + decoder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit); + if (setMemLimit) + { + mt_wasUsed = true; + RINOK(setMemLimit->SetMemLimit(memUsage)); + } + } + } + #endif + + { + CMyComPtr 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 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 setFinishMode; + decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); + if (setFinishMode) + { + finishMode = fullUnpack; + RINOK(setFinishMode->SetFinishMode(BoolToInt(finishMode))); + } + } + + UInt32 numStreams = (UInt32)coderInfo.NumStreams; + + CObjArray packSizes(numStreams); + CObjArray 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 > inStreams; + + CLockedInStream *lockedInStreamSpec = new CLockedInStream; + CMyComPtr 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 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 inStreamPointers(num); + for (i = 0; i < num; i++) + inStreamPointers[i] = inStreams[i]; + + if (outStream) + { + CMyComPtr 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 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 _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 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 encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2; + + #ifndef _7ZIP_ST + { + CMyComPtr setCoderMt; + encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); + } + } + #endif + + RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon)); + + /* + CMyComPtr 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 setCompressCodecsInfo; + encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + // we must use g_ExternalCodecs also + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); + } + #endif + */ + + CMyComPtr 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 _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 &coderUnpackSizes, + UInt64 &unpackSize, + ISequentialOutStream *outStream, + CRecordVector &packSizes, + ICompressProgressInfo *compressProgress) +{ + RINOK(EncoderConstr()); + + if (!_mixerRef) + { + RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); + } + + _mixer->ReInit(); + + CMtEncMultiProgress *mtProgressSpec = NULL; + CMyComPtr mtProgress; + + CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL; + CMyComPtr mtOutStreamNotify; + + CObjectVector inOutTempBuffers; + CObjectVector tempBufferSpecs; + CObjectVector > 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 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 inStreamSizeCount = inStreamSizeCountSpec; + + CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; + CMyComPtr outStreamSizeCount; + + inStreamSizeCountSpec->Init(inStream); + + ISequentialInStream *inStreamPointer = inStreamSizeCount; + CRecordVector outStreamPointers; + + SetFolder(folderItem); + + for (i = 0; i < numMethods; i++) + { + IUnknown *coder = _mixer->GetCoder(i).GetUnknown(); + + CMyComPtr resetInitVector; + coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); + if (resetInitVector) + { + resetInitVector->ResetInitVector(); + } + + { + CMyComPtr 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 writeCoderProperties; + coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); + + CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props; + + if (writeCoderProperties) + { + CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; + CMyComPtr 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 _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 _mixerRef; + + CCompressionMethodMode _options; + NCoderMixer2::CBindInfo _bindInfo; + CRecordVector _decompressionMethods; + + CRecordVector _SrcIn_to_DestOut; + CRecordVector _SrcOut_to_DestIn; + // CRecordVector _DestIn_to_SrcOut; + CRecordVector _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 &coderUnpackSizes, + UInt64 &unpackSize, + ISequentialOutStream *outStream, + CRecordVector &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 _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 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 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 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 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 callbackMessage; + extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage); + + CFolderOutStream *folderOutStream = new CFolderOutStream; + CMyComPtr 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 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 stream; + HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + } + + _stream = stream; + + if (stream) + { + CMyComPtr 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 _stream; + UInt64 _pos; + UInt32 _crc; + bool _size_Defined; + UInt64 _size; + + const UInt32 *_indexes; + unsigned _numFiles; + unsigned _index; + + CMyComPtr _updateCallback; + + HRESULT OpenStream(); + void AddFileInfo(bool isProcessed); + +public: + CRecordVector Processed; + CRecordVector CRCs; + CRecordVector 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 openArchiveCallbackTemp = openArchiveCallback; + + #ifndef _NO_CRYPTO + CMyComPtr 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 _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 _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 _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 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 &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 &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 &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 getRawProps; + updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps); + + CUniqBlocks secureBlocks; + secureBlocks.AddUniq(NULL, 0); + + CObjectVector treeFolders; + { + CTreeFolder folder; + folder.Parent = -1; + treeFolders.Add(folder); + } + */ + + CObjectVector 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 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 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 +#else +#include +#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 *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 *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 *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 &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 *dataVector, + UInt64 &dataOffset, + CFolders &folders, + CRecordVector &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 &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 &dataVector + _7Z_DECODER_CRYPRO_VARS_DECL + ) +{ + CFolders folders; + CRecordVector 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 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 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 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 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 IDs; + + CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} +}; + +struct CFolderEx: public CFolder +{ + unsigned UnpackCoder; +}; + +struct CFolders +{ + CNum NumPackStreams; + CNum NumFolders; + + CObjArray PackPositions; // NumPackStreams + 1 + // CUInt32DefVector PackCRCs; // we don't use PackCRCs now + + CUInt32DefVector FolderCRCs; // NumFolders + CObjArray NumUnpackStreamsVector; // NumFolders + + CObjArray CoderUnpackSizes; // including unpack sizes of bond coders + CObjArray FoToCoderUnpackSizes; // NumFolders + 1 + CObjArray FoStartPackStreamIndex; // NumFolders + 1 + CObjArray FoToMainUnpackSizeIndex; // NumFolders + + CObjArray 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 Files; + + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CUInt32DefVector Attrib; + CBoolVector IsAnti; + /* + CBoolVector IsAux; + CByteBuffer SecureBuf; + CRecordVector SecureIDs; + */ + + CByteBuffer NamesBuf; + CObjArray 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 FileInfoPopIDs; + + void Clear() + { + StartPosition = 0; + StartPositionAfterHeader = 0; + DataStartPosition = 0; + DataStartPosition2 = 0; + FileInfoPopIDs.Clear(); + } +}; + +struct CDbEx: public CDatabase +{ + CInArchiveInfo ArcInfo; + + CObjArray FolderStartFileIndex; + CObjArray FileIndexToFolderIndexMap; + + UInt64 HeadersSize; + UInt64 PhySize; + + /* + CRecordVector 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 _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 *dataVector, + CFolders &folders); + + void ReadSubStreamsInfo( + CFolders &folders, + CRecordVector &unpackSizes, + CUInt32DefVector &digests); + + void ReadStreamsInfo( + const CObjectVector *dataVector, + UInt64 &dataOffset, + CFolders &folders, + CRecordVector &unpackSizes, + CUInt32DefVector &digests); + + void ReadBoolVector(unsigned numItems, CBoolVector &v); + void ReadBoolVector2(unsigned numItems, CBoolVector &v); + void ReadUInt64DefVector(const CObjectVector &dataVector, + CUInt64DefVector &v, unsigned numItems); + HRESULT ReadAndDecodePackedStreams( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 baseOffset, UInt64 &dataOffset, + CObjectVector &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 Coders; + CObjArray2 Bonds; + CObjArray2 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 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 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 &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 &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 &folders, + const COutFolders &outFolders, + const CRecordVector &unpackSizes, + const CUInt32DefVector &digests) +{ + const CRecordVector &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 &packSizes, CObjectVector &folders, COutFolders &outFolders) +{ + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr 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 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 packSizes; + CObjectVector 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 NumUnpackStreamsVector; + CRecordVector 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 PackSizes; + CUInt32DefVector PackCRCs; + CObjectVector Folders; + + CRecordVector Files; + UStringVector Names; + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CUInt32DefVector Attrib; + CBoolVector IsAnti; + + /* + CBoolVector IsAux; + + CByteBuffer SecureBuf; + CRecordVector SecureSizes; + CRecordVector 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 &packSizes, + const CUInt32DefVector &packCRCs); + + void WriteUnpackInfo( + const CObjectVector &folders, + const COutFolders &outFolders); + + void WriteSubStreamsInfo( + const CObjectVector &folders, + const COutFolders &outFolders, + const CRecordVector &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 &packSizes, CObjectVector &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 Stream; +public: + + COutArchive() { _outByte.Create(1 << 16); } + CMyComPtr 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 &src, + CRecordVector &dest, UInt32 item) +{ + FOR_VECTOR (i, src) + if (src[i] == item) + { + dest.Add(item); + src.Delete(i); + return; + } +} + +static void RemoveOneItem(CRecordVector &src, UInt32 item) +{ + FOR_VECTOR (i, src) + if (src[i] == item) + { + src.Delete(i); + return; + } +} + +static void InsertToHead(CRecordVector &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 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 _stream; + CMyComPtr _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 &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 &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 inStreamLimited(streamSpec); + streamSpec->SetStream(inStream); + streamSpec->Init(size); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr 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 &updateItems = *(const CObjectVector *)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 *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 Indices; + + CRecordVector 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 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 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 _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 _opCallback; + CMyComPtr _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 _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 _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 InStream; + + CFolderOutStream2 *FosSpec; + CMyComPtr Fos; + + UInt64 StartPos; + const CFolders *Folders; + int FolderIndex; + + // bool send_UnpackSize; + // UInt64 UnpackSize; + + #ifndef _NO_CRYPTO + CMyComPtr 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 &updateItems, + // const CObjectVector &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 opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + + CMyComPtr extractCallback; + updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback); + + // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); + + /* + CMyComPtr 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 filters; + CObjectVector 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 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 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 sbInStream; + CRepackStreamBase *repackBase; + CFolderInStream2 *FosSpec2 = NULL; + + CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes; + CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; + { + #ifndef _7ZIP_ST + if (options.MultiThreadMixer) + { + repackBase = threadDecoder.FosSpec; + CMyComPtr 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 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 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 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 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 &updateItems, + // const CObjectVector &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 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 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 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 s; + unk->QueryInterface(IID_ISequentialInStream, (void**)&s); + c2.CanRead = (s != NULL); + } + { + CMyComPtr 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 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 setStream; + coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream); + if (setStream) + { + CMyComPtr seqInStream2; + RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2)); + RINOK(setStream->SetInStream(seqInStream2)); + isSet = true; + } + } + + if (!isSet && numInStreams != 0) + { + CMyComPtr setStream2; + coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2); + if (!setStream2) + return E_NOTIMPL; + + for (UInt32 i = 0; i < numInStreams; i++) + { + CMyComPtr 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 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 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 setOutStream; + coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (setOutStream) + { + CMyComPtr seqOutStream2; + RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2)); + RINOK(setOutStream->SetOutStream(seqOutStream2)); + isSet = true; + } + } + + if (!isSet && numOutStreams != 0) + { + return E_NOTIMPL; + /* + CMyComPtr setStream2; + coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2); + if (!setStream2) + return E_NOTIMPL; + for (UInt32 i = 0; i < numOutStreams; i++) + { + CMyComPtr 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 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 > seqInStreams; + CObjectVector< CMyComPtr > 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 seqInStream; + RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream)); + seqInStreams.Add(seqInStream); + } + + for (i = 0; i < numOutStreams; i++) + { + CMyComPtr 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 initEncoder; + coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder); + if (initEncoder) + RINOK(initEncoder->InitEncoder()); + } + else + { + CMyComPtr 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 seqInStream; + + RINOK(GetInStream2(inStreams, /* inSizes, */ + _bi.UnpackCoder, &seqInStream)) + + FOR_VECTOR (i, _coders) + { + CCoder &coder = _coders[i]; + CMyComPtr 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 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 _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 _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 Coders; + CRecordVector Bonds; + CRecordVector 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 Coder_to_Stream; + CRecordVector 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 Coder; + CMyComPtr Coder2; + UInt32 NumStreams; + + UInt64 UnpackSize; + const UInt64 *UnpackSizePointer; + + CRecordVector PackSizes; + CRecordVector 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 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 _coders; + + CObjectVector _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 InStreamPointers; + CRecordVector OutStreamPointers; + +private: + void Execute(); +public: + bool EncodeMode; + HRESULT Result; + CObjectVector< CMyComPtr > InStreams; + CObjectVector< CMyComPtr > 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 _streamBinders; + + HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); + HRESULT ReturnIfError(HRESULT code); + +public: + CObjectVector _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 _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 _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 _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 _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 _volumeStream; + COutArchive _archive; + CCRC _crc; + +public: + MY_UNKNOWN_IMP + + CFileItem _file; + CUpdateOptions _options; + CMyComPtr 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 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 Stream; + UInt64 Size; + UInt64 GlobalOffset; + UInt64 LocalPos; + + CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {} + }; + + CObjectVector 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 Stream; + UInt64 Size; + UInt64 Pos; + }; + CObjectVector Streams; +public: + CMyComPtr 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 _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 Binary files /dev/null and b/other-licenses/7zstub/src/CPP/7zip/Archive/Icons/7z.ico 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 _bcjStream; + CFilterCoder *_filterCoder; + CMyComPtr _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 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 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 _stream; + CMyComPtr _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 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 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 outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr 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 > _streams; + CRecordVector _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 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 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 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 copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr 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 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 _stream; + CMyComPtr _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 _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 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(¤tTotalPacked)); + CMyComPtr 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 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 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 fileInStream; + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress); + } + + if (indexInArchive != 0) + return E_INVALIDARG; + + CMyComPtr 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 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 + +#include "../../../../C/CpuArch.h" + +#if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE) +#include +#include +#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 [inputFile] [outputFile] [...]\n" + "\n" + "\n" + " e : Encode file\n" + " d : Decode file\n" + " b : Benchmark\n" + "\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 &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 ¶ms = parser.NonSwitchStrings; + + unsigned paramIndex = 0; + if (paramIndex >= params.Size()) + IncorrectCommand(); + const UString &command = params[paramIndex++]; + + CObjectVector 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 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 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 progress; + + if (!stdOutMode) + { + progressSpec = new CProgressPrint; + progress = progressSpec; + } + + if (encodeMode) + { + NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; + CMyComPtr 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((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 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 + +#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 +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 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 Binary files /dev/null and b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXCon/7z.ico 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 <@|!>ame must be +static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!>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 [] [...] [...]\n" + "\n" + "\n" + // " l: List contents of archive\n" + " t: Test integrity of archive\n" + " x: eXtract files with full pathname (default)\n" + "\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 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(), 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(), 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 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 _archiveHandler; + FString _directoryPath; + UString _filePath; + FString _diskFilePath; + + bool _extractMode; + struct CProcessedFileInfo + { + FILETIME MTime; + bool IsDir; + UInt32 Attributes; + } _processedFileInfo; + + COutFileStream *_outFileStreamSpec; + CMyComPtr _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 ExtractCallback; + + CArchiveLink ArchiveLink; + HRESULT Result; + UString ErrorMessage; + + void Process2() + { + NFind::CFileInfo fi; + if (!fi.Find(FileName)) + { + ErrorMessage = kCantFindArchive; + Result = E_FAIL; + return; + } + + CObjectVector incl; + CIntVector excl; + COpenOptions options; + options.codecs = Codecs; + options.types = &incl; + options.excludedFormats = ! + 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 `ConvertToString` 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 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 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 + +// #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 Binary files /dev/null and b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXSetup/setup.ico 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 Binary files /dev/null and b/other-licenses/7zstub/src/CPP/7zip/Bundles/SFXWin/7z.ico 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 + +#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 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 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(), 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 +#include + +// #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 &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 &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 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 &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 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 &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 &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 &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 GetCodecs; + CMyComPtr GetHashers; + + CObjectVector Codecs; + CObjectVector 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 &methods); + + +struct CCreatedCoder +{ + CMyComPtr Coder; + CMyComPtr 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 &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 &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 &coder); + +HRESULT CreateFilter( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr &filter); + +HRESULT CreateHasher( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name, + CMyComPtr &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 +#include +#include +#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 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 _inStream; + CMyComPtr _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 _SetPassword; + CMyComPtr _CryptoProperties; + #endif + + #ifndef EXTRACT_ONLY + CMyComPtr _SetCoderProperties; + CMyComPtr _WriteCoderProperties; + // CMyComPtr _CryptoResetSalt; + CMyComPtr _CryptoResetInitVector; + #endif + + CMyComPtr _SetDecoderProperties2; + +public: + CMyComPtr 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 + +#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 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 _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 _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 Stream; + CRecordVector 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 Stream; + CRecordVector 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 _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 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 _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 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 ¶m, 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 ¶m = 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 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 _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 _progress; + CMyComPtr _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 inStreamLoc(inStreamSpec); + *inStream = inStreamLoc.Detach(); + + CBinderOutStream *outStreamSpec = new CBinderOutStream(this); + CMyComPtr 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 + +#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 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 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 _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 _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 + +#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 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 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(¤tInPos, &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 _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 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 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 _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 + +#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 _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 _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 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 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 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 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 _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 +#define USE_POSIX_TIME +#define USE_POSIX_TIME2 +#endif + +#ifdef USE_POSIX_TIME +#include +#ifdef USE_POSIX_TIME2 +#include +#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 + +// #include +// #include + +// for Windows CE: +#include + + +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 + +#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 _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 _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 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 VolumesSizes; + UString VolName; + UString VolExt; + + FString DirPrefix; + const CObjectVector *DirItems; + + bool PasswordIsDefined; + UString Password; + bool AskPassword; + + bool m_NeedBeClosed; + + FStringVector FailedFiles; + CRecordVector FailedCodes; + + CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; + + ~CArchiveUpdateCallback() { Finilize(); } + HRESULT Finilize(); + + void Init(const CObjectVector *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 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 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 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 outFileStream = outFileStreamSpec; + if (!outFileStreamSpec->Create(archiveName, false)) + { + PrintError("can't create archive file"); + return 1; + } + + CMyComPtr outArchive; + if (createObjectFunc(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK) + { + PrintError("Can not get class object"); + return 1; + } + + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr 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 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 archive; + if (createObjectFunc(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK) + { + PrintError("Can not get class object"); + return 1; + } + + CInFileStream *fileSpec = new CInFileStream; + CMyComPtr file = fileSpec; + + if (!fileSpec->Open(archiveName)) + { + PrintError("Can not open archive file", archiveName); + return 1; + } + + { + CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; + CMyComPtr 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 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 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 +#endif +#else +// for isatty() +#include +#endif + +#include + +#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 <@|!>ame must be +static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!>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 *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 *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 *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 &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 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 +// #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 *realIndices) +{ + _hardLinks.Clear(); + + if (!_arc->Ask_INode) + return S_OK; + + IInArchive *archive = _arc->Archive; + CRecordVector &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 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 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 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 _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 IDs; + CObjectVector 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 _extractCallback2; + CMyComPtr _compressProgress; + CMyComPtr _cryptoGetTextPassword; + CMyComPtr _callbackMessage; + CMyComPtr _folderArchiveExtractCallback2; + + FString _dirPathPrefix; + FString _dirPathPrefix_Full; + NExtract::NPathMode::EEnum _pathMode; + NExtract::NOverwriteMode::EEnum _overwriteMode; + bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_"; + + #ifndef _SFX + + CMyComPtr ExtractToStreamCallback; + CGetProp *GetProp_Spec; + CMyComPtr 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 _outFileStream; + + #ifndef _SFX + + COutStreamWithHash *_hashStreamSpec; + CMyComPtr _hashStream; + bool _hashStreamWasUsed; + + #endif + + bool _removePartsForAltStreams; + UStringVector _removePathParts; + + #ifndef _SFX + bool _use_baseParentFolder_mode; + UInt32 _baseParentFolder; + #endif + + bool _stdOutMode; + bool _testMode; + bool _multiArchives; + + CMyComPtr _localProgress; + UInt64 _packTotal; + + UInt64 _progressTotal; + bool _progressTotal_Defined; + + CObjectVector _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 *realIndices); // NULL means all items + + #endif + + + #ifdef SUPPORT_ALT_STREAMS + CObjectVector _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 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 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 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 FileSizes; + + bool PasswordWasAsked; + + IOpenCallbackUI *Callback; + CMyComPtr 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 + +#ifndef _WIN32 +#define USE_POSIX_TIME +#define USE_POSIX_TIME2 +#endif + +#ifdef USE_POSIX_TIME +#include +#ifdef USE_POSIX_TIME2 +#include +#endif +#endif + +#ifdef _WIN32 +#define USE_ALLOCA +#endif + +#ifdef USE_ALLOCA +#ifdef _WIN32 +#include +#else +#include +#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 _encoder; + CMyComPtr _encoderFilter; + CBenchProgressInfo *progressInfoSpec[2]; + CMyComPtr 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 _decoders[2]; + CMyComPtr _decoderFilter; + + HRESULT Results[2]; + CBenchmarkOutStream *outStreamSpec; + CMyComPtr 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 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 coder; + if (_encoderFilter) + coder = _encoderFilter; + else + coder = _encoder; + { + CMyComPtr scp; + coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + UInt64 reduceSize = kBufferSize; + RINOK(method.SetCoderProps(scp, &reduceSize)); + } + else + { + if (method.AreThereNonOptionalProps()) + return E_INVALIDARG; + } + + CMyComPtr writeCoderProps; + coder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps); + if (writeCoderProps) + { + RINOK(writeCoderProps->WriteCoderProperties(propStream)); + } + + { + CMyComPtr 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 inStream = inStreamSpec; + inStreamSpec->Init(temp, sizeof(temp)); + + CCrcOutStream *crcStreamSpec = new CCrcOutStream; + CMyComPtr 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 cp; + CMyComPtr coder; + if (_encoderFilter) + coder = _encoderFilter; + else + coder = _encoder; + coder.QueryInterface(IID_ICryptoProperties, &cp); + CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; + CMyComPtr 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 inStream = inStreamSpec; + CMyComPtr &decoder = _decoders[decoderIndex]; + CMyComPtr coder; + if (_decoderFilter) + { + if (decoderIndex != 0) + return E_FAIL; + coder = _decoderFilter; + } + else + coder = decoder; + + CMyComPtr setDecProps; + coder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps); + if (!setDecProps && propStreamSpec->Pos != 0) + return E_FAIL; + + CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; + CMyComPtr crcOutStream = crcOutStreamSpec; + + CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; + pi->BenchInfo.UnpackSize = 0; + pi->BenchInfo.PackSize = 0; + + #ifndef _7ZIP_ST + { + CMyComPtr setCoderMt; + coder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(NumDecoderSubThreads)); + } + } + #endif + + CMyComPtr scp; + coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + UInt64 reduceSize = _uncompressedDataSize; + RINOK(_method.SetCoderProps(scp, &reduceSize)); + } + + CMyComPtr cp; + coder.QueryInterface(IID_ICryptoProperties, &cp); + + if (setDecProps) + { + RINOK(setDecProps->SetDecoderProperties2(propStreamSpec->Buffer, (UInt32)propStreamSpec->Pos)); + } + + { + CMyComPtr 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 &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 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 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 hasher; + AString name; + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher)); + if (!hasher) + return E_NOTIMPL; + CMyComPtr 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 &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 &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 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 + +#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 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 &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 &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 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 &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 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 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 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 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 &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 ids; + CObjectVector 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 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 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 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 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 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 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 &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 Exts; + + #ifndef _SFX + Func_CreateOutArchive CreateOutArchive; + bool UpdateEnabled; + bool NewInterface; + // UInt32 Version; + UInt32 SignatureOffset; + CObjectVector 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 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 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 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 Formats; + + #ifdef EXTERNAL_CODECS + CRecordVector Codecs; + CRecordVector 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 &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 &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 __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 +#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 _items; + UInt64 _maxEndOffset; + CMyComPtr _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 progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; + CMyComPtr outStream(outStreamSpec); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr 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 &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 Callback; + CMyComPtr OpenVolumeCallback; + UInt64 Files; + UInt64 Offset; + + #ifndef _NO_CRYPTO + CMyComPtr 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 &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 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 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 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 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 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 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 handler = handlerSpec; + + CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback; + CMyComPtr 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 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 &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 limitedStream = limitedStreamSpec; + limitedStreamSpec->SetStream(op.stream); + + CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL; + CMyComPtr 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 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 fileStream; + CMyComPtr 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 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 getStream; + if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream) + break; + + CMyComPtr subSeqStream; + if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream) + break; + + CMyComPtr 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 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 = ! + 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 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 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 inc; + CIntVector excl; + + op.types = &inc; + op.excludedFormats = ! + op.stdInMode = false; + op.stream = NULL; + if (Arcs.Size() == 0) // ??? + return Open2(op, NULL); + + COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; + CMyComPtr 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 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 &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 Props; +}; +*/ + +#ifdef _SFX +#define OPEN_PROPS_DECL +#else +#define OPEN_PROPS_DECL const CObjectVector *props; +// #define OPEN_PROPS_DECL , const CObjectVector *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 *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 &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 Archive; + CMyComPtr InStream; + // we use InStream in 2 cases (ArcStreamOffset != 0): + // 1) if we use additional cache stream + // 2) we reopen sfx archive with CTailInStream + + CMyComPtr GetRawProps; + CMyComPtr 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 &stream); +}; + +struct CArchiveLink +{ + CObjectVector 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 &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 &properties) +{ + if (properties.IsEmpty()) + return S_OK; + CMyComPtr 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 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 &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 Stream; + FString Name; + UInt64 Pos; + UInt64 RealSize; + }; + CObjectVector Streams; +public: + // CMyComPtr VolumeCallback; + CRecordVector 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 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 &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 *_arcItems; + IUpdateCallbackUI *_callback; + CDirItemsStat *_stat; + + CUpdateProduceCallbackImp( + const CObjectVector *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 &arcItems, + Byte *processedItemsStatuses, + const CDirItems &dirItems, + const CDirItem *parentDirItem, + CTempFiles &tempFiles, + CUpdateErrorInfo &errorInfo, + IUpdateCallbackUI *callback, + CFinishArchiveStat &st) +{ + CMyComPtr outArchive; + int formatIndex = options.MethodMode.Type.FormatIndex; + + if (arc) + { + formatIndex = arc->FormatIndex; + if (formatIndex < 0) + return E_NOTIMPL; + CMyComPtr 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 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 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 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 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 outSeekStream; + CMyComPtr 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 sfxStream(sfxStreamSpec); + if (!sfxStreamSpec->Open(options.SfxModule)) + return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule); + + CMyComPtr 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 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 &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 + +#endif + +HRESULT UpdateArchive( + CCodecs *codecs, + const CObjectVector &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 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 = ! + 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 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 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 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 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 RenamePairs; + + bool InitFormatIndex(const CCodecs *codecs, const CObjectVector &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 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 &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 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 inStreamLoc(inStreamSpec); + *inStream = inStreamLoc.Detach(); + } + else + { + CInFileStream *inStreamSpec = new CInFileStream; + CMyComPtr 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 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 _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 _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 VolumesSizes; + FString VolName; + FString VolExt; + + IUpdateCallbackUI *Callback; + + const CDirItems *DirItems; + const CDirItem *ParentDirItem; + + const CArc *Arc; + CMyComPtr Archive; + const CObjectVector *ArcItems; + const CRecordVector *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 + +#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 &arcItems = *(const CObjectVector *)param; + int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]); + if (res != 0) + return res; + return MyCompare(i1, i2); +} + +void GetUpdatePairInfoList( + const CDirItems &dirItems, + const CObjectVector &arcItems, + NFileTimeType::EEnum fileTimeType, + CRecordVector &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 &arcItems, + NFileTimeType::EEnum fileTimeType, + CRecordVector &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 &updatePairs, + const CActionSet &actionSet, + CRecordVector &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 &updatePairs, + const NUpdateArchive::CActionSet &actionSet, + CRecordVector &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 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 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 &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 + +#include "../../Common/CreateCoder.h" +#include "../../UI/Common/Property.h" + +HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS + const CObjectVector &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 @@ + + + + + + + + + + + + + \ 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 &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 &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 &hashers); + void PrintResultLine(UInt64 fileSize, + const CObjectVector &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 _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 &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 *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 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 &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 *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 +#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 + " [...] [...]\n" + "\n" + "\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" + "\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 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 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 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 + +#ifndef UNDER_CE +#include "../../../Windows/CommonDialog.h" +#include "../../../Windows/Shell.h" +#endif + +#include "../../../Windows/FileName.h" +#include "../../../Windows/FileFind.h" + +#ifdef UNDER_CE +#include +#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 _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 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 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 _outFileStream; +public: + CObjectVector 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 _hashStream; + IHashCalc *_hashCalc; // it's for stat in Test operation + #endif + +public: + + #ifndef _SFX + CVirtFileSystem *VirtFileSystemSpec; + CMyComPtr 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 + +#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 + +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 _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 + +#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 &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 &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 + +#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 _attribMap; + CObjectVector _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 *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 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 &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 &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 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 diff --git a/other-licenses/7zstub/src/CPP/Build.mak b/other-licenses/7zstub/src/CPP/Build.mak new file mode 100644 index 0000000000..28d5eca27d --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Build.mak @@ -0,0 +1,145 @@ +LIBS = $(LIBS) oleaut32.lib ole32.lib + +!IFNDEF MY_NO_UNICODE +CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE +!ENDIF + +# CFLAGS = $(CFLAGS) -FAsc -Fa$O/Asm/ + +!IFNDEF O +!IFDEF CPU +O=$(CPU) +!ELSE +O=O +!ENDIF +!ENDIF + +!IF "$(CPU)" == "AMD64" +MY_ML = ml64 -Dx64 -WX +!ELSEIF "$(CPU)" == "ARM" +MY_ML = armasm -WX +!ELSE +MY_ML = ml -WX +!ENDIF + + +!IFDEF UNDER_CE +RFLAGS = $(RFLAGS) -dUNDER_CE +!IFDEF MY_CONSOLE +LFLAGS = $(LFLAGS) /ENTRY:mainACRTStartup +!ENDIF +!ELSE +!IFNDEF NEW_COMPILER +LFLAGS = $(LFLAGS) -OPT:NOWIN98 +!ENDIF +!IF "$(CPU)" != "ARM" && "$(CPU)" != "ARM64" +CFLAGS = $(CFLAGS) -Gr +!ENDIF +LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib +!ENDIF + +!IF "$(CPU)" == "ARM" +COMPL_ASM = $(MY_ML) $** $O/$(*B).obj +!ELSE +COMPL_ASM = $(MY_ML) -c -Fo$O/ $** +!ENDIF + +CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR- -GF + +!IFDEF MY_STATIC_LINK +!IFNDEF MY_SINGLE_THREAD +CFLAGS = $(CFLAGS) -MT +!ENDIF +!ELSE +CFLAGS = $(CFLAGS) -MD +!ENDIF + +!IFDEF NEW_COMPILER +CFLAGS = $(CFLAGS) -GS- -Zc:forScope -Zc:wchar_t +!IFNDEF UNDER_CE +CFLAGS = $(CFLAGS) -MP2 +!IFNDEF CPU +# CFLAGS = $(CFLAGS) -arch:IA32 +!ENDIF +!ENDIF +!ELSE +CFLAGS = $(CFLAGS) +!ENDIF + +!IF "$(CPU)" == "AMD64" +CFLAGS_O1 = $(CFLAGS) -O1 +!ELSE +CFLAGS_O1 = $(CFLAGS) -O1 +!ENDIF +CFLAGS_O2 = $(CFLAGS) -O2 + +LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF + +!IFNDEF UNDER_CE +LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE +!ENDIF + +!IFDEF DEF_FILE +LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) +!ELSE +!IF defined(MY_FIXED) && "$(CPU)" != "ARM" && "$(CPU)" != "ARM64" +LFLAGS = $(LFLAGS) /FIXED +!ELSE +LFLAGS = $(LFLAGS) /FIXED:NO +!ENDIF +# /BASE:0x400000 +!ENDIF + + +# !IF "$(CPU)" == "AMD64" + +!IFDEF SUB_SYS_VER + +MY_SUB_SYS_VER=5.02 + +!IFDEF MY_CONSOLE +LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER) +!ELSE +LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER) +!ENDIF + +!ENDIF + + +PROGPATH = $O\$(PROG) + +COMPL_O1 = $(CC) $(CFLAGS_O1) $** +COMPL_O2 = $(CC) $(CFLAGS_O2) $** +COMPL_PCH = $(CC) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** +COMPL = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** + +COMPLB = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $< +# COMPLB_O2 = $(CC) $(CFLAGS_O2) -Yu"StdAfx.h" -Fp$O/a.pch $< +COMPLB_O2 = $(CC) $(CFLAGS_O2) $< + +CFLAGS_C_ALL = $(CFLAGS_O2) $(CFLAGS_C_SPEC) +CCOMPL_PCH = $(CC) $(CFLAGS_C_ALL) -Yc"Precomp.h" -Fp$O/a.pch $** +CCOMPL_USE = $(CC) $(CFLAGS_C_ALL) -Yu"Precomp.h" -Fp$O/a.pch $** +CCOMPL = $(CC) $(CFLAGS_C_ALL) $** +CCOMPLB = $(CC) $(CFLAGS_C_ALL) $< + + +all: $(PROGPATH) + +clean: + -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O\*.asm + +$O: + if not exist "$O" mkdir "$O" +$O/Asm: + if not exist "$O/Asm" mkdir "$O/Asm" + +$(PROGPATH): $O $O/Asm $(OBJS) $(DEF_FILE) + link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) + +!IFNDEF NO_DEFAULT_RES +$O\resource.res: $(*B).rc + rc $(RFLAGS) -fo$@ $** +!ENDIF +$O\StdAfx.obj: $(*B).cpp + $(COMPL_PCH) diff --git a/other-licenses/7zstub/src/CPP/Common/AutoPtr.h b/other-licenses/7zstub/src/CPP/Common/AutoPtr.h new file mode 100644 index 0000000000..e53fb7f5d5 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/AutoPtr.h @@ -0,0 +1,35 @@ +// Common/AutoPtr.h + +#ifndef __COMMON_AUTOPTR_H +#define __COMMON_AUTOPTR_H + +template class CMyAutoPtr +{ + T *_p; +public: + CMyAutoPtr(T *p = 0) : _p(p) {} + CMyAutoPtr(CMyAutoPtr& p): _p(p.release()) {} + CMyAutoPtr& operator=(CMyAutoPtr& p) + { + reset(p.release()); + return (*this); + } + ~CMyAutoPtr() { delete _p; } + T& operator*() const { return *_p; } + // T* operator->() const { return (&**this); } + T* get() const { return _p; } + T* release() + { + T *tmp = _p; + _p = 0; + return tmp; + } + void reset(T* p = 0) + { + if (p != _p) + delete _p; + _p = p; + } +}; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/CRC.cpp b/other-licenses/7zstub/src/CPP/Common/CRC.cpp new file mode 100644 index 0000000000..6ac52c4c12 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/CRC.cpp @@ -0,0 +1,7 @@ +// Common/CRC.cpp + +#include "StdAfx.h" + +#include "../../C/7zCrc.h" + +struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; diff --git a/other-licenses/7zstub/src/CPP/Common/C_FileIO.cpp b/other-licenses/7zstub/src/CPP/Common/C_FileIO.cpp new file mode 100644 index 0000000000..d68a427793 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/C_FileIO.cpp @@ -0,0 +1,92 @@ +// Common/C_FileIO.cpp + +#include "C_FileIO.h" + +#include +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace NC { +namespace NFile { +namespace NIO { + +bool CFileBase::OpenBinary(const char *name, int flags) +{ + #ifdef O_BINARY + flags |= O_BINARY; + #endif + Close(); + _handle = ::open(name, flags, 0666); + return _handle != -1; +} + +bool CFileBase::Close() +{ + if (_handle == -1) + return true; + if (close(_handle) != 0) + return false; + _handle = -1; + return true; +} + +bool CFileBase::GetLength(UInt64 &length) const +{ + off_t curPos = Seek(0, SEEK_CUR); + off_t lengthTemp = Seek(0, SEEK_END); + Seek(curPos, SEEK_SET); + length = (UInt64)lengthTemp; + return true; +} + +off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const +{ + return ::lseek(_handle, distanceToMove, moveMethod); +} + +///////////////////////// +// CInFile + +bool CInFile::Open(const char *name) +{ + return CFileBase::OpenBinary(name, O_RDONLY); +} + +bool CInFile::OpenShared(const char *name, bool) +{ + return Open(name); +} + +ssize_t CInFile::Read(void *data, size_t size) +{ + return read(_handle, data, size); +} + +///////////////////////// +// COutFile + +bool COutFile::Create(const char *name, bool createAlways) +{ + if (createAlways) + { + Close(); + _handle = ::creat(name, 0666); + return _handle != -1; + } + return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); +} + +bool COutFile::Open(const char *name, DWORD creationDisposition) +{ + return Create(name, false); +} + +ssize_t COutFile::Write(const void *data, size_t size) +{ + return write(_handle, data, size); +} + +}}} diff --git a/other-licenses/7zstub/src/CPP/Common/C_FileIO.h b/other-licenses/7zstub/src/CPP/Common/C_FileIO.h new file mode 100644 index 0000000000..4c400b41f2 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/C_FileIO.h @@ -0,0 +1,53 @@ +// Common/C_FileIO.h + +#ifndef __COMMON_C_FILEIO_H +#define __COMMON_C_FILEIO_H + +#include +#include + +#include "MyTypes.h" +#include "MyWindows.h" + +#ifdef _WIN32 +#ifdef _MSC_VER +typedef size_t ssize_t; +#endif +#endif + +namespace NC { +namespace NFile { +namespace NIO { + +class CFileBase +{ +protected: + int _handle; + bool OpenBinary(const char *name, int flags); +public: + CFileBase(): _handle(-1) {}; + ~CFileBase() { Close(); } + bool Close(); + bool GetLength(UInt64 &length) const; + off_t Seek(off_t distanceToMove, int moveMethod) const; +}; + +class CInFile: public CFileBase +{ +public: + bool Open(const char *name); + bool OpenShared(const char *name, bool shareForWrite); + ssize_t Read(void *data, size_t size); +}; + +class COutFile: public CFileBase +{ +public: + bool Create(const char *name, bool createAlways); + bool Open(const char *name, DWORD creationDisposition); + ssize_t Write(const void *data, size_t size); +}; + +}}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/ComTry.h b/other-licenses/7zstub/src/CPP/Common/ComTry.h new file mode 100644 index 0000000000..e6b514d44e --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/ComTry.h @@ -0,0 +1,21 @@ +// ComTry.h + +#ifndef __COM_TRY_H +#define __COM_TRY_H + +#include "MyWindows.h" +// #include "Exception.h" +// #include "NewHandler.h" + +#define COM_TRY_BEGIN try { +#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } + +/* +#define COM_TRY_END } \ + catch(const CNewException &) { return E_OUTOFMEMORY; } \ + catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \ +*/ + // catch(const CSystemException &e) { return e.ErrorCode; } + // catch(...) { return E_FAIL; } + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/CommandLineParser.cpp b/other-licenses/7zstub/src/CPP/Common/CommandLineParser.cpp new file mode 100644 index 0000000000..94aabce6dd --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/CommandLineParser.cpp @@ -0,0 +1,197 @@ +// CommandLineParser.cpp + +#include "StdAfx.h" + +#include "CommandLineParser.h" + +namespace NCommandLineParser { + +bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) +{ + dest1.Empty(); + dest2.Empty(); + bool quoteMode = false; + unsigned i; + for (i = 0; i < src.Len(); i++) + { + wchar_t c = src[i]; + if ((c == L' ' || c == L'\t') && !quoteMode) + { + dest2 = src.Ptr(i + 1); + return i != 0; + } + if (c == L'\"') + quoteMode = !quoteMode; + else + dest1 += c; + } + return i != 0; +} + +void SplitCommandLine(const UString &s, UStringVector &parts) +{ + UString sTemp (s); + sTemp.Trim(); + parts.Clear(); + for (;;) + { + UString s1, s2; + if (SplitCommandLine(sTemp, s1, s2)) + parts.Add(s1); + if (s2.IsEmpty()) + break; + sTemp = s2; + } +} + + +static const char * const kStopSwitchParsing = "--"; + +static bool inline IsItSwitchChar(wchar_t c) +{ + return (c == '-'); +} + +CParser::CParser(): + _switches(NULL), + StopSwitchIndex(-1) +{ +} + +CParser::~CParser() +{ + delete []_switches; +} + + +// if (s) contains switch then function updates switch structures +// out: true, if (s) is a switch +bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches) +{ + if (s.IsEmpty() || !IsItSwitchChar(s[0])) + return false; + + unsigned pos = 1; + unsigned switchIndex = 0; + int maxLen = -1; + + for (unsigned i = 0; i < numSwitches; i++) + { + const char * const key = switchForms[i].Key; + unsigned switchLen = MyStringLen(key); + if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) + continue; + if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key)) + { + switchIndex = i; + maxLen = switchLen; + } + } + + if (maxLen < 0) + { + ErrorMessage = "Unknown switch:"; + return false; + } + + pos += maxLen; + + CSwitchResult &sw = _switches[switchIndex]; + const CSwitchForm &form = switchForms[switchIndex]; + + if (!form.Multi && sw.ThereIs) + { + ErrorMessage = "Multiple instances for switch:"; + return false; + } + + sw.ThereIs = true; + + int rem = s.Len() - pos; + if (rem < form.MinLen) + { + ErrorMessage = "Too short switch:"; + return false; + } + + sw.WithMinus = false; + sw.PostCharIndex = -1; + + switch (form.Type) + { + case NSwitchType::kMinus: + if (rem == 1) + { + sw.WithMinus = (s[pos] == '-'); + if (sw.WithMinus) + return true; + ErrorMessage = "Incorrect switch postfix:"; + return false; + } + break; + + case NSwitchType::kChar: + if (rem == 1) + { + wchar_t c = s[pos]; + if (c <= 0x7F) + { + sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); + if (sw.PostCharIndex >= 0) + return true; + } + ErrorMessage = "Incorrect switch postfix:"; + return false; + } + break; + + case NSwitchType::kString: + { + sw.PostStrings.Add(s.Ptr(pos)); + return true; + } + } + + if (pos != s.Len()) + { + ErrorMessage = "Too long switch:"; + return false; + } + return true; +} + + +bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings) +{ + StopSwitchIndex = -1; + ErrorMessage.Empty(); + ErrorLine.Empty(); + NonSwitchStrings.Clear(); + delete []_switches; + _switches = NULL; + _switches = new CSwitchResult[numSwitches]; + + FOR_VECTOR (i, commandStrings) + { + const UString &s = commandStrings[i]; + if (StopSwitchIndex < 0) + { + if (s.IsEqualTo(kStopSwitchParsing)) + { + StopSwitchIndex = NonSwitchStrings.Size(); + continue; + } + if (!s.IsEmpty() && IsItSwitchChar(s[0])) + { + if (ParseString(s, switchForms, numSwitches)) + continue; + ErrorLine = s; + return false; + } + } + NonSwitchStrings.Add(s); + } + return true; +} + +} diff --git a/other-licenses/7zstub/src/CPP/Common/CommandLineParser.h b/other-licenses/7zstub/src/CPP/Common/CommandLineParser.h new file mode 100644 index 0000000000..ec6336c81d --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/CommandLineParser.h @@ -0,0 +1,63 @@ +// Common/CommandLineParser.h + +#ifndef __COMMON_COMMAND_LINE_PARSER_H +#define __COMMON_COMMAND_LINE_PARSER_H + +#include "MyString.h" + +namespace NCommandLineParser { + +bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2); +void SplitCommandLine(const UString &s, UStringVector &parts); + +namespace NSwitchType +{ + enum EEnum + { + kSimple, + kMinus, + kString, + kChar + }; +} + +struct CSwitchForm +{ + const char *Key; + Byte Type; + bool Multi; + Byte MinLen; + // int MaxLen; + const char *PostCharSet; +}; + +struct CSwitchResult +{ + bool ThereIs; + bool WithMinus; + int PostCharIndex; + UStringVector PostStrings; + + CSwitchResult(): ThereIs(false) {}; +}; + +class CParser +{ + CSwitchResult *_switches; + + bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches); +public: + UStringVector NonSwitchStrings; + int StopSwitchIndex; // NonSwitchStrings[StopSwitchIndex+] are after "--" + AString ErrorMessage; + UString ErrorLine; + + CParser(); + ~CParser(); + bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings); + const CSwitchResult& operator[](unsigned index) const { return _switches[index]; } +}; + +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/Common.h b/other-licenses/7zstub/src/CPP/Common/Common.h new file mode 100644 index 0000000000..c1ecc7ed44 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/Common.h @@ -0,0 +1,43 @@ +// Common.h + +#ifndef __COMMON_COMMON_H +#define __COMMON_COMMON_H + +/* +This file is included to all cpp files in 7-Zip. +Each folder contains StdAfx.h file that includes "Common.h". +So 7-Zip includes "Common.h" in both modes: + with precompiled StdAfx.h +and + without precompiled StdAfx.h + +If you use 7-Zip code, you must include "Common.h" before other h files of 7-zip. +If you don't need some things that are used in 7-Zip, +you can change this h file or h files included in this file. +*/ + +// compiler pragmas to disable some warnings +#include "../../C/Compiler.h" + +// it's or code that defines windows things, if it's not _WIN32 +#include "MyWindows.h" + +// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers +#include "NewHandler.h" + + + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + + +/* There is BUG in MSVC 6.0 compiler for operator new[]: + It doesn't check overflow, when it calculates size in bytes for allocated array. + So we can use MY_ARRAY_NEW macro instead of new[] operator. */ + +#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64) + #define MY_ARRAY_NEW(p, T, size) p = new T[(size > (unsigned)0xFFFFFFFF / sizeof(T)) ? (unsigned)0xFFFFFFFF / sizeof(T) : size]; +#else + #define MY_ARRAY_NEW(p, T, size) p = new T[size]; +#endif + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/CrcReg.cpp b/other-licenses/7zstub/src/CPP/Common/CrcReg.cpp new file mode 100644 index 0000000000..1d9d009038 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/CrcReg.cpp @@ -0,0 +1,98 @@ +// CrcReg.cpp + +#include "StdAfx.h" + +#include "../../C/7zCrc.h" +#include "../../C/CpuArch.h" + +#include "../Common/MyCom.h" + +#include "../7zip/Common/RegisterCodec.h" + +EXTERN_C_BEGIN + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table); + +extern CRC_FUNC g_CrcUpdate; +extern CRC_FUNC g_CrcUpdateT8; +extern CRC_FUNC g_CrcUpdateT4; + +EXTERN_C_END + +class CCrcHasher: + public IHasher, + public ICompressSetCoderProperties, + public CMyUnknownImp +{ + UInt32 _crc; + CRC_FUNC _updateFunc; + Byte mtDummy[1 << 7]; + + bool SetFunctions(UInt32 tSize); +public: + CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); } + + MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties) + INTERFACE_IHasher(;) + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); +}; + +bool CCrcHasher::SetFunctions(UInt32 tSize) +{ + _updateFunc = g_CrcUpdate; + + if (tSize == 1) + _updateFunc = CrcUpdateT1; + else if (tSize == 4) + { + if (g_CrcUpdateT4) + _updateFunc = g_CrcUpdateT4; + else + return false; + } + else if (tSize == 8) + { + if (g_CrcUpdateT8) + _updateFunc = g_CrcUpdateT8; + else + return false; + } + + return true; +} + +STDMETHODIMP CCrcHasher::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; +} + +STDMETHODIMP_(void) CCrcHasher::Init() throw() +{ + _crc = CRC_INIT_VAL; +} + +STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size) throw() +{ + _crc = _updateFunc(_crc, data, size, g_CrcTable); +} + +STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest) throw() +{ + UInt32 val = CRC_GET_DIGEST(_crc); + SetUi32(digest, val); +} + +REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4) diff --git a/other-licenses/7zstub/src/CPP/Common/Defs.h b/other-licenses/7zstub/src/CPP/Common/Defs.h new file mode 100644 index 0000000000..9416098132 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/Defs.h @@ -0,0 +1,15 @@ +// Common/Defs.h + +#ifndef __COMMON_DEFS_H +#define __COMMON_DEFS_H + +template inline T MyMin(T a, T b) { return a < b ? a : b; } +template inline T MyMax(T a, T b) { return a > b ? a : b; } + +template inline int MyCompare(T a, T b) + { return a == b ? 0 : (a < b ? -1 : 1); } + +inline int BoolToInt(bool v) { return (v ? 1 : 0); } +inline bool IntToBool(int v) { return (v != 0); } + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/DynamicBuffer.h b/other-licenses/7zstub/src/CPP/Common/DynamicBuffer.h new file mode 100644 index 0000000000..16c925010e --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/DynamicBuffer.h @@ -0,0 +1,64 @@ +// Common/DynamicBuffer.h + +#ifndef __COMMON_DYNAMIC_BUFFER_H +#define __COMMON_DYNAMIC_BUFFER_H + +template class CDynamicBuffer +{ + T *_items; + size_t _size; + size_t _pos; + + CDynamicBuffer(const CDynamicBuffer &buffer); + void operator=(const CDynamicBuffer &buffer); + + void Grow(size_t size) + { + size_t delta = _size >= 64 ? _size : 64; + if (delta < size) + delta = size; + size_t newCap = _size + delta; + if (newCap < delta) + { + newCap = _size + size; + if (newCap < size) + throw 20120116; + } + + T *newBuffer = new T[newCap]; + if (_pos != 0) + memcpy(newBuffer, _items, _pos * sizeof(T)); + delete []_items; + _items = newBuffer; + _size = newCap; + } + +public: + CDynamicBuffer(): _items(0), _size(0), _pos(0) {} + // operator T *() { return _items; } + operator const T *() const { return _items; } + ~CDynamicBuffer() { delete []_items; } + + T *GetCurPtrAndGrow(size_t addSize) + { + size_t rem = _size - _pos; + if (rem < addSize) + Grow(addSize - rem); + T *res = _items + _pos; + _pos += addSize; + return res; + } + + void AddData(const T *data, size_t size) + { + memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T)); + } + + const size_t GetPos() const { return _pos; } + + // void Empty() { _pos = 0; } +}; + +typedef CDynamicBuffer CByteDynamicBuffer; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/IntToString.cpp b/other-licenses/7zstub/src/CPP/Common/IntToString.cpp new file mode 100644 index 0000000000..da627caefc --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/IntToString.cpp @@ -0,0 +1,193 @@ +// Common/IntToString.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#include "IntToString.h" + +#define CONVERT_INT_TO_STR(charType, tempSize) \ + unsigned char temp[tempSize]; unsigned i = 0; \ + while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ + *s++ = (charType)('0' + (unsigned)val); \ + while (i != 0) { i--; *s++ = temp[i]; } \ + *s = 0; + +void ConvertUInt32ToString(UInt32 val, char *s) throw() +{ + CONVERT_INT_TO_STR(char, 16); +} + +void ConvertUInt64ToString(UInt64 val, char *s) throw() +{ + if (val <= (UInt32)0xFFFFFFFF) + { + ConvertUInt32ToString((UInt32)val, s); + return; + } + CONVERT_INT_TO_STR(char, 24); +} + +void ConvertUInt64ToOct(UInt64 val, char *s) throw() +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 3; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0x7); + val >>= 3; + s[--i] = (char)('0' + t); + } + while (i); +} + + +#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + +static inline char GetHexChar(unsigned t) { return GET_HEX_CHAR(t); } + + +void ConvertUInt32ToHex(UInt32 val, char *s) throw() +{ + UInt32 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0xF); + val >>= 4; + s[--i] = GET_HEX_CHAR(t); + } + while (i); +} + + +void ConvertUInt64ToHex(UInt64 val, char *s) throw() +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0xF); + val >>= 4; + s[--i] = GET_HEX_CHAR(t); + } + while (i); +} + +void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw() +{ + s[8] = 0; + for (int i = 7; i >= 0; i--) + { + unsigned t = val & 0xF; + val >>= 4; + s[i] = GET_HEX_CHAR(t);; + } +} + +/* +void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s) +{ + s[8] = 0; + for (int i = 7; i >= 0; i--) + { + unsigned t = val & 0xF; + val >>= 4; + s[i] = (wchar_t)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + } +} +*/ + +void ConvertUInt32ToString(UInt32 val, wchar_t *s) throw() +{ + CONVERT_INT_TO_STR(wchar_t, 16); +} + +void ConvertUInt64ToString(UInt64 val, wchar_t *s) throw() +{ + if (val <= (UInt32)0xFFFFFFFF) + { + ConvertUInt32ToString((UInt32)val, s); + return; + } + CONVERT_INT_TO_STR(wchar_t, 24); +} + +void ConvertInt64ToString(Int64 val, char *s) throw() +{ + if (val < 0) + { + *s++ = '-'; + val = -val; + } + ConvertUInt64ToString(val, s); +} + +void ConvertInt64ToString(Int64 val, wchar_t *s) throw() +{ + if (val < 0) + { + *s++ = L'-'; + val = -val; + } + ConvertUInt64ToString(val, s); +} + + +static void ConvertByteToHex2Digits(unsigned v, char *s) throw() +{ + s[0] = GetHexChar(v >> 4); + s[1] = GetHexChar(v & 0xF); +} + +static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw() +{ + ConvertByteToHex2Digits(val >> 8, s); + ConvertByteToHex2Digits(val & 0xFF, s + 2); +} + +char *RawLeGuidToString(const Byte *g, char *s) throw() +{ + ConvertUInt32ToHex8Digits(GetUi32(g ), s); s += 8; *s++ = '-'; + ConvertUInt16ToHex4Digits(GetUi16(g + 4), s); s += 4; *s++ = '-'; + ConvertUInt16ToHex4Digits(GetUi16(g + 6), s); s += 4; *s++ = '-'; + for (unsigned i = 0; i < 8; i++) + { + if (i == 2) + *s++ = '-'; + ConvertByteToHex2Digits(g[8 + i], s); + s += 2; + } + *s = 0; + return s; +} + +char *RawLeGuidToString_Braced(const Byte *g, char *s) throw() +{ + *s++ = '{'; + s = RawLeGuidToString(g, s); + *s++ = '}'; + *s = 0; + return s; +} diff --git a/other-licenses/7zstub/src/CPP/Common/IntToString.h b/other-licenses/7zstub/src/CPP/Common/IntToString.h new file mode 100644 index 0000000000..07b67c31fa --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/IntToString.h @@ -0,0 +1,28 @@ +// Common/IntToString.h + +#ifndef __COMMON_INT_TO_STRING_H +#define __COMMON_INT_TO_STRING_H + +#include "MyTypes.h" + +void ConvertUInt32ToString(UInt32 value, char *s) throw(); +void ConvertUInt64ToString(UInt64 value, char *s) throw(); + +void ConvertUInt32ToString(UInt32 value, wchar_t *s) throw(); +void ConvertUInt64ToString(UInt64 value, wchar_t *s) throw(); + +void ConvertUInt64ToOct(UInt64 value, char *s) throw(); + +void ConvertUInt32ToHex(UInt32 value, char *s) throw(); +void ConvertUInt64ToHex(UInt64 value, char *s) throw(); +void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw(); +// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw(); + +void ConvertInt64ToString(Int64 value, char *s) throw(); +void ConvertInt64ToString(Int64 value, wchar_t *s) throw(); + +// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian. +char *RawLeGuidToString(const Byte *guid, char *s) throw(); +char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw(); + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/Lang.h b/other-licenses/7zstub/src/CPP/Common/Lang.h new file mode 100644 index 0000000000..e95de6859d --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/Lang.h @@ -0,0 +1,23 @@ +// Common/Lang.h + +#ifndef __COMMON_LANG_H +#define __COMMON_LANG_H + +#include "MyString.h" + +class CLang +{ + wchar_t *_text; + CRecordVector _ids; + CRecordVector _offsets; + + bool OpenFromString(const AString &s); +public: + CLang(): _text(0) {} + ~CLang() { Clear(); } + bool Open(CFSTR fileName, const char *id); + void Clear() throw(); + const wchar_t *Get(UInt32 id) const throw(); +}; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/ListFileUtils.cpp b/other-licenses/7zstub/src/CPP/Common/ListFileUtils.cpp new file mode 100644 index 0000000000..f22680b504 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/ListFileUtils.cpp @@ -0,0 +1,117 @@ +// Common/ListFileUtils.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#include "../Windows/FileIO.h" + +#include "ListFileUtils.h" +#include "MyBuffer.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +static const char kQuoteChar = '\"'; + +static void AddName(UStringVector &strings, UString &s) +{ + s.Trim(); + if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar) + { + s.DeleteBack(); + s.Delete(0); + } + if (!s.IsEmpty()) + strings.Add(s); +} + +bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage) +{ + NWindows::NFile::NIO::CInFile file; + if (!file.Open(fileName)) + return false; + UInt64 fileSize; + if (!file.GetLength(fileSize)) + return false; + if (fileSize >= ((UInt32)1 << 31) - 32) + return false; + UString u; + if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE) + { + if ((fileSize & 1) != 0) + return false; + CByteArr buf((size_t)fileSize); + UInt32 processed; + if (!file.Read(buf, (UInt32)fileSize, processed)) + return false; + if (processed != fileSize) + return false; + file.Close(); + unsigned num = (unsigned)fileSize / 2; + wchar_t *p = u.GetBuf(num); + if (codePage == MY__CP_UTF16) + for (unsigned i = 0; i < num; i++) + { + wchar_t c = GetUi16(buf + (size_t)i * 2); + if (c == 0) + return false; + p[i] = c; + } + else + for (unsigned i = 0; i < num; i++) + { + wchar_t c = (wchar_t)GetBe16(buf + (size_t)i * 2); + if (c == 0) + return false; + p[i] = c; + } + p[num] = 0; + u.ReleaseBuf_SetLen(num); + } + else + { + AString s; + char *p = s.GetBuf((unsigned)fileSize); + UInt32 processed; + if (!file.Read(p, (UInt32)fileSize, processed)) + return false; + if (processed != fileSize) + return false; + file.Close(); + s.ReleaseBuf_CalcLen((unsigned)processed); + if (s.Len() != processed) + return false; + + // #ifdef CP_UTF8 + if (codePage == CP_UTF8) + { + if (!ConvertUTF8ToUnicode(s, u)) + return false; + } + else + // #endif + MultiByteToUnicodeString2(u, s, codePage); + } + + const wchar_t kGoodBOM = 0xFEFF; + const wchar_t kBadBOM = 0xFFFE; + + UString s; + unsigned i = 0; + for (; i < u.Len() && u[i] == kGoodBOM; i++); + for (; i < u.Len(); i++) + { + wchar_t c = u[i]; + if (c == kGoodBOM || c == kBadBOM) + return false; + if (c == '\n' || c == 0xD) + { + AddName(strings, s); + s.Empty(); + } + else + s += c; + } + AddName(strings, s); + return true; +} diff --git a/other-licenses/7zstub/src/CPP/Common/ListFileUtils.h b/other-licenses/7zstub/src/CPP/Common/ListFileUtils.h new file mode 100644 index 0000000000..ec32d8e048 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/ListFileUtils.h @@ -0,0 +1,14 @@ +// Common/ListFileUtils.h + +#ifndef __COMMON_LIST_FILE_UTILS_H +#define __COMMON_LIST_FILE_UTILS_H + +#include "MyString.h" +#include "MyTypes.h" + +#define MY__CP_UTF16 1200 +#define MY__CP_UTF16BE 1201 + +bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyBuffer.h b/other-licenses/7zstub/src/CPP/Common/MyBuffer.h new file mode 100644 index 0000000000..ae320eefe9 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyBuffer.h @@ -0,0 +1,259 @@ +// Common/MyBuffer.h + +#ifndef __COMMON_MY_BUFFER_H +#define __COMMON_MY_BUFFER_H + +#include "Defs.h" + +/* 7-Zip now uses CBuffer only as CByteBuffer. + So there is no need to use MY_ARRAY_NEW macro in CBuffer code. */ + +template class CBuffer +{ + T *_items; + size_t _size; + +public: + void Free() + { + if (_items) + { + delete []_items; + _items = 0; + } + _size = 0; + } + + CBuffer(): _items(0), _size(0) {}; + CBuffer(size_t size): _items(0), _size(0) { _items = new T[size]; _size = size; } + CBuffer(const CBuffer &buffer): _items(0), _size(0) + { + size_t size = buffer._size; + if (size != 0) + { + _items = new T[size]; + memcpy(_items, buffer._items, size * sizeof(T)); + _size = size; + } + } + + ~CBuffer() { delete []_items; } + + operator T *() { return _items; } + operator const T *() const { return _items; } + size_t Size() const { return _size; } + + void Alloc(size_t size) + { + if (size != _size) + { + Free(); + if (size != 0) + { + _items = new T[size]; + _size = size; + } + } + } + + void AllocAtLeast(size_t size) + { + if (size > _size) + { + Free(); + _items = new T[size]; + _size = size; + } + } + + void CopyFrom(const T *data, size_t size) + { + Alloc(size); + if (size != 0) + memcpy(_items, data, size * sizeof(T)); + } + + void ChangeSize_KeepData(size_t newSize, size_t keepSize) + { + if (newSize == _size) + return; + T *newBuffer = NULL; + if (newSize != 0) + { + newBuffer = new T[newSize]; + if (keepSize > _size) + keepSize = _size; + if (keepSize != 0) + memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T)); + } + delete []_items; + _items = newBuffer; + _size = newSize; + } + + CBuffer& operator=(const CBuffer &buffer) + { + if (&buffer != this) + CopyFrom(buffer, buffer._size); + return *this; + } +}; + +template +bool operator==(const CBuffer& b1, const CBuffer& b2) +{ + size_t size1 = b1.Size(); + if (size1 != b2.Size()) + return false; + if (size1 == 0) + return true; + return memcmp(b1, b2, size1 * sizeof(T)) == 0; +} + +template +bool operator!=(const CBuffer& b1, const CBuffer& b2) +{ + size_t size1 = b1.Size(); + if (size1 != b2.Size()) + return true; + if (size1 == 0) + return false; + return memcmp(b1, b2, size1 * sizeof(T)) != 0; +} + + +// typedef CBuffer CCharBuffer; +// typedef CBuffer CWCharBuffer; +typedef CBuffer CByteBuffer; + + +template class CObjArray +{ +protected: + T *_items; +private: + // we disable copy + CObjArray(const CObjArray &buffer); + void operator=(const CObjArray &buffer); +public: + void Free() + { + delete []_items; + _items = 0; + } + CObjArray(size_t size): _items(0) + { + if (size != 0) + { + MY_ARRAY_NEW(_items, T, size) + // _items = new T[size]; + } + } + CObjArray(): _items(0) {}; + ~CObjArray() { delete []_items; } + + operator T *() { return _items; } + operator const T *() const { return _items; } + + void Alloc(size_t newSize) + { + delete []_items; + _items = 0; + MY_ARRAY_NEW(_items, T, newSize) + // _items = new T[newSize]; + } +}; + +typedef CObjArray CByteArr; +typedef CObjArray CBoolArr; +typedef CObjArray CIntArr; +typedef CObjArray CUIntArr; + + +template class CObjArray2 +{ + T *_items; + unsigned _size; + + // we disable copy + CObjArray2(const CObjArray2 &buffer); + void operator=(const CObjArray2 &buffer); +public: + + void Free() + { + delete []_items; + _items = 0; + _size = 0; + } + CObjArray2(): _items(0), _size(0) {}; + /* + CObjArray2(const CObjArray2 &buffer): _items(0), _size(0) + { + size_t newSize = buffer._size; + if (newSize != 0) + { + T *newBuffer = new T[newSize];; + _items = newBuffer; + _size = newSize; + const T *src = buffer; + for (size_t i = 0; i < newSize; i++) + newBuffer[i] = src[i]; + } + } + */ + /* + CObjArray2(size_t size): _items(0), _size(0) + { + if (size != 0) + { + _items = new T[size]; + _size = size; + } + } + */ + + ~CObjArray2() { delete []_items; } + + operator T *() { return _items; } + operator const T *() const { return _items; } + + unsigned Size() const { return (unsigned)_size; } + bool IsEmpty() const { return _size == 0; } + + // SetSize doesn't keep old items. It allocates new array if size is not equal + void SetSize(unsigned size) + { + if (size == _size) + return; + T *newBuffer = NULL; + if (size != 0) + { + MY_ARRAY_NEW(newBuffer, T, size) + // newBuffer = new T[size]; + } + delete []_items; + _items = newBuffer; + _size = size; + } + + /* + CObjArray2& operator=(const CObjArray2 &buffer) + { + Free(); + size_t newSize = buffer._size; + if (newSize != 0) + { + T *newBuffer = new T[newSize];; + _items = newBuffer; + _size = newSize; + const T *src = buffer; + for (size_t i = 0; i < newSize; i++) + newBuffer[i] = src[i]; + } + return *this; + } + */ +}; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyBuffer2.h b/other-licenses/7zstub/src/CPP/Common/MyBuffer2.h new file mode 100644 index 0000000000..5cabd73c5e --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyBuffer2.h @@ -0,0 +1,45 @@ +// Common/MyBuffer2.h + +#ifndef __COMMON_MY_BUFFER2_H +#define __COMMON_MY_BUFFER2_H + +#include "../../C/Alloc.h" + +#include "Defs.h" + +class CMidBuffer +{ + Byte *_data; + size_t _size; + + CLASS_NO_COPY(CMidBuffer) + +public: + CMidBuffer(): _data(NULL), _size(0) {}; + ~CMidBuffer() { ::MidFree(_data); } + + void Free() { ::MidFree(_data); _data = NULL; _size = 0; } + + bool IsAllocated() const { return _data != NULL; } + operator Byte *() { return _data; } + operator const Byte *() const { return _data; } + size_t Size() const { return _size; } + + void AllocAtLeast(size_t size) + { + if (!_data || size > _size) + { + const size_t kMinSize = (size_t)1 << 16; + if (size < kMinSize) + size = kMinSize; + ::MidFree(_data); + _size = 0; + _data = 0; + _data = (Byte *)::MidAlloc(size); + if (_data) + _size = size; + } + } +}; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyCom.h b/other-licenses/7zstub/src/CPP/Common/MyCom.h new file mode 100644 index 0000000000..ca49ead992 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyCom.h @@ -0,0 +1,277 @@ +// MyCom.h + +#ifndef __MY_COM_H +#define __MY_COM_H + +#include "MyWindows.h" + +#ifndef RINOK +#define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } +#endif + +template +class CMyComPtr +{ + T* _p; +public: + CMyComPtr(): _p(NULL) {} + CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } + ~CMyComPtr() { if (_p) _p->Release(); } + void Release() { if (_p) { _p->Release(); _p = NULL; } } + operator T*() const { return (T*)_p; } + // T& operator*() const { return *_p; } + T** operator&() { return &_p; } + T* operator->() const { return _p; } + T* operator=(T* p) + { + if (p) + p->AddRef(); + if (_p) + _p->Release(); + _p = p; + return p; + } + T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } + bool operator!() const { return (_p == NULL); } + // bool operator==(T* pT) const { return _p == pT; } + void Attach(T* p2) + { + Release(); + _p = p2; + } + T* Detach() + { + T* pt = _p; + _p = NULL; + return pt; + } + #ifdef _WIN32 + HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); + } + #endif + /* + HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + CLSID clsid; + HRESULT hr = CLSIDFromProgID(szProgID, &clsid); + ATLASSERT(_p == NULL); + if (SUCCEEDED(hr)) + hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); + return hr; + } + */ + template + HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() + { + return _p->QueryInterface(iid, (void**)pp); + } +}; + +////////////////////////////////////////////////////////// + +inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) +{ + *bstr = ::SysAllocString(src); + return (*bstr) ? S_OK : E_OUTOFMEMORY; +} + +class CMyComBSTR +{ + BSTR m_str; + +public: + CMyComBSTR(): m_str(NULL) {} + ~CMyComBSTR() { ::SysFreeString(m_str); } + BSTR* operator&() { return &m_str; } + operator LPCOLESTR() const { return m_str; } + // operator bool() const { return m_str != NULL; } + // bool operator!() const { return m_str == NULL; } +private: + // operator BSTR() const { return m_str; } + + CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } + // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } + // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } + CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } + + /* + CMyComBSTR(REFGUID src) + { + LPOLESTR szGuid; + StringFromCLSID(src, &szGuid); + m_str = ::SysAllocString(szGuid); + CoTaskMemFree(szGuid); + } + */ + + CMyComBSTR& operator=(const CMyComBSTR& src) + { + if (m_str != src.m_str) + { + if (m_str) + ::SysFreeString(m_str); + m_str = src.MyCopy(); + } + return *this; + } + + CMyComBSTR& operator=(LPCOLESTR src) + { + ::SysFreeString(m_str); + m_str = ::SysAllocString(src); + return *this; + } + + unsigned Len() const { return ::SysStringLen(m_str); } + + BSTR MyCopy() const + { + // We don't support Byte BSTRs here + return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); + /* + UINT byteLen = ::SysStringByteLen(m_str); + BSTR res = ::SysAllocStringByteLen(NULL, byteLen); + if (res && byteLen != 0 && m_str) + memcpy(res, m_str, byteLen); + return res; + */ + } + + /* + void Attach(BSTR src) { m_str = src; } + BSTR Detach() + { + BSTR s = m_str; + m_str = NULL; + return s; + } + */ + + void Empty() + { + ::SysFreeString(m_str); + m_str = NULL; + } +}; + + + +/* + If CMyUnknownImp doesn't use virtual destructor, the code size is smaller. + But if some class_1 derived from CMyUnknownImp + uses MY_ADDREF_RELEASE and IUnknown::Release() + and some another class_2 is derived from class_1, + then class_1 must use virtual destructor: + virtual ~class_1(); + In that case, class_1::Release() calls correct destructor of class_2. + + Also you can use virtual ~CMyUnknownImp(), if you want to disable warning + "class has virtual functions, but destructor is not virtual". +*/ + +class CMyUnknownImp +{ +public: + ULONG __m_RefCount; + CMyUnknownImp(): __m_RefCount(0) {} + + // virtual + ~CMyUnknownImp() {} +}; + + + +#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ +(REFGUID iid, void **outObject) throw() { *outObject = NULL; + +#define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; } + +#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ + { *outObject = (void *)(IUnknown *)(i *)this; } + +#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ + MY_QUERYINTERFACE_ENTRY(i) + +#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; ++__m_RefCount; /* AddRef(); */ return S_OK; } + +#define MY_ADDREF_RELEASE \ +STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \ +STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ + return __m_RefCount; delete this; return 0; } + +#define MY_UNKNOWN_IMP_SPEC(i) \ + MY_QUERYINTERFACE_BEGIN \ + i \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + + +#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + +#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ + MY_QUERYINTERFACE_ENTRY(i) \ + ) + +#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + ) + +#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + ) + +#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + ) + +#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + ) + +#define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + MY_QUERYINTERFACE_ENTRY(i6) \ + ) + +#define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + MY_QUERYINTERFACE_ENTRY(i6) \ + MY_QUERYINTERFACE_ENTRY(i7) \ + ) + +const HRESULT k_My_HRESULT_WritingWasCut = 0x20000010; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyException.h b/other-licenses/7zstub/src/CPP/Common/MyException.h new file mode 100644 index 0000000000..cd9fe6948b --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyException.h @@ -0,0 +1,14 @@ +// Common/Exception.h + +#ifndef __COMMON_EXCEPTION_H +#define __COMMON_EXCEPTION_H + +#include "MyWindows.h" + +struct CSystemException +{ + HRESULT ErrorCode; + CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} +}; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyGuidDef.h b/other-licenses/7zstub/src/CPP/Common/MyGuidDef.h new file mode 100644 index 0000000000..e0359e203a --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyGuidDef.h @@ -0,0 +1,54 @@ +// Common/MyGuidDef.h + +#ifndef GUID_DEFINED +#define GUID_DEFINED + +#include "MyTypes.h" + +typedef struct { + UInt32 Data1; + UInt16 Data2; + UInt16 Data3; + unsigned char Data4[8]; +} GUID; + +#ifdef __cplusplus +#define REFGUID const GUID & +#else +#define REFGUID const GUID * +#endif + +#define REFCLSID REFGUID +#define REFIID REFGUID + +#ifdef __cplusplus +inline int operator==(REFGUID g1, REFGUID g2) +{ + for (int i = 0; i < (int)sizeof(g1); i++) + if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) + return 0; + return 1; +} +inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } +#endif + +#ifdef __cplusplus + #define MY_EXTERN_C extern "C" +#else + #define MY_EXTERN_C extern +#endif + +#endif + + +#ifdef DEFINE_GUID +#undef DEFINE_GUID +#endif + +#ifdef INITGUID + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyInitGuid.h b/other-licenses/7zstub/src/CPP/Common/MyInitGuid.h new file mode 100644 index 0000000000..79fea19ab8 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyInitGuid.h @@ -0,0 +1,45 @@ +// Common/MyInitGuid.h + +#ifndef __COMMON_MY_INITGUID_H +#define __COMMON_MY_INITGUID_H + +/* +This file must be included only to one C++ file in project before +declarations of COM interfaces with DEFINE_GUID macro. + +Each GUID must be initialized exactly once in project. +There are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h): + - if INITGUID is not defined: DEFINE_GUID declares an external reference to the symbol name. + - if INITGUID is defined: DEFINE_GUID initializes the symbol name to the value of the GUID. + +Also we need IID_IUnknown that is initialized in some file for linking: + MSVC: by default the linker uses some lib file that contains IID_IUnknown + MinGW: add -luuid switch for linker + WinCE: we define IID_IUnknown in this file + Other: we define IID_IUnknown in this file +*/ + +#ifdef _WIN32 + +#ifdef UNDER_CE +#include +#endif + +#include + +#ifdef UNDER_CE +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +#endif + +#else + +#define INITGUID +#include "MyGuidDef.h" +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + +#endif + + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyLinux.h b/other-licenses/7zstub/src/CPP/Common/MyLinux.h new file mode 100644 index 0000000000..b4e7605226 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyLinux.h @@ -0,0 +1,42 @@ +// MyLinux.h + +#ifndef __MY_LIN_LINUX_H +#define __MY_LIN_LINUX_H + +#define MY_LIN_S_IFMT 00170000 +#define MY_LIN_S_IFSOCK 0140000 +#define MY_LIN_S_IFLNK 0120000 +#define MY_LIN_S_IFREG 0100000 +#define MY_LIN_S_IFBLK 0060000 +#define MY_LIN_S_IFDIR 0040000 +#define MY_LIN_S_IFCHR 0020000 +#define MY_LIN_S_IFIFO 0010000 + +#define MY_LIN_S_ISLNK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFLNK) +#define MY_LIN_S_ISREG(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFREG) +#define MY_LIN_S_ISDIR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFDIR) +#define MY_LIN_S_ISCHR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFCHR) +#define MY_LIN_S_ISBLK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFBLK) +#define MY_LIN_S_ISFIFO(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFIFO) +#define MY_LIN_S_ISSOCK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFSOCK) + +#define MY_LIN_S_ISUID 0004000 +#define MY_LIN_S_ISGID 0002000 +#define MY_LIN_S_ISVTX 0001000 + +#define MY_LIN_S_IRWXU 00700 +#define MY_LIN_S_IRUSR 00400 +#define MY_LIN_S_IWUSR 00200 +#define MY_LIN_S_IXUSR 00100 + +#define MY_LIN_S_IRWXG 00070 +#define MY_LIN_S_IRGRP 00040 +#define MY_LIN_S_IWGRP 00020 +#define MY_LIN_S_IXGRP 00010 + +#define MY_LIN_S_IRWXO 00007 +#define MY_LIN_S_IROTH 00004 +#define MY_LIN_S_IWOTH 00002 +#define MY_LIN_S_IXOTH 00001 + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyString.cpp b/other-licenses/7zstub/src/CPP/Common/MyString.cpp new file mode 100644 index 0000000000..bf62303df1 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyString.cpp @@ -0,0 +1,1659 @@ +// Common/MyString.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "IntToString.h" + +#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING) +#include "StringConvert.h" +#endif + +#include "MyString.h" + +#define MY_STRING_NEW(_T_, _size_) new _T_[_size_] +// #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_))) + +/* +inline const char* MyStringGetNextCharPointer(const char *p) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + return CharNextA(p); + #else + return p + 1; + #endif +} +*/ + +#define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, _size_) +#define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, _size_) + + +int FindCharPosInString(const char *s, char c) throw() +{ + for (const char *p = s;; p++) + { + if (*p == c) + return (int)(p - s); + if (*p == 0) + return -1; + // MyStringGetNextCharPointer(p); + } +} + +int FindCharPosInString(const wchar_t *s, wchar_t c) throw() +{ + for (const wchar_t *p = s;; p++) + { + if (*p == c) + return (int)(p - s); + if (*p == 0) + return -1; + } +} + +/* +void MyStringUpper_Ascii(char *s) throw() +{ + for (;;) + { + char c = *s; + if (c == 0) + return; + *s++ = MyCharUpper_Ascii(c); + } +} + +void MyStringUpper_Ascii(wchar_t *s) throw() +{ + for (;;) + { + wchar_t c = *s; + if (c == 0) + return; + *s++ = MyCharUpper_Ascii(c); + } +} +*/ + +void MyStringLower_Ascii(char *s) throw() +{ + for (;;) + { + char c = *s; + if (c == 0) + return; + *s++ = MyCharLower_Ascii(c); + } +} + +void MyStringLower_Ascii(wchar_t *s) throw() +{ + for (;;) + { + wchar_t c = *s; + if (c == 0) + return; + *s++ = MyCharLower_Ascii(c); + } +} + +#ifdef _WIN32 + +#ifdef _UNICODE + +// wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } +// wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } +// for WinCE - FString - char +// const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; } + +#else + +// const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); } +// char * MyStringUpper(char *s) { return CharUpperA(s); } +// char * MyStringLower(char *s) { return CharLowerA(s); } + +wchar_t MyCharUpper_WIN(wchar_t c) throw() +{ + wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return (wchar_t)(unsigned)(UINT_PTR)res; + const int kBufSize = 4; + char s[kBufSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); + if (numChars == 0 || numChars > kBufSize) + return c; + s[numChars] = 0; + ::CharUpperA(s); + ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); + return c; +} + +/* +wchar_t MyCharLower_WIN(wchar_t c) +{ + wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return (wchar_t)(unsigned)(UINT_PTR)res; + const int kBufSize = 4; + char s[kBufSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); + if (numChars == 0 || numChars > kBufSize) + return c; + s[numChars] = 0; + ::CharLowerA(s); + ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); + return c; +} +*/ + +/* +wchar_t * MyStringUpper(wchar_t *s) +{ + if (s == 0) + return 0; + wchar_t *res = CharUpperW(s); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return res; + AString a = UnicodeStringToMultiByte(s); + a.MakeUpper(); + MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + return s; +} +*/ + +/* +wchar_t * MyStringLower(wchar_t *s) +{ + if (s == 0) + return 0; + wchar_t *res = CharLowerW(s); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return res; + AString a = UnicodeStringToMultiByte(s); + a.MakeLower(); + MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + return s; +} +*/ + +#endif + +#endif + +bool IsString1PrefixedByString2(const char *s1, const char *s2) throw() +{ + for (;;) + { + unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true; + unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false; + } +} + +bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false; + if (c1 == 0) return true; + } +} + +// ---------- ASCII ---------- + +bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() +{ + const char *s1 = _chars; + for (;;) + { + char c2 = *s++; + if (c2 == 0) + return true; + char c1 = *s1++; + if (MyCharLower_Ascii(c1) != + MyCharLower_Ascii(c2)) + return false; + } +} + +bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() +{ + const wchar_t *s1 = _chars; + for (;;) + { + char c2 = *s++; + if (c2 == 0) + return true; + wchar_t c1 = *s1++; + if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) + return false; + } +} + +bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw() +{ + for (;;) + { + unsigned char c = *a; + if (c != *u) + return false; + if (c == 0) + return true; + a++; + u++; + } +} + +bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw() +{ + for (;;) + { + char c1 = *s1++; + char c2 = *s2++; + if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + if (c1 == 0) + return true; + } +} + +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + if (c1 == 0) + return true; + } +} + +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + char c2 = *s2++; + if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))) + return false; + if (c1 == 0) + return true; + } +} + +bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; + } +} + +bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; + } +} + +bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + char c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; + if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) + return false; + } +} + +bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; + if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) + return false; + } +} + +// NTFS order: uses upper case +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2) + { + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + if (u1 < u2) return -1; + if (u1 > u2) return 1; + } + if (c1 == 0) return 0; + } +} + +/* +int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) +{ + for (; num != 0; num--) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2) + { + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + if (u1 < u2) return -1; + if (u1 > u2) return 1; + } + if (c1 == 0) return 0; + } + return 0; +} +*/ + +// ---------- AString ---------- + +void AString::InsertSpace(unsigned &index, unsigned size) +{ + Grow(size); + MoveItems(index + size, index); +} + +#define k_Alloc_Len_Limit 0x40000000 + +void AString::ReAlloc(unsigned newLimit) +{ + if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220; + // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1); + char *newBuf = MY_STRING_NEW_char(newLimit + 1); + memcpy(newBuf, _chars, (size_t)(_len + 1)); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = newLimit; +} + +void AString::ReAlloc2(unsigned newLimit) +{ + if (newLimit >= k_Alloc_Len_Limit) throw 20130220; + // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0); + char *newBuf = MY_STRING_NEW_char(newLimit + 1); + newBuf[0] = 0; + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = newLimit; +} + +void AString::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW_char(len + 1); + _len = len; + _limit = len; +} + +void AString::Grow_1() +{ + unsigned next = _len; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +void AString::Grow(unsigned n) +{ + unsigned freeSize = _limit - _len; + if (n <= freeSize) + return; + + unsigned next = _len + n; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +AString::AString(unsigned num, const char *s) +{ + unsigned len = MyStringLen(s); + if (num > len) + num = len; + SetStartLen(num); + memcpy(_chars, s, num); + _chars[num] = 0; +} + +AString::AString(unsigned num, const AString &s) +{ + if (num > s._len) + num = s._len; + SetStartLen(num); + memcpy(_chars, s._chars, num); + _chars[num] = 0; +} + +AString::AString(const AString &s, char c) +{ + SetStartLen(s.Len() + 1); + char *chars = _chars; + unsigned len = s.Len(); + memcpy(chars, s, len); + chars[len] = c; + chars[(size_t)len + 1] = 0; +} + +AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2) +{ + SetStartLen(num1 + num2); + char *chars = _chars; + memcpy(chars, s1, num1); + memcpy(chars + num1, s2, num2 + 1); +} + +AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); } +AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); } +AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); } + +static const unsigned kStartStringCapacity = 4; + +AString::AString() +{ + _chars = 0; + _chars = MY_STRING_NEW_char(kStartStringCapacity); + _len = 0; + _limit = kStartStringCapacity - 1; + _chars[0] = 0; +} + +AString::AString(char c) +{ + SetStartLen(1); + char *chars = _chars; + chars[0] = c; + chars[1] = 0; +} + +AString::AString(const char *s) +{ + SetStartLen(MyStringLen(s)); + MyStringCopy(_chars, s); +} + +AString::AString(const AString &s) +{ + SetStartLen(s._len); + MyStringCopy(_chars, s._chars); +} + +AString &AString::operator=(char c) +{ + if (1 > _limit) + { + char *newBuf = MY_STRING_NEW_char(1 + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = 1; + } + _len = 1; + char *chars = _chars; + chars[0] = c; + chars[1] = 0; + return *this; +} + +AString &AString::operator=(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s); + return *this; +} + +AString &AString::operator=(const AString &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s._chars); + return *this; +} + +void AString::SetFromWStr_if_Ascii(const wchar_t *s) +{ + unsigned len = 0; + { + for (;; len++) + { + wchar_t c = s[len]; + if (c == 0) + break; + if (c >= 0x80) + return; + } + } + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + char *dest = _chars; + unsigned i; + for (i = 0; i < len; i++) + dest[i] = (char)s[i]; + dest[i] = 0; +} + +/* +void AString::SetFromBstr_if_Ascii(BSTR s) +{ + unsigned len = ::SysStringLen(s); + { + for (unsigned i = 0; i < len; i++) + if (s[i] <= 0 || s[i] >= 0x80) + return; + } + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + char *dest = _chars; + unsigned i; + for (i = 0; i < len; i++) + dest[i] = (char)s[i]; + dest[i] = 0; +} +*/ + +void AString::Add_Space() { operator+=(' '); } +void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } +void AString::Add_LF() { operator+=('\n'); } + +AString &AString::operator+=(const char *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + MyStringCopy(_chars + _len, s); + _len += len; + return *this; +} + +void AString::Add_OptSpaced(const char *s) +{ + Add_Space_if_NotEmpty(); + (*this) += s; +} + +AString &AString::operator+=(const AString &s) +{ + Grow(s._len); + MyStringCopy(_chars + _len, s._chars); + _len += s._len; + return *this; +} + +void AString::Add_UInt32(UInt32 v) +{ + char sz[16]; + ConvertUInt32ToString(v, sz); + (*this) += sz; +} + +void AString::SetFrom(const char *s, unsigned len) // no check +{ + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + if (len != 0) + memcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + +void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check +{ + unsigned i; + for (i = 0; i < len; i++) + if (s[i] == 0) + break; + SetFrom(s, i); +} + +int AString::Find(const char *s, unsigned startIndex) const throw() +{ + const char *fs = strstr(_chars + startIndex, s); + if (!fs) + return -1; + return (int)(fs - _chars); + + /* + if (s[0] == 0) + return startIndex; + unsigned len = MyStringLen(s); + const char *p = _chars + startIndex; + for (;; p++) + { + const char c = *p; + if (c != s[0]) + { + if (c == 0) + return -1; + continue; + } + unsigned i; + for (i = 1; i < len; i++) + if (p[i] != s[i]) + break; + if (i == len) + return (int)(p - _chars); + } + */ +} + +int AString::ReverseFind(char c) const throw() +{ + if (_len == 0) + return -1; + const char *p = _chars + _len - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; // p = GetPrevCharPointer(_chars, p); + } +} + +int AString::ReverseFind_PathSepar() const throw() +{ + if (_len == 0) + return -1; + const char *p = _chars + _len - 1; + for (;;) + { + char c = *p; + if (IS_PATH_SEPAR(c)) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; + } +} + +void AString::TrimLeft() throw() +{ + const char *p = _chars; + for (;; p++) + { + char c = *p; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + unsigned pos = (unsigned)(p - _chars); + if (pos != 0) + { + MoveItems(0, pos); + _len -= pos; + } +} + +void AString::TrimRight() throw() +{ + const char *p = _chars; + unsigned i; + for (i = _len; i != 0; i--) + { + char c = p[(size_t)i - 1]; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + if (i != _len) + { + _chars[i] = 0; + _len = i; + } +} + +void AString::InsertAtFront(char c) +{ + if (_limit == _len) + Grow_1(); + MoveItems(1, 0); + _chars[0] = c; + _len++; +} + +/* +void AString::Insert(unsigned index, char c) +{ + InsertSpace(index, 1); + _chars[index] = c; + _len++; +} +*/ + +void AString::Insert(unsigned index, const char *s) +{ + unsigned num = MyStringLen(s); + if (num != 0) + { + InsertSpace(index, num); + memcpy(_chars + index, s, num); + _len += num; + } +} + +void AString::Insert(unsigned index, const AString &s) +{ + unsigned num = s.Len(); + if (num != 0) + { + InsertSpace(index, num); + memcpy(_chars + index, s, num); + _len += num; + } +} + +void AString::RemoveChar(char ch) throw() +{ + char *src = _chars; + + for (;;) + { + char c = *src++; + if (c == 0) + return; + if (c == ch) + break; + } + + char *dest = src - 1; + + for (;;) + { + char c = *src++; + if (c == 0) + break; + if (c != ch) + *dest++ = c; + } + + *dest = 0; + _len = (unsigned)(dest - _chars); +} + +// !!!!!!!!!!!!!!! test it if newChar = '\0' +void AString::Replace(char oldChar, char newChar) throw() +{ + if (oldChar == newChar) + return; // 0; + // unsigned number = 0; + int pos = 0; + char *chars = _chars; + while ((unsigned)pos < _len) + { + pos = Find(oldChar, pos); + if (pos < 0) + break; + chars[(unsigned)pos] = newChar; + pos++; + // number++; + } + return; // number; +} + +void AString::Replace(const AString &oldString, const AString &newString) +{ + if (oldString.IsEmpty()) + return; // 0; + if (oldString == newString) + return; // 0; + unsigned oldLen = oldString.Len(); + unsigned newLen = newString.Len(); + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldString, pos); + if (pos < 0) + break; + Delete(pos, oldLen); + Insert(pos, newString); + pos += newLen; + // number++; + } + // return number; +} + +void AString::Delete(unsigned index) throw() +{ + MoveItems(index, index + 1); + _len--; +} + +void AString::Delete(unsigned index, unsigned count) throw() +{ + if (index + count > _len) + count = _len - index; + if (count > 0) + { + MoveItems(index, index + count); + _len -= count; + } +} + +void AString::DeleteFrontal(unsigned num) throw() +{ + if (num != 0) + { + MoveItems(0, num); + _len -= num; + } +} + +/* +AString operator+(const AString &s1, const AString &s2) +{ + AString result(s1); + result += s2; + return result; +} + +AString operator+(const AString &s, const char *chars) +{ + AString result(s); + result += chars; + return result; +} + +AString operator+(const char *chars, const AString &s) +{ + AString result(chars); + result += s; + return result; +} + +AString operator+(const AString &s, char c) +{ + AString result(s); + result += c; + return result; +} +*/ + +/* +AString operator+(char c, const AString &s) +{ + AString result(c); + result += s; + return result; +} +*/ + + + + +// ---------- UString ---------- + +void UString::InsertSpace(unsigned index, unsigned size) +{ + Grow(size); + MoveItems(index + size, index); +} + +void UString::ReAlloc(unsigned newLimit) +{ + if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221; + // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1); + wmemcpy(newBuf, _chars, _len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = newLimit; +} + +void UString::ReAlloc2(unsigned newLimit) +{ + if (newLimit >= k_Alloc_Len_Limit) throw 20130221; + // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1); + newBuf[0] = 0; + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = newLimit; +} + +void UString::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW_wchar_t(len + 1); + _len = len; + _limit = len; +} + +void UString::Grow_1() +{ + unsigned next = _len; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +void UString::Grow(unsigned n) +{ + unsigned freeSize = _limit - _len; + if (n <= freeSize) + return; + + unsigned next = _len + n; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + + +UString::UString(unsigned num, const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (num > len) + num = len; + SetStartLen(num); + wmemcpy(_chars, s, num); + _chars[num] = 0; +} + + +UString::UString(unsigned num, const UString &s) +{ + if (num > s._len) + num = s._len; + SetStartLen(num); + wmemcpy(_chars, s._chars, num); + _chars[num] = 0; +} + +UString::UString(const UString &s, wchar_t c) +{ + SetStartLen(s.Len() + 1); + wchar_t *chars = _chars; + unsigned len = s.Len(); + wmemcpy(chars, s, len); + chars[len] = c; + chars[(size_t)len + 1] = 0; +} + +UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2) +{ + SetStartLen(num1 + num2); + wchar_t *chars = _chars; + wmemcpy(chars, s1, num1); + wmemcpy(chars + num1, s2, num2 + 1); +} + +UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); } +UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); } +UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); } + +UString::UString() +{ + _chars = 0; + _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity); + _len = 0; + _limit = kStartStringCapacity - 1; + _chars[0] = 0; +} + +UString::UString(wchar_t c) +{ + SetStartLen(1); + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; +} + +UString::UString(char c) +{ + SetStartLen(1); + wchar_t *chars = _chars; + chars[0] = (unsigned char)c; + chars[1] = 0; +} + +UString::UString(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + SetStartLen(len); + wmemcpy(_chars, s, len + 1); +} + +UString::UString(const char *s) +{ + unsigned len = MyStringLen(s); + SetStartLen(len); + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; +} + +UString::UString(const UString &s) +{ + SetStartLen(s._len); + wmemcpy(_chars, s._chars, s._len + 1); +} + +UString &UString::operator=(wchar_t c) +{ + if (1 > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = 1; + } + _len = 1; + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; + return *this; +} + +UString &UString::operator=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + wmemcpy(_chars, s, len + 1); + return *this; +} + +UString &UString::operator=(const UString &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + wmemcpy(_chars, s._chars, len + 1); + return *this; +} + +void UString::SetFrom(const wchar_t *s, unsigned len) // no check +{ + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + if (len != 0) + wmemcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + +void UString::SetFromBstr(BSTR s) +{ + unsigned len = ::SysStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + // if (s) + wmemcpy(_chars, s, len + 1); +} + +UString &UString::operator=(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; + _len = len; + return *this; +} + +void UString::Add_Space() { operator+=(L' '); } +void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } + +void UString::Add_LF() +{ + if (_limit == _len) + Grow_1(); + unsigned len = _len; + wchar_t *chars = _chars; + chars[len++] = L'\n'; + chars[len] = 0; + _len = len; +} + +UString &UString::operator+=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + wmemcpy(_chars + _len, s, len + 1); + _len += len; + return *this; +} + +UString &UString::operator+=(const UString &s) +{ + Grow(s._len); + wmemcpy(_chars + _len, s._chars, s._len + 1); + _len += s._len; + return *this; +} + +UString &UString::operator+=(const char *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + wchar_t *chars = _chars + _len; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; + _len += len; + return *this; +} + + +void UString::Add_UInt32(UInt32 v) +{ + char sz[16]; + ConvertUInt32ToString(v, sz); + (*this) += sz; +} + + +int UString::Find(const wchar_t *s, unsigned startIndex) const throw() +{ + const wchar_t *fs = wcsstr(_chars + startIndex, s); + if (!fs) + return -1; + return (int)(fs - _chars); + + /* + if (s[0] == 0) + return startIndex; + unsigned len = MyStringLen(s); + const wchar_t *p = _chars + startIndex; + for (;; p++) + { + const wchar_t c = *p; + if (c != s[0]) + { + if (c == 0) + return -1; + continue; + } + unsigned i; + for (i = 1; i < len; i++) + if (p[i] != s[i]) + break; + if (i == len) + return (int)(p - _chars); + } + */ +} + +int UString::ReverseFind(wchar_t c) const throw() +{ + if (_len == 0) + return -1; + const wchar_t *p = _chars + _len - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; + } +} + +int UString::ReverseFind_PathSepar() const throw() +{ + if (_len == 0) + return -1; + const wchar_t *p = _chars + _len - 1; + for (;;) + { + wchar_t c = *p; + if (IS_PATH_SEPAR(c)) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; + } +} + +void UString::TrimLeft() throw() +{ + const wchar_t *p = _chars; + for (;; p++) + { + wchar_t c = *p; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + unsigned pos = (unsigned)(p - _chars); + if (pos != 0) + { + MoveItems(0, pos); + _len -= pos; + } +} + +void UString::TrimRight() throw() +{ + const wchar_t *p = _chars; + unsigned i; + for (i = _len; i != 0; i--) + { + wchar_t c = p[(size_t)i - 1]; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + if (i != _len) + { + _chars[i] = 0; + _len = i; + } +} + +void UString::InsertAtFront(wchar_t c) +{ + if (_limit == _len) + Grow_1(); + MoveItems(1, 0); + _chars[0] = c; + _len++; +} + +/* +void UString::Insert(unsigned index, wchar_t c) +{ + InsertSpace(index, 1); + _chars[index] = c; + _len++; +} +*/ + +void UString::Insert(unsigned index, const wchar_t *s) +{ + unsigned num = MyStringLen(s); + if (num != 0) + { + InsertSpace(index, num); + wmemcpy(_chars + index, s, num); + _len += num; + } +} + +void UString::Insert(unsigned index, const UString &s) +{ + unsigned num = s.Len(); + if (num != 0) + { + InsertSpace(index, num); + wmemcpy(_chars + index, s, num); + _len += num; + } +} + +void UString::RemoveChar(wchar_t ch) throw() +{ + wchar_t *src = _chars; + + for (;;) + { + wchar_t c = *src++; + if (c == 0) + return; + if (c == ch) + break; + } + + wchar_t *dest = src - 1; + + for (;;) + { + wchar_t c = *src++; + if (c == 0) + break; + if (c != ch) + *dest++ = c; + } + + *dest = 0; + _len = (unsigned)(dest - _chars); +} + +// !!!!!!!!!!!!!!! test it if newChar = '\0' +void UString::Replace(wchar_t oldChar, wchar_t newChar) throw() +{ + if (oldChar == newChar) + return; // 0; + // unsigned number = 0; + int pos = 0; + wchar_t *chars = _chars; + while ((unsigned)pos < _len) + { + pos = Find(oldChar, pos); + if (pos < 0) + break; + chars[(unsigned)pos] = newChar; + pos++; + // number++; + } + return; // number; +} + +void UString::Replace(const UString &oldString, const UString &newString) +{ + if (oldString.IsEmpty()) + return; // 0; + if (oldString == newString) + return; // 0; + unsigned oldLen = oldString.Len(); + unsigned newLen = newString.Len(); + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldString, pos); + if (pos < 0) + break; + Delete(pos, oldLen); + Insert(pos, newString); + pos += newLen; + // number++; + } + // return number; +} + +void UString::Delete(unsigned index) throw() +{ + MoveItems(index, index + 1); + _len--; +} + +void UString::Delete(unsigned index, unsigned count) throw() +{ + if (index + count > _len) + count = _len - index; + if (count > 0) + { + MoveItems(index, index + count); + _len -= count; + } +} + +void UString::DeleteFrontal(unsigned num) throw() +{ + if (num != 0) + { + MoveItems(0, num); + _len -= num; + } +} + + +// ---------- UString2 ---------- + +void UString2::ReAlloc2(unsigned newLimit) +{ + if (newLimit >= k_Alloc_Len_Limit) throw 20130221; + // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); + _chars = MY_STRING_NEW_wchar_t(newLimit + 1); +} + +void UString2::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW_wchar_t(len + 1); + _len = len; +} + + +/* +UString2::UString2(wchar_t c) +{ + SetStartLen(1); + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; +} +*/ + +UString2::UString2(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + SetStartLen(len); + wmemcpy(_chars, s, len + 1); +} + +UString2::UString2(const UString2 &s): _chars(NULL), _len(0) +{ + if (s._chars) + { + SetStartLen(s._len); + wmemcpy(_chars, s._chars, s._len + 1); + } +} + +/* +UString2 &UString2::operator=(wchar_t c) +{ + if (1 > _len) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1); + if (_chars) + MY_STRING_DELETE(_chars); + _chars = newBuf; + } + _len = 1; + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; + return *this; +} +*/ + +UString2 &UString2::operator=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (len > _len) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + if (_chars) + MY_STRING_DELETE(_chars); + _chars = newBuf; + } + _len = len; + MyStringCopy(_chars, s); + return *this; +} + +void UString2::SetFromAscii(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _len) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + if (_chars) + MY_STRING_DELETE(_chars); + _chars = newBuf; + } + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; + _len = len; +} + +UString2 &UString2::operator=(const UString2 &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _len) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + if (_chars) + MY_STRING_DELETE(_chars); + _chars = newBuf; + } + _len = len; + MyStringCopy(_chars, s._chars); + return *this; +} + +bool operator==(const UString2 &s1, const UString2 &s2) +{ + return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0); +} + +bool operator==(const UString2 &s1, const wchar_t *s2) +{ + if (s1.IsEmpty()) + return (*s2 == 0); + return wcscmp(s1.GetRawPtr(), s2) == 0; +} + +bool operator==(const wchar_t *s1, const UString2 &s2) +{ + if (s2.IsEmpty()) + return (*s1 == 0); + return wcscmp(s1, s2.GetRawPtr()) == 0; +} + + + +// ---------------------------------------- + +/* +int MyStringCompareNoCase(const char *s1, const char *s2) +{ + return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); +} +*/ + +static inline UINT GetCurrentCodePage() +{ + #if defined(UNDER_CE) || !defined(_WIN32) + return CP_ACP; + #else + return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif +} + +#ifdef USE_UNICODE_FSTRING + +#ifndef _UNICODE + +AString fs2fas(CFSTR s) +{ + return UnicodeStringToMultiByte(s, GetCurrentCodePage()); +} + +FString fas2fs(const char *s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +FString fas2fs(const AString &s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +#endif + +#else + +UString fs2us(const FChar *s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +UString fs2us(const FString &s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +FString us2fs(const wchar_t *s) +{ + return UnicodeStringToMultiByte(s, GetCurrentCodePage()); +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyString.h b/other-licenses/7zstub/src/CPP/Common/MyString.h new file mode 100644 index 0000000000..f484ad225f --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyString.h @@ -0,0 +1,867 @@ +// Common/String.h + +#ifndef __COMMON_STRING_H +#define __COMMON_STRING_H + +#include + +#ifndef _WIN32 +#include +#include +#endif + +#include "MyWindows.h" +#include "MyTypes.h" +#include "MyVector.h" + + +#ifdef _MSC_VER + #ifdef _NATIVE_WCHAR_T_DEFINED + #define MY_NATIVE_WCHAR_T_DEFINED + #endif +#else + #define MY_NATIVE_WCHAR_T_DEFINED +#endif + +/* + native support for wchar_t: + _MSC_VER == 1600 : /Zc:wchar_t is not supported + _MSC_VER == 1310 (VS2003) + ? _MSC_VER == 1400 (VS2005) : wchar_t <- unsigned short + /Zc:wchar_t : wchar_t <- __wchar_t, _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED + _MSC_VER > 1400 (VS2008+) + /Zc:wchar_t[-] + /Zc:wchar_t is on by default +*/ + +#ifdef _WIN32 +#define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/') +#else +#define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR) +#endif + +inline bool IsPathSepar(char c) { return IS_PATH_SEPAR(c); } +inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); } + +inline unsigned MyStringLen(const char *s) +{ + unsigned i; + for (i = 0; s[i] != 0; i++); + return i; +} + +inline void MyStringCopy(char *dest, const char *src) +{ + while ((*dest++ = *src++) != 0); +} + +inline char *MyStpCpy(char *dest, const char *src) +{ + for (;;) + { + char c = *src; + *dest = c; + if (c == 0) + return dest; + src++; + dest++; + } +} + +inline unsigned MyStringLen(const wchar_t *s) +{ + unsigned i; + for (i = 0; s[i] != 0; i++); + return i; +} + +inline void MyStringCopy(wchar_t *dest, const wchar_t *src) +{ + while ((*dest++ = *src++) != 0); +} + +inline void MyStringCat(wchar_t *dest, const wchar_t *src) +{ + MyStringCopy(dest + MyStringLen(dest), src); +} + + +/* +inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src) +{ + for (;;) + { + wchar_t c = *src; + *dest = c; + if (c == 0) + return dest; + src++; + dest++; + } +} +*/ + +int FindCharPosInString(const char *s, char c) throw(); +int FindCharPosInString(const wchar_t *s, wchar_t c) throw(); + +#ifdef _WIN32 + #ifndef _UNICODE + #define STRING_UNICODE_THROW + #endif +#endif + +#ifndef STRING_UNICODE_THROW + #define STRING_UNICODE_THROW throw() +#endif + + +inline char MyCharUpper_Ascii(char c) +{ + if (c >= 'a' && c <= 'z') + return (char)((unsigned char)c - 0x20); + return c; +} + +/* +inline wchar_t MyCharUpper_Ascii(wchar_t c) +{ + if (c >= 'a' && c <= 'z') + return (wchar_t)(c - 0x20); + return c; +} +*/ + +inline char MyCharLower_Ascii(char c) +{ + if (c >= 'A' && c <= 'Z') + return (char)((unsigned char)c + 0x20); + return c; +} + +inline wchar_t MyCharLower_Ascii(wchar_t c) +{ + if (c >= 'A' && c <= 'Z') + return (wchar_t)(c + 0x20); + return c; +} + +wchar_t MyCharUpper_WIN(wchar_t c) throw(); + +inline wchar_t MyCharUpper(wchar_t c) throw() +{ + if (c < 'a') return c; + if (c <= 'z') return (wchar_t)(c - 0x20); + if (c <= 0x7F) return c; + #ifdef _WIN32 + #ifdef _UNICODE + return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); + #else + return (wchar_t)MyCharUpper_WIN(c); + #endif + #else + return (wchar_t)towupper(c); + #endif +} + +/* +wchar_t MyCharLower_WIN(wchar_t c) throw(); + +inline wchar_t MyCharLower(wchar_t c) throw() +{ + if (c < 'A') return c; + if (c <= 'Z') return (wchar_t)(c + 0x20); + if (c <= 0x7F) return c; + #ifdef _WIN32 + #ifdef _UNICODE + return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); + #else + return (wchar_t)MyCharLower_WIN(c); + #endif + #else + return (wchar_t)tolower(c); + #endif +} +*/ + +// char *MyStringUpper(char *s) throw(); +// char *MyStringLower(char *s) throw(); + +// void MyStringUpper_Ascii(char *s) throw(); +// void MyStringUpper_Ascii(wchar_t *s) throw(); +void MyStringLower_Ascii(char *s) throw(); +void MyStringLower_Ascii(wchar_t *s) throw(); +// wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW; +// wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW; + +bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw(); + +bool IsString1PrefixedByString2(const char *s1, const char *s2) throw(); +bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw(); +bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw(); +bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw(); +bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw(); + +#define MyStringCompare(s1, s2) wcscmp(s1, s2) +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw(); +// int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw(); + +// ---------- ASCII ---------- +// char values in ASCII strings must be less then 128 +bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw(); +bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw(); +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw(); +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw(); + +#define MY_STRING_DELETE(_p_) delete []_p_; +// #define MY_STRING_DELETE(_p_) my_delete(_p_); + + +#define FORBID_STRING_OPS_2(cls, t) \ + void Find(t) const; \ + void Find(t, unsigned startIndex) const; \ + void ReverseFind(t) const; \ + void InsertAtFront(t); \ + void RemoveChar(t); \ + void Replace(t, t); \ + +#define FORBID_STRING_OPS(cls, t) \ + explicit cls(t); \ + explicit cls(const t *); \ + cls &operator=(t); \ + cls &operator=(const t *); \ + cls &operator+=(t); \ + cls &operator+=(const t *); \ + FORBID_STRING_OPS_2(cls, t); \ + +/* + cls &operator+(t); \ + cls &operator+(const t *); \ +*/ + +#define FORBID_STRING_OPS_AString(t) FORBID_STRING_OPS(AString, t) +#define FORBID_STRING_OPS_UString(t) FORBID_STRING_OPS(UString, t) +#define FORBID_STRING_OPS_UString2(t) FORBID_STRING_OPS(UString2, t) + +class AString +{ + char *_chars; + unsigned _len; + unsigned _limit; + + void MoveItems(unsigned dest, unsigned src) + { + memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char)); + } + + void InsertSpace(unsigned &index, unsigned size); + + void ReAlloc(unsigned newLimit); + void ReAlloc2(unsigned newLimit); + void SetStartLen(unsigned len); + void Grow_1(); + void Grow(unsigned n); + + AString(unsigned num, const char *s); + AString(unsigned num, const AString &s); + AString(const AString &s, char c); // it's for String + char + AString(const char *s1, unsigned num1, const char *s2, unsigned num2); + + friend AString operator+(const AString &s, char c) { return AString(s, c); } ; + // friend AString operator+(char c, const AString &s); // is not supported + + friend AString operator+(const AString &s1, const AString &s2); + friend AString operator+(const AString &s1, const char *s2); + friend AString operator+(const char *s1, const AString &s2); + + // ---------- forbidden functions ---------- + + #ifdef MY_NATIVE_WCHAR_T_DEFINED + FORBID_STRING_OPS_AString(wchar_t) + #endif + + FORBID_STRING_OPS_AString(signed char) + FORBID_STRING_OPS_AString(unsigned char) + FORBID_STRING_OPS_AString(short) + FORBID_STRING_OPS_AString(unsigned short) + FORBID_STRING_OPS_AString(int) + FORBID_STRING_OPS_AString(unsigned) + FORBID_STRING_OPS_AString(long) + FORBID_STRING_OPS_AString(unsigned long) + +public: + explicit AString(); + explicit AString(char c); + explicit AString(const char *s); + AString(const AString &s); + ~AString() { MY_STRING_DELETE(_chars); } + + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + void Empty() { _len = 0; _chars[0] = 0; } + + operator const char *() const { return _chars; } + const char *Ptr() const { return _chars; } + const char *Ptr(unsigned pos) const { return _chars + pos; } + const char *RightPtr(unsigned num) const { return _chars + _len - num; } + char Back() const { return _chars[(size_t)_len - 1]; } + + void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; } + + /* GetBuf(minLen): provides the buffer that can store + at least (minLen) characters and additional null terminator. + 9.35: GetBuf doesn't preserve old characters and terminator */ + char *GetBuf(unsigned minLen) + { + if (minLen > _limit) + ReAlloc2(minLen); + return _chars; + } + char *GetBuf_SetEnd(unsigned minLen) + { + if (minLen > _limit) + ReAlloc2(minLen); + char *chars = _chars; + chars[minLen] = 0; + _len = minLen; + return chars; + } + + void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } + void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } + void ReleaseBuf_CalcLen(unsigned maxLen) + { + char *chars = _chars; + chars[maxLen] = 0; + _len = MyStringLen(chars); + } + + AString &operator=(char c); + AString &operator=(const char *s); + AString &operator=(const AString &s); + void SetFromWStr_if_Ascii(const wchar_t *s); + // void SetFromBstr_if_Ascii(BSTR s); + + AString &operator+=(char c) + { + if (_limit == _len) + Grow_1(); + unsigned len = _len; + char *chars = _chars; + chars[len++] = c; + chars[len] = 0; + _len = len; + return *this; + } + + void Add_Space(); + void Add_Space_if_NotEmpty(); + void Add_OptSpaced(const char *s); + void Add_LF(); + void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); } + + AString &operator+=(const char *s); + AString &operator+=(const AString &s); + + void Add_UInt32(UInt32 v); + + void SetFrom(const char *s, unsigned len); // no check + void SetFrom_CalcLen(const char *s, unsigned len); + + AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } + AString Left(unsigned count) const { return AString(count, *this); } + + // void MakeUpper() { MyStringUpper(_chars); } + // void MakeLower() { MyStringLower(_chars); } + void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } + + + bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; } + bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); } + // int Compare(const char *s) const { return MyStringCompare(_chars, s); } + // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); } + // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); } + // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); } + bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); } + bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); + + bool IsAscii() const + { + unsigned len = Len(); + const char *s = _chars; + for (unsigned i = 0; i < len; i++) + if ((unsigned char)s[i] >= 0x80) + return false; + return true; + } + int Find(char c) const { return FindCharPosInString(_chars, c); } + int Find(char c, unsigned startIndex) const + { + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : (int)startIndex + pos; + } + + int ReverseFind(char c) const throw(); + int ReverseFind_Dot() const throw() { return ReverseFind('.'); } + int ReverseFind_PathSepar() const throw(); + + int Find(const char *s) const { return Find(s, 0); } + int Find(const char *s, unsigned startIndex) const throw(); + + void TrimLeft() throw(); + void TrimRight() throw(); + void Trim() + { + TrimRight(); + TrimLeft(); + } + + void InsertAtFront(char c); + // void Insert(unsigned index, char c); + void Insert(unsigned index, const char *s); + void Insert(unsigned index, const AString &s); + + void RemoveChar(char ch) throw(); + + void Replace(char oldChar, char newChar) throw(); + void Replace(const AString &oldString, const AString &newString); + + void Delete(unsigned index) throw(); + void Delete(unsigned index, unsigned count) throw(); + void DeleteFrontal(unsigned num) throw(); + void DeleteBack() { _chars[--_len] = 0; } + void DeleteFrom(unsigned index) + { + if (index < _len) + { + _len = index; + _chars[index] = 0; + } + } +}; + +bool operator<(const AString &s1, const AString &s2); +bool operator>(const AString &s1, const AString &s2); + +/* +bool operator==(const AString &s1, const AString &s2); +bool operator==(const AString &s1, const char *s2); +bool operator==(const char *s1, const AString &s2); + +bool operator!=(const AString &s1, const AString &s2); +bool operator!=(const AString &s1, const char *s2); +bool operator!=(const char *s1, const AString &s2); +*/ + +inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; } +inline bool operator==(const AString &s1, const char *s2) { return strcmp(s1, s2) == 0; } +inline bool operator==(const char *s1, const AString &s2) { return strcmp(s1, s2) == 0; } + +inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; } +inline bool operator!=(const AString &s1, const char *s2) { return strcmp(s1, s2) != 0; } +inline bool operator!=(const char *s1, const AString &s2) { return strcmp(s1, s2) != 0; } + +// ---------- forbidden functions ---------- + +void operator==(char c1, const AString &s2); +void operator==(const AString &s1, char c2); + +void operator+(char c, const AString &s); // this function can be OK, but we don't use it + +void operator+(const AString &s, int c); +void operator+(const AString &s, unsigned c); +void operator+(int c, const AString &s); +void operator+(unsigned c, const AString &s); +void operator-(const AString &s, int c); +void operator-(const AString &s, unsigned c); + + +class UString +{ + wchar_t *_chars; + unsigned _len; + unsigned _limit; + + void MoveItems(unsigned dest, unsigned src) + { + memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t)); + } + + void InsertSpace(unsigned index, unsigned size); + + void ReAlloc(unsigned newLimit); + void ReAlloc2(unsigned newLimit); + void SetStartLen(unsigned len); + void Grow_1(); + void Grow(unsigned n); + + UString(unsigned num, const wchar_t *s); // for Mid + UString(unsigned num, const UString &s); // for Left + UString(const UString &s, wchar_t c); // it's for String + char + UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2); + + friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } ; + // friend UString operator+(wchar_t c, const UString &s); // is not supported + + friend UString operator+(const UString &s1, const UString &s2); + friend UString operator+(const UString &s1, const wchar_t *s2); + friend UString operator+(const wchar_t *s1, const UString &s2); + + // ---------- forbidden functions ---------- + + FORBID_STRING_OPS_UString(signed char) + FORBID_STRING_OPS_UString(unsigned char) + FORBID_STRING_OPS_UString(short) + + #ifdef MY_NATIVE_WCHAR_T_DEFINED + FORBID_STRING_OPS_UString(unsigned short) + #endif + + FORBID_STRING_OPS_UString(int) + FORBID_STRING_OPS_UString(unsigned) + FORBID_STRING_OPS_UString(long) + FORBID_STRING_OPS_UString(unsigned long) + + FORBID_STRING_OPS_2(UString, char) + +public: + UString(); + explicit UString(wchar_t c); + explicit UString(char c); + explicit UString(const char *s); + // UString(const AString &s); + UString(const wchar_t *s); + UString(const UString &s); + ~UString() { MY_STRING_DELETE(_chars); } + + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + void Empty() { _len = 0; _chars[0] = 0; } + + operator const wchar_t *() const { return _chars; } + const wchar_t *Ptr() const { return _chars; } + const wchar_t *Ptr(unsigned pos) const { return _chars + pos; } + const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; } + wchar_t Back() const { return _chars[(size_t)_len - 1]; } + + void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; } + + wchar_t *GetBuf() { return _chars; } + + wchar_t *GetBuf(unsigned minLen) + { + if (minLen > _limit) + ReAlloc2(minLen); + return _chars; + } + wchar_t *GetBuf_SetEnd(unsigned minLen) + { + if (minLen > _limit) + ReAlloc2(minLen); + wchar_t *chars = _chars; + chars[minLen] = 0; + _len = minLen; + return chars; + } + + void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } + void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } + void ReleaseBuf_CalcLen(unsigned maxLen) + { + wchar_t *chars = _chars; + chars[maxLen] = 0; + _len = MyStringLen(chars); + } + + UString &operator=(wchar_t c); + UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); } + UString &operator=(const wchar_t *s); + UString &operator=(const UString &s); + void SetFrom(const wchar_t *s, unsigned len); // no check + void SetFromBstr(BSTR s); + UString &operator=(const char *s); + UString &operator=(const AString &s) { return operator=(s.Ptr()); } + + UString &operator+=(wchar_t c) + { + if (_limit == _len) + Grow_1(); + unsigned len = _len; + wchar_t *chars = _chars; + chars[len++] = c; + chars[len] = 0; + _len = len; + return *this; + } + + UString &operator+=(char c) { return (*this)+=((wchar_t)(unsigned char)c); } + + void Add_Space(); + void Add_Space_if_NotEmpty(); + void Add_LF(); + void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); } + + UString &operator+=(const wchar_t *s); + UString &operator+=(const UString &s); + UString &operator+=(const char *s); + UString &operator+=(const AString &s) { return operator+=(s.Ptr()); } + + void Add_UInt32(UInt32 v); + + UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); } + UString Left(unsigned count) const { return UString(count, *this); } + + // void MakeUpper() { MyStringUpper(_chars); } + // void MakeUpper() { MyStringUpper_Ascii(_chars); } + // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); } + void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } + + bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); } + bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); } + bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); } + int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } + // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); } + // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); } + // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); } + bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); } + bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); } + bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); + + bool IsAscii() const + { + unsigned len = Len(); + const wchar_t *s = _chars; + for (unsigned i = 0; i < len; i++) + if (s[i] >= 0x80) + return false; + return true; + } + int Find(wchar_t c) const { return FindCharPosInString(_chars, c); } + int Find(wchar_t c, unsigned startIndex) const + { + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : (int)startIndex + pos; + } + + int ReverseFind(wchar_t c) const throw(); + int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); } + int ReverseFind_PathSepar() const throw(); + + int Find(const wchar_t *s) const { return Find(s, 0); } + int Find(const wchar_t *s, unsigned startIndex) const throw(); + + void TrimLeft() throw(); + void TrimRight() throw(); + void Trim() + { + TrimRight(); + TrimLeft(); + } + + void InsertAtFront(wchar_t c); + // void Insert(unsigned index, wchar_t c); + void Insert(unsigned index, const wchar_t *s); + void Insert(unsigned index, const UString &s); + + void RemoveChar(wchar_t ch) throw(); + + void Replace(wchar_t oldChar, wchar_t newChar) throw(); + void Replace(const UString &oldString, const UString &newString); + + void Delete(unsigned index) throw(); + void Delete(unsigned index, unsigned count) throw(); + void DeleteFrontal(unsigned num) throw(); + void DeleteBack() { _chars[--_len] = 0; } + void DeleteFrom(unsigned index) + { + if (index < _len) + { + _len = index; + _chars[index] = 0; + } + } +}; + +bool operator<(const UString &s1, const UString &s2); +bool operator>(const UString &s1, const UString &s2); + +inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; } +inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; } +inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; } + +inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; } +inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; } +inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; } + + +// ---------- forbidden functions ---------- + +void operator==(wchar_t c1, const UString &s2); +void operator==(const UString &s1, wchar_t c2); + +void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it + +void operator+(const AString &s1, const UString &s2); +void operator+(const UString &s1, const AString &s2); + +void operator+(const UString &s1, const char *s2); +void operator+(const char *s1, const UString &s2); + +void operator+(const UString &s, char c); +void operator+(const UString &s, unsigned char c); +void operator+(char c, const UString &s); +void operator+(unsigned char c, const UString &s); +void operator-(const UString &s1, wchar_t c); + +#ifdef _WIN32 +// can we forbid these functions, if wchar_t is 32-bit ? +void operator+(const UString &s, int c); +void operator+(const UString &s, unsigned c); +void operator+(int c, const UString &s); +void operator+(unsigned c, const UString &s); +void operator-(const UString &s1, int c); +void operator-(const UString &s1, unsigned c); +#endif + + + + + + + +class UString2 +{ + wchar_t *_chars; + unsigned _len; + + void ReAlloc2(unsigned newLimit); + void SetStartLen(unsigned len); + + // ---------- forbidden functions ---------- + + FORBID_STRING_OPS_UString2(char) + FORBID_STRING_OPS_UString2(signed char) + FORBID_STRING_OPS_UString2(unsigned char) + FORBID_STRING_OPS_UString2(short) + + UString2 &operator=(wchar_t c); + UString2(wchar_t c); + +public: + UString2(): _chars(NULL), _len(0) {} + UString2(const wchar_t *s); + UString2(const UString2 &s); + ~UString2() { if (_chars) MY_STRING_DELETE(_chars); } + + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + // void Empty() { _len = 0; _chars[0] = 0; } + + // operator const wchar_t *() const { return _chars; } + const wchar_t *GetRawPtr() const { return _chars; } + + int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } + + wchar_t *GetBuf(unsigned minLen) + { + if (!_chars || minLen > _len) + ReAlloc2(minLen); + return _chars; + } + void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } + + UString2 &operator=(const wchar_t *s); + UString2 &operator=(const UString2 &s); + void SetFromAscii(const char *s); +}; + +bool operator==(const UString2 &s1, const UString2 &s2); +bool operator==(const UString2 &s1, const wchar_t *s2); +bool operator==(const wchar_t *s1, const UString2 &s2); + +inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); } +inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); } +inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); } + + +// ---------- forbidden functions ---------- + +void operator==(wchar_t c1, const UString2 &s2); +void operator==(const UString2 &s1, wchar_t c2); +bool operator<(const UString2 &s1, const UString2 &s2); +bool operator>(const UString2 &s1, const UString2 &s2); + +void operator+(const UString2 &s1, const UString2 &s2); +void operator+(const UString2 &s1, const wchar_t *s2); +void operator+(const wchar_t *s1, const UString2 &s2); +void operator+(wchar_t c, const UString2 &s); +void operator+(const UString2 &s, wchar_t c); +void operator+(const UString2 &s, char c); +void operator+(const UString2 &s, unsigned char c); +void operator+(char c, const UString2 &s); +void operator+(unsigned char c, const UString2 &s); +void operator-(const UString2 &s1, wchar_t c); + + + + + + +typedef CObjectVector AStringVector; +typedef CObjectVector UStringVector; + +#ifdef _UNICODE + typedef UString CSysString; +#else + typedef AString CSysString; +#endif + +typedef CObjectVector CSysStringVector; + + +// ---------- FString ---------- + +#ifdef _WIN32 + #define USE_UNICODE_FSTRING +#endif + +#ifdef USE_UNICODE_FSTRING + + #define __FTEXT(quote) L##quote + + typedef wchar_t FChar; + typedef UString FString; + + #define fs2us(_x_) (_x_) + #define us2fs(_x_) (_x_) + FString fas2fs(const char *s); + FString fas2fs(const AString &s); + AString fs2fas(const FChar *s); + +#else + + #define __FTEXT(quote) quote + + typedef char FChar; + typedef AString FString; + + UString fs2us(const FChar *s); + UString fs2us(const FString &s); + FString us2fs(const wchar_t *s); + #define fas2fs(_x_) (_x_) + #define fs2fas(_x_) (_x_) + +#endif + +#define FTEXT(quote) __FTEXT(quote) + +#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR) +#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR) + +// #define FCHAR_ANY_MASK FTEXT('*') +// #define FSTRING_ANY_MASK FTEXT("*") + +typedef const FChar *CFSTR; + +typedef CObjectVector FStringVector; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyTypes.h b/other-licenses/7zstub/src/CPP/Common/MyTypes.h new file mode 100644 index 0000000000..6e73aca31e --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyTypes.h @@ -0,0 +1,35 @@ +// Common/MyTypes.h + +#ifndef __COMMON_MY_TYPES_H +#define __COMMON_MY_TYPES_H + +#include "../../C/7zTypes.h" + +typedef int HRes; + +struct CBoolPair +{ + bool Val; + bool Def; + + CBoolPair(): Val(false), Def(false) {} + + void Init() + { + Val = false; + Def = false; + } + + void SetTrueTrue() + { + Val = true; + Def = true; + } +}; + +#define CLASS_NO_COPY(cls) \ + private: \ + cls(const cls &); \ + cls &operator=(const cls &); + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyUnknown.h b/other-licenses/7zstub/src/CPP/Common/MyUnknown.h new file mode 100644 index 0000000000..b1d476ffb8 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyUnknown.h @@ -0,0 +1,17 @@ +// MyUnknown.h + +#ifndef __MY_UNKNOWN_H +#define __MY_UNKNOWN_H + +#include "MyWindows.h" + +/* +#ifdef _WIN32 +#include +#include +#else +#include "MyWindows.h" +#endif +*/ + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyVector.cpp b/other-licenses/7zstub/src/CPP/Common/MyVector.cpp new file mode 100644 index 0000000000..9a6d1d5aee --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyVector.cpp @@ -0,0 +1,3 @@ +// Common/MyVector.cpp + +#include "StdAfx.h" diff --git a/other-licenses/7zstub/src/CPP/Common/MyVector.h b/other-licenses/7zstub/src/CPP/Common/MyVector.h new file mode 100644 index 0000000000..21125fa7da --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyVector.h @@ -0,0 +1,634 @@ +// Common/MyVector.h + +#ifndef __COMMON_MY_VECTOR_H +#define __COMMON_MY_VECTOR_H + +#include + +template +class CRecordVector +{ + T *_items; + unsigned _size; + unsigned _capacity; + + void MoveItems(unsigned destIndex, unsigned srcIndex) + { + memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T)); + } + + void ReserveOnePosition() + { + if (_size == _capacity) + { + unsigned newCapacity = _capacity + (_capacity >> 2) + 1; + T *p; + MY_ARRAY_NEW(p, T, newCapacity); + // p = new T[newCapacity]; + if (_size != 0) + memcpy(p, _items, (size_t)_size * sizeof(T)); + delete []_items; + _items = p; + _capacity = newCapacity; + } + } + +public: + + CRecordVector(): _items(0), _size(0), _capacity(0) {} + + CRecordVector(const CRecordVector &v): _items(0), _size(0), _capacity(0) + { + unsigned size = v.Size(); + if (size != 0) + { + _items = new T[size]; + _size = size; + _capacity = size; + memcpy(_items, v._items, (size_t)size * sizeof(T)); + } + } + + unsigned Size() const { return _size; } + bool IsEmpty() const { return _size == 0; } + + void ConstructReserve(unsigned size) + { + if (size != 0) + { + MY_ARRAY_NEW(_items, T, size) + // _items = new T[size]; + _capacity = size; + } + } + + void Reserve(unsigned newCapacity) + { + if (newCapacity > _capacity) + { + T *p; + MY_ARRAY_NEW(p, T, newCapacity); + // p = new T[newCapacity]; + if (_size != 0) + memcpy(p, _items, (size_t)_size * sizeof(T)); + delete []_items; + _items = p; + _capacity = newCapacity; + } + } + + void ClearAndReserve(unsigned newCapacity) + { + Clear(); + if (newCapacity > _capacity) + { + delete []_items; + _items = NULL; + _capacity = 0; + MY_ARRAY_NEW(_items, T, newCapacity) + // _items = new T[newCapacity]; + _capacity = newCapacity; + } + } + + void ClearAndSetSize(unsigned newSize) + { + ClearAndReserve(newSize); + _size = newSize; + } + + void ChangeSize_KeepData(unsigned newSize) + { + if (newSize > _capacity) + { + T *p; + MY_ARRAY_NEW(p, T, newSize) + // p = new T[newSize]; + if (_size != 0) + memcpy(p, _items, (size_t)_size * sizeof(T)); + delete []_items; + _items = p; + _capacity = newSize; + } + _size = newSize; + } + + void ReserveDown() + { + if (_size == _capacity) + return; + T *p = NULL; + if (_size != 0) + { + p = new T[_size]; + memcpy(p, _items, (size_t)_size * sizeof(T)); + } + delete []_items; + _items = p; + _capacity = _size; + } + + ~CRecordVector() { delete []_items; } + + void ClearAndFree() + { + delete []_items; + _items = NULL; + _size = 0; + _capacity = 0; + } + + void Clear() { _size = 0; } + + void DeleteBack() { _size--; } + + void DeleteFrom(unsigned index) + { + // if (index <= _size) + _size = index; + } + + void DeleteFrontal(unsigned num) + { + if (num != 0) + { + MoveItems(0, num); + _size -= num; + } + } + + void Delete(unsigned index) + { + MoveItems(index, index + 1); + _size -= 1; + } + + /* + void Delete(unsigned index, unsigned num) + { + if (num > 0) + { + MoveItems(index, index + num); + _size -= num; + } + } + */ + + CRecordVector& operator=(const CRecordVector &v) + { + if (&v == this) + return *this; + unsigned size = v.Size(); + if (size > _capacity) + { + delete []_items; + _capacity = 0; + _size = 0; + _items = NULL; + _items = new T[size]; + _capacity = size; + } + _size = size; + if (size != 0) + memcpy(_items, v._items, (size_t)size * sizeof(T)); + return *this; + } + + CRecordVector& operator+=(const CRecordVector &v) + { + unsigned size = v.Size(); + Reserve(_size + size); + if (size != 0) + memcpy(_items + _size, v._items, (size_t)size * sizeof(T)); + _size += size; + return *this; + } + + unsigned Add(const T item) + { + ReserveOnePosition(); + _items[_size] = item; + return _size++; + } + + void AddInReserved(const T item) + { + _items[_size++] = item; + } + + void Insert(unsigned index, const T item) + { + ReserveOnePosition(); + MoveItems(index + 1, index); + _items[index] = item; + _size++; + } + + void MoveToFront(unsigned index) + { + if (index != 0) + { + T temp = _items[index]; + memmove(_items + 1, _items, (size_t)index * sizeof(T)); + _items[0] = temp; + } + } + + const T& operator[](unsigned index) const { return _items[index]; } + T& operator[](unsigned index) { return _items[index]; } + const T& Front() const { return _items[0]; } + T& Front() { return _items[0]; } + const T& Back() const { return _items[(size_t)_size - 1]; } + T& Back() { return _items[(size_t)_size - 1]; } + + /* + void Swap(unsigned i, unsigned j) + { + T temp = _items[i]; + _items[i] = _items[j]; + _items[j] = temp; + } + */ + + int FindInSorted(const T item, unsigned left, unsigned right) const + { + while (left != right) + { + unsigned mid = (left + right) / 2; + const T midVal = (*this)[mid]; + if (item == midVal) + return mid; + if (item < midVal) + right = mid; + else + left = mid + 1; + } + return -1; + } + + int FindInSorted2(const T &item, unsigned left, unsigned right) const + { + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + return -1; + } + + int FindInSorted(const T item) const + { + return FindInSorted(item, 0, _size); + } + + int FindInSorted2(const T &item) const + { + return FindInSorted2(item, 0, _size); + } + + unsigned AddToUniqueSorted(const T item) + { + unsigned left = 0, right = _size; + while (left != right) + { + unsigned mid = (left + right) / 2; + const T midVal = (*this)[mid]; + if (item == midVal) + return mid; + if (item < midVal) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + unsigned AddToUniqueSorted2(const T &item) + { + unsigned left = 0, right = _size; + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param) + { + T temp = p[k]; + for (;;) + { + unsigned s = (k << 1); + if (s > size) + break; + if (s < size && compare(p + s + 1, p + s, param) > 0) + s++; + if (compare(&temp, p + s, param) >= 0) + break; + p[k] = p[s]; + k = s; + } + p[k] = temp; + } + + void Sort(int (*compare)(const T*, const T*, void *), void *param) + { + unsigned size = _size; + if (size <= 1) + return; + T* p = (&Front()) - 1; + { + unsigned i = size >> 1; + do + SortRefDown(p, i, size, compare, param); + while (--i != 0); + } + do + { + T temp = p[size]; + p[size--] = p[1]; + p[1] = temp; + SortRefDown(p, 1, size, compare, param); + } + while (size > 1); + } + + static void SortRefDown2(T* p, unsigned k, unsigned size) + { + T temp = p[k]; + for (;;) + { + unsigned s = (k << 1); + if (s > size) + break; + if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0) + s++; + if (temp.Compare(p[s]) >= 0) + break; + p[k] = p[s]; + k = s; + } + p[k] = temp; + } + + void Sort2() + { + unsigned size = _size; + if (size <= 1) + return; + T* p = (&Front()) - 1; + { + unsigned i = size >> 1; + do + SortRefDown2(p, i, size); + while (--i != 0); + } + do + { + T temp = p[size]; + p[size--] = p[1]; + p[1] = temp; + SortRefDown2(p, 1, size); + } + while (size > 1); + } +}; + +typedef CRecordVector CIntVector; +typedef CRecordVector CUIntVector; +typedef CRecordVector CBoolVector; +typedef CRecordVector CByteVector; +typedef CRecordVector CPointerVector; + +template +class CObjectVector +{ + CPointerVector _v; +public: + unsigned Size() const { return _v.Size(); } + bool IsEmpty() const { return _v.IsEmpty(); } + void ReserveDown() { _v.ReserveDown(); } + // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); } + void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); } + + CObjectVector() {}; + CObjectVector(const CObjectVector &v) + { + unsigned size = v.Size(); + _v.ConstructReserve(size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + } + CObjectVector& operator=(const CObjectVector &v) + { + if (&v == this) + return *this; + Clear(); + unsigned size = v.Size(); + _v.Reserve(size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + return *this; + } + + CObjectVector& operator+=(const CObjectVector &v) + { + unsigned size = v.Size(); + _v.Reserve(Size() + size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + return *this; + } + + const T& operator[](unsigned index) const { return *((T *)_v[index]); } + T& operator[](unsigned index) { return *((T *)_v[index]); } + const T& Front() const { return operator[](0); } + T& Front() { return operator[](0); } + const T& Back() const { return *(T *)_v.Back(); } + T& Back() { return *(T *)_v.Back(); } + + void MoveToFront(unsigned index) { _v.MoveToFront(index); } + + unsigned Add(const T& item) { return _v.Add(new T(item)); } + + void AddInReserved(const T& item) { _v.AddInReserved(new T(item)); } + + T& AddNew() + { + T *p = new T; + _v.Add(p); + return *p; + } + + T& AddNewInReserved() + { + T *p = new T; + _v.AddInReserved(p); + return *p; + } + + void Insert(unsigned index, const T& item) { _v.Insert(index, new T(item)); } + + T& InsertNew(unsigned index) + { + T *p = new T; + _v.Insert(index, p); + return *p; + } + + ~CObjectVector() + { + for (unsigned i = _v.Size(); i != 0;) + delete (T *)_v[--i]; + } + + void ClearAndFree() + { + Clear(); + _v.ClearAndFree(); + } + + void Clear() + { + for (unsigned i = _v.Size(); i != 0;) + delete (T *)_v[--i]; + _v.Clear(); + } + + void DeleteFrom(unsigned index) + { + unsigned size = _v.Size(); + for (unsigned i = index; i < size; i++) + delete (T *)_v[i]; + _v.DeleteFrom(index); + } + + void DeleteFrontal(unsigned num) + { + for (unsigned i = 0; i < num; i++) + delete (T *)_v[i]; + _v.DeleteFrontal(num); + } + + void DeleteBack() + { + delete (T *)_v.Back(); + _v.DeleteBack(); + } + + void Delete(unsigned index) + { + delete (T *)_v[index]; + _v.Delete(index); + } + + /* + void Delete(unsigned index, unsigned num) + { + for (unsigned i = 0; i < num; i++) + delete (T *)_v[index + i]; + _v.Delete(index, num); + } + */ + + /* + int Find(const T& item) const + { + unsigned size = Size(); + for (unsigned i = 0; i < size; i++) + if (item == (*this)[i]) + return i; + return -1; + } + */ + + int FindInSorted(const T& item) const + { + unsigned left = 0, right = Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + return -1; + } + + unsigned AddToUniqueSorted(const T& item) + { + unsigned left = 0, right = Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + /* + unsigned AddToSorted(const T& item) + { + unsigned left = 0, right = Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + { + right = mid + 1; + break; + } + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + */ + + void Sort(int (*compare)(void *const *, void *const *, void *), void *param) + { _v.Sort(compare, param); } + + static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) + { return (*(*((const T **)a1))).Compare(*(*((const T **)a2))); } + + void Sort() { _v.Sort(CompareObjectItems, 0); } +}; + +#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++) + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyWindows.cpp b/other-licenses/7zstub/src/CPP/Common/MyWindows.cpp new file mode 100644 index 0000000000..bc9f7be3f5 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyWindows.cpp @@ -0,0 +1,145 @@ +// MyWindows.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 + +#include + +#include "MyWindows.h" + +static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); } +static inline void FreeForBSTR(void *pv) { ::free(pv);} + +/* Win32 uses DWORD (32-bit) type to store size of string before (OLECHAR *) string. + We must select CBstrSizeType for another systems (not Win32): + + if (CBstrSizeType is UINT32), + then we support only strings smaller than 4 GB. + Win32 version always has that limitation. + + if (CBstrSizeType is UINT), + (UINT can be 16/32/64-bit) + We can support strings larger than 4 GB (if UINT is 64-bit), + but sizeof(UINT) can be different in parts compiled by + different compilers/settings, + and we can't send such BSTR strings between such parts. +*/ + +typedef UINT32 CBstrSizeType; +// typedef UINT CBstrSizeType; + +#define k_BstrSize_Max 0xFFFFFFFF +// #define k_BstrSize_Max UINT_MAX +// #define k_BstrSize_Max ((UINT)(INT)-1) + +BSTR SysAllocStringByteLen(LPCSTR s, UINT len) +{ + /* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end. + We provide also aligned null OLECHAR at the end. */ + + if (len >= (k_BstrSize_Max - sizeof(OLECHAR) - sizeof(OLECHAR) - sizeof(CBstrSizeType))) + return NULL; + + UINT size = (len + sizeof(OLECHAR) + sizeof(OLECHAR) - 1) & ~(sizeof(OLECHAR) - 1); + void *p = AllocateForBSTR(size + sizeof(CBstrSizeType)); + if (!p) + return NULL; + *(CBstrSizeType *)p = (CBstrSizeType)len; + BSTR bstr = (BSTR)((CBstrSizeType *)p + 1); + if (s) + memcpy(bstr, s, len); + for (; len < size; len++) + ((Byte *)bstr)[len] = 0; + return bstr; +} + +BSTR SysAllocStringLen(const OLECHAR *s, UINT len) +{ + if (len >= (k_BstrSize_Max - sizeof(OLECHAR) - sizeof(CBstrSizeType)) / sizeof(OLECHAR)) + return NULL; + + UINT size = len * sizeof(OLECHAR); + void *p = AllocateForBSTR(size + sizeof(CBstrSizeType) + sizeof(OLECHAR)); + if (!p) + return NULL; + *(CBstrSizeType *)p = (CBstrSizeType)size; + BSTR bstr = (BSTR)((CBstrSizeType *)p + 1); + if (s) + memcpy(bstr, s, size); + bstr[len] = 0; + return bstr; +} + +BSTR SysAllocString(const OLECHAR *s) +{ + if (!s) + return 0; + const OLECHAR *s2 = s; + while (*s2 != 0) + s2++; + return SysAllocStringLen(s, (UINT)(s2 - s)); +} + +void SysFreeString(BSTR bstr) +{ + if (bstr) + FreeForBSTR((CBstrSizeType *)bstr - 1); +} + +UINT SysStringByteLen(BSTR bstr) +{ + if (!bstr) + return 0; + return *((CBstrSizeType *)bstr - 1); +} + +UINT SysStringLen(BSTR bstr) +{ + if (!bstr) + return 0; + return *((CBstrSizeType *)bstr - 1) / sizeof(OLECHAR); +} + + +HRESULT VariantClear(VARIANTARG *prop) +{ + if (prop->vt == VT_BSTR) + SysFreeString(prop->bstrVal); + prop->vt = VT_EMPTY; + return S_OK; +} + +HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src) +{ + HRESULT res = ::VariantClear(dest); + if (res != S_OK) + return res; + if (src->vt == VT_BSTR) + { + dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal, + SysStringByteLen(src->bstrVal)); + if (!dest->bstrVal) + return E_OUTOFMEMORY; + dest->vt = VT_BSTR; + } + else + *dest = *src; + return S_OK; +} + +LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2) +{ + if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1; + if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1; + if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1; + if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1; + return 0; +} + +DWORD GetLastError() +{ + return 0; +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/MyWindows.h b/other-licenses/7zstub/src/CPP/Common/MyWindows.h new file mode 100644 index 0000000000..cc78478150 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/MyWindows.h @@ -0,0 +1,231 @@ +// MyWindows.h + +#ifndef __MY_WINDOWS_H +#define __MY_WINDOWS_H + +#ifdef _WIN32 + +#include + +#ifdef UNDER_CE + #undef VARIANT_TRUE + #define VARIANT_TRUE ((VARIANT_BOOL)-1) +#endif + +#else + +#include // for wchar_t +#include +// #include // for uintptr_t + +#include "MyGuidDef.h" + +#define WINAPI + +typedef char CHAR; +typedef unsigned char UCHAR; + +#undef BYTE +typedef unsigned char BYTE; + +typedef short SHORT; +typedef unsigned short USHORT; + +#undef WORD +typedef unsigned short WORD; +typedef short VARIANT_BOOL; + +typedef int INT; +typedef Int32 INT32; +typedef unsigned int UINT; +typedef UInt32 UINT32; +typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit +typedef UINT32 ULONG; + +#undef DWORD +typedef UINT32 DWORD; + +typedef long BOOL; + +#ifndef FALSE + #define FALSE 0 + #define TRUE 1 +#endif + +// typedef size_t ULONG_PTR; +typedef size_t DWORD_PTR; +// typedef uintptr_t UINT_PTR; +// typedef ptrdiff_t UINT_PTR; + +typedef Int64 LONGLONG; +typedef UInt64 ULONGLONG; + +typedef struct _LARGE_INTEGER { LONGLONG QuadPart; } LARGE_INTEGER; +typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart; } ULARGE_INTEGER; + +typedef const CHAR *LPCSTR; +typedef CHAR TCHAR; +typedef const TCHAR *LPCTSTR; +typedef wchar_t WCHAR; +typedef WCHAR OLECHAR; +typedef const WCHAR *LPCWSTR; +typedef OLECHAR *BSTR; +typedef const OLECHAR *LPCOLESTR; +typedef OLECHAR *LPOLESTR; + +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME; + +#define HRESULT LONG +#define FAILED(Status) ((HRESULT)(Status)<0) +typedef ULONG PROPID; +typedef LONG SCODE; + +#define ERROR_NEGATIVE_SEEK 131L + +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) +#define E_NOTIMPL ((HRESULT)0x80004001L) +#define E_NOINTERFACE ((HRESULT)0x80004002L) +#define E_ABORT ((HRESULT)0x80004004L) +#define E_FAIL ((HRESULT)0x80004005L) +#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) +#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) +#define E_INVALIDARG ((HRESULT)0x80070057L) + +#ifdef _MSC_VER +#define STDMETHODCALLTYPE __stdcall +#else +#define STDMETHODCALLTYPE +#endif + +#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f +#define STDMETHOD(f) STDMETHOD_(HRESULT, f) +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE +#define STDMETHODIMP STDMETHODIMP_(HRESULT) + +#define PURE = 0 + +#define MIDL_INTERFACE(x) struct + +#ifdef __cplusplus + +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +struct IUnknown +{ + STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; + STDMETHOD_(ULONG, AddRef)() PURE; + STDMETHOD_(ULONG, Release)() PURE; + #ifndef _WIN32 + virtual ~IUnknown() {} + #endif +}; + +typedef IUnknown *LPUNKNOWN; + +#endif + +#define VARIANT_TRUE ((VARIANT_BOOL)-1) +#define VARIANT_FALSE ((VARIANT_BOOL)0) + +enum VARENUM +{ + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_FILETIME = 64 +}; + +typedef unsigned short VARTYPE; +typedef WORD PROPVAR_PAD1; +typedef WORD PROPVAR_PAD2; +typedef WORD PROPVAR_PAD3; + +typedef struct tagPROPVARIANT +{ + VARTYPE vt; + PROPVAR_PAD1 wReserved1; + PROPVAR_PAD2 wReserved2; + PROPVAR_PAD3 wReserved3; + union + { + CHAR cVal; + UCHAR bVal; + SHORT iVal; + USHORT uiVal; + LONG lVal; + ULONG ulVal; + INT intVal; + UINT uintVal; + LARGE_INTEGER hVal; + ULARGE_INTEGER uhVal; + VARIANT_BOOL boolVal; + SCODE scode; + FILETIME filetime; + BSTR bstrVal; + }; +} PROPVARIANT; + +typedef PROPVARIANT tagVARIANT; +typedef tagVARIANT VARIANT; +typedef VARIANT VARIANTARG; + +MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); +MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src); + +typedef struct tagSTATPROPSTG +{ + LPOLESTR lpwstrName; + PROPID propid; + VARTYPE vt; +} STATPROPSTG; + +MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); +MY_EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len); +MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); +MY_EXTERN_C void SysFreeString(BSTR bstr); +MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); +MY_EXTERN_C UINT SysStringLen(BSTR bstr); + +MY_EXTERN_C DWORD GetLastError(); +MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); + +#define CP_ACP 0 +#define CP_OEMCP 1 +#define CP_UTF8 65001 + +typedef enum tagSTREAM_SEEK +{ + STREAM_SEEK_SET = 0, + STREAM_SEEK_CUR = 1, + STREAM_SEEK_END = 2 +} STREAM_SEEK; + +#endif +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/NewHandler.cpp b/other-licenses/7zstub/src/CPP/Common/NewHandler.cpp new file mode 100644 index 0000000000..18d2d1865b --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/NewHandler.cpp @@ -0,0 +1,163 @@ +// NewHandler.cpp + +#include "StdAfx.h" + +#include + +#include "NewHandler.h" + +// #define DEBUG_MEMORY_LEAK + +#ifndef DEBUG_MEMORY_LEAK + +#ifdef _7ZIP_REDEFINE_OPERATOR_NEW + +/* +void * my_new(size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void my_delete(void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} + +void * my_Realloc(void *p, size_t newSize, size_t oldSize) +{ + void *newBuf = my_new(newSize); + if (oldSize != 0) + memcpy(newBuf, p, oldSize); + my_delete(p); + return newBuf; +} +*/ + +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new(size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} + +/* +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new[](size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete[](void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} +*/ + +#endif + +#else + +#include + +// #pragma init_seg(lib) +const int kDebugSize = 1000000; +static void *a[kDebugSize]; +static int index = 0; + +static int numAllocs = 0; +void * __cdecl operator new(size_t size) +{ + numAllocs++; + void *p = HeapAlloc(GetProcessHeap(), 0, size); + if (index < kDebugSize) + { + a[index] = p; + index++; + } + if (p == 0) + throw CNewException(); + printf("Alloc %6d, size = %8u\n", numAllocs, (unsigned)size); + return p; +} + +class CC +{ +public: + CC() + { + for (int i = 0; i < kDebugSize; i++) + a[i] = 0; + } + ~CC() + { + for (int i = 0; i < kDebugSize; i++) + if (a[i] != 0) + return; + } +} g_CC; + + +void __cdecl operator delete(void *p) +{ + if (p == 0) + return; + /* + for (int i = 0; i < index; i++) + if (a[i] == p) + a[i] = 0; + */ + HeapFree(GetProcessHeap(), 0, p); + numAllocs--; + printf("Free %d\n", numAllocs); +} + +#endif + +/* +int MemErrorVC(size_t) +{ + throw CNewException(); + // return 1; +} +CNewHandlerSetter::CNewHandlerSetter() +{ + // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); +} +CNewHandlerSetter::~CNewHandlerSetter() +{ + // _set_new_handler(MemErrorOldVCFunction); +} +*/ diff --git a/other-licenses/7zstub/src/CPP/Common/NewHandler.h b/other-licenses/7zstub/src/CPP/Common/NewHandler.h new file mode 100644 index 0000000000..9d20ee1347 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/NewHandler.h @@ -0,0 +1,88 @@ +// Common/NewHandler.h + +#ifndef __COMMON_NEW_HANDLER_H +#define __COMMON_NEW_HANDLER_H + +/* +NewHandler.h and NewHandler.cpp allows to solve problem with compilers that +don't throw exception in operator new(). + +This file must be included before any code that uses operators new() or delete() +and you must compile and link "NewHandler.cpp", if you use some old MSVC compiler. + +The operator new() in some MSVC versions doesn't throw exception std::bad_alloc. +MSVC 6.0 (_MSC_VER == 1200) doesn't throw exception. +The code produced by some another MSVC compilers also can be linked +to library that doesn't throw exception. +We suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc. +For older _MSC_VER versions we redefine operator new() and operator delete(). +Our version of operator new() throws CNewException() exception on failure. + +It's still allowed to use redefined version of operator new() from "NewHandler.cpp" +with any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions. +But if you use some additional code (outside of 7-Zip's code), you must check +that redefined version of operator new() is not problem for your code. +*/ + +#include + +#ifdef _WIN32 +// We can compile my_new and my_delete with _fastcall +/* +void * my_new(size_t size); +void my_delete(void *p) throw(); +// void * my_Realloc(void *p, size_t newSize, size_t oldSize); +*/ +#endif + + +#if defined(_MSC_VER) && (_MSC_VER < 1900) + // If you want to use default operator new(), you can disable the following line + #define _7ZIP_REDEFINE_OPERATOR_NEW +#endif + + +#ifdef _7ZIP_REDEFINE_OPERATOR_NEW + +// std::bad_alloc can require additional DLL dependency. +// So we don't define CNewException as std::bad_alloc here. + +class CNewException {}; + +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new(size_t size); + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw(); + +#else + +#include + +#define CNewException std::bad_alloc + +#endif + +/* +#ifdef _WIN32 +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new[](size_t size); + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete[](void *p) throw(); +#endif +*/ + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/Sha256Reg.cpp b/other-licenses/7zstub/src/CPP/Common/Sha256Reg.cpp new file mode 100644 index 0000000000..14a3652377 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/Sha256Reg.cpp @@ -0,0 +1,40 @@ +// Sha256Reg.cpp + +#include "StdAfx.h" + +#include "../../C/Sha256.h" + +#include "../Common/MyCom.h" + +#include "../7zip/Common/RegisterCodec.h" + +class CSha256Hasher: + public IHasher, + public CMyUnknownImp +{ + CSha256 _sha; + Byte mtDummy[1 << 7]; + +public: + CSha256Hasher() { Sha256_Init(&_sha); } + + MY_UNKNOWN_IMP1(IHasher) + INTERFACE_IHasher(;) +}; + +STDMETHODIMP_(void) CSha256Hasher::Init() throw() +{ + Sha256_Init(&_sha); +} + +STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size) throw() +{ + Sha256_Update(&_sha, (const Byte *)data, size); +} + +STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest) throw() +{ + Sha256_Final(&_sha, digest); +} + +REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE) diff --git a/other-licenses/7zstub/src/CPP/Common/StdAfx.h b/other-licenses/7zstub/src/CPP/Common/StdAfx.h new file mode 100644 index 0000000000..3f1890a278 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "Common.h" + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/StdInStream.cpp b/other-licenses/7zstub/src/CPP/Common/StdInStream.cpp new file mode 100644 index 0000000000..f547b54fb5 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StdInStream.cpp @@ -0,0 +1,89 @@ +// Common/StdInStream.cpp + +#include "StdAfx.h" + +#include + +#include "StdInStream.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +// #define kEOFMessage "Unexpected end of input stream" +// #define kReadErrorMessage "Error reading input stream" +// #define kIllegalCharMessage "Illegal zero character in input stream" + +#define kFileOpenMode TEXT("r") + +extern int g_CodePage; + +CStdInStream g_StdIn(stdin); + +bool CStdInStream::Open(LPCTSTR fileName) throw() +{ + Close(); + _stream = _tfopen(fileName, kFileOpenMode); + _streamIsOpen = (_stream != 0); + return _streamIsOpen; +} + +bool CStdInStream::Close() throw() +{ + if (!_streamIsOpen) + return true; + _streamIsOpen = (fclose(_stream) != 0); + return !_streamIsOpen; +} + +bool CStdInStream::ScanAStringUntilNewLine(AString &s) +{ + s.Empty(); + for (;;) + { + int intChar = GetChar(); + if (intChar == EOF) + return true; + char c = (char)intChar; + if (c == 0) + return false; + if (c == '\n') + return true; + s += c; + } +} + +bool CStdInStream::ScanUStringUntilNewLine(UString &dest) +{ + dest.Empty(); + AString s; + bool res = ScanAStringUntilNewLine(s); + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUTF8ToUnicode(s, dest); + else + MultiByteToUnicodeString2(dest, s, (UINT)codePage); + return res; +} + +/* +bool CStdInStream::ReadToString(AString &resultString) +{ + resultString.Empty(); + for (;;) + { + int intChar = GetChar(); + if (intChar == EOF) + return !Error(); + char c = (char)intChar; + if (c == 0) + return false; + resultString += c; + } +} +*/ + +int CStdInStream::GetChar() +{ + return fgetc(_stream); // getc() doesn't work in BeOS? +} diff --git a/other-licenses/7zstub/src/CPP/Common/StdInStream.h b/other-licenses/7zstub/src/CPP/Common/StdInStream.h new file mode 100644 index 0000000000..20f9ce3436 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StdInStream.h @@ -0,0 +1,38 @@ +// Common/StdInStream.h + +#ifndef __COMMON_STD_IN_STREAM_H +#define __COMMON_STD_IN_STREAM_H + +#include + +#include "MyString.h" +#include "MyTypes.h" + +class CStdInStream +{ + FILE *_stream; + bool _streamIsOpen; +public: + CStdInStream(): _stream(0), _streamIsOpen(false) {}; + CStdInStream(FILE *stream): _stream(stream), _streamIsOpen(false) {}; + ~CStdInStream() { Close(); } + + bool Open(LPCTSTR fileName) throw(); + bool Close() throw(); + + // returns: + // false, if ZERO character in stream + // true, if EOF or '\n' + bool ScanAStringUntilNewLine(AString &s); + bool ScanUStringUntilNewLine(UString &s); + // bool ReadToString(AString &resultString); + + bool Eof() const throw() { return (feof(_stream) != 0); } + bool Error() const throw() { return (ferror(_stream) != 0); } + + int GetChar(); +}; + +extern CStdInStream g_StdIn; + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/StdOutStream.cpp b/other-licenses/7zstub/src/CPP/Common/StdOutStream.cpp new file mode 100644 index 0000000000..dc6d4bd4a9 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StdOutStream.cpp @@ -0,0 +1,163 @@ +// Common/StdOutStream.cpp + +#include "StdAfx.h" + +#include + +#include "IntToString.h" +#include "StdOutStream.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +#define kFileOpenMode "wt" + +extern int g_CodePage; + +CStdOutStream g_StdOut(stdout); +CStdOutStream g_StdErr(stderr); + +bool CStdOutStream::Open(const char *fileName) throw() +{ + Close(); + _stream = fopen(fileName, kFileOpenMode); + _streamIsOpen = (_stream != 0); + return _streamIsOpen; +} + +bool CStdOutStream::Close() throw() +{ + if (!_streamIsOpen) + return true; + if (fclose(_stream) != 0) + return false; + _stream = 0; + _streamIsOpen = false; + return true; +} + +bool CStdOutStream::Flush() throw() +{ + return (fflush(_stream) == 0); +} + +CStdOutStream & endl(CStdOutStream & outStream) throw() +{ + return outStream << '\n'; +} + +CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) +{ + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + AString dest; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, dest); + else + UnicodeStringToMultiByte2(dest, s, (UINT)codePage); + return operator<<((const char *)dest); +} + +void StdOut_Convert_UString_to_AString(const UString &s, AString &temp) +{ + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); +} + +void CStdOutStream::PrintUString(const UString &s, AString &temp) +{ + StdOut_Convert_UString_to_AString(s, temp); + *this << (const char *)temp; +} + + +static const wchar_t kReplaceChar = '_'; + +void CStdOutStream::Normalize_UString__LF_Allowed(UString &s) +{ + unsigned len = s.Len(); + wchar_t *d = s.GetBuf(); + + if (IsTerminalMode) + for (unsigned i = 0; i < len; i++) + { + wchar_t c = d[i]; + if (c <= 13 && c >= 7 && c != '\n') + d[i] = kReplaceChar; + } +} + +void CStdOutStream::Normalize_UString(UString &s) +{ + unsigned len = s.Len(); + wchar_t *d = s.GetBuf(); + + if (IsTerminalMode) + for (unsigned i = 0; i < len; i++) + { + wchar_t c = d[i]; + if (c <= 13 && c >= 7) + d[i] = kReplaceChar; + } + else + for (unsigned i = 0; i < len; i++) + { + wchar_t c = d[i]; + if (c == '\n') + d[i] = kReplaceChar; + } +} + +void CStdOutStream::NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA) +{ + tempU = s; + Normalize_UString(tempU); + PrintUString(tempU, tempA); +} + +void CStdOutStream::NormalizePrint_UString(const UString &s) +{ + NormalizePrint_wstr(s); +} + +void CStdOutStream::NormalizePrint_wstr(const wchar_t *s) +{ + UString tempU = s; + Normalize_UString(tempU); + AString tempA; + PrintUString(tempU, tempA); +} + + +CStdOutStream & CStdOutStream::operator<<(Int32 number) throw() +{ + char s[32]; + ConvertInt64ToString(number, s); + return operator<<(s); +} + +CStdOutStream & CStdOutStream::operator<<(Int64 number) throw() +{ + char s[32]; + ConvertInt64ToString(number, s); + return operator<<(s); +} + +CStdOutStream & CStdOutStream::operator<<(UInt32 number) throw() +{ + char s[16]; + ConvertUInt32ToString(number, s); + return operator<<(s); +} + +CStdOutStream & CStdOutStream::operator<<(UInt64 number) throw() +{ + char s[32]; + ConvertUInt64ToString(number, s); + return operator<<(s); +} diff --git a/other-licenses/7zstub/src/CPP/Common/StdOutStream.h b/other-licenses/7zstub/src/CPP/Common/StdOutStream.h new file mode 100644 index 0000000000..475954c069 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StdOutStream.h @@ -0,0 +1,71 @@ +// Common/StdOutStream.h + +#ifndef __COMMON_STD_OUT_STREAM_H +#define __COMMON_STD_OUT_STREAM_H + +#include + +#include "MyString.h" +#include "MyTypes.h" + +class CStdOutStream +{ + FILE *_stream; + bool _streamIsOpen; +public: + bool IsTerminalMode; + + CStdOutStream(): _stream(0), _streamIsOpen(false), IsTerminalMode(false) {}; + CStdOutStream(FILE *stream): _stream(stream), _streamIsOpen(false) {}; + ~CStdOutStream() { Close(); } + + // void AttachStdStream(FILE *stream) { _stream = stream; _streamIsOpen = false; } + // bool IsDefined() const { return _stream != NULL; } + + operator FILE *() { return _stream; } + bool Open(const char *fileName) throw(); + bool Close() throw(); + bool Flush() throw(); + + CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream &)) + { + (*func)(*this); + return *this; + } + + CStdOutStream & operator<<(const char *s) throw() + { + fputs(s, _stream); + return *this; + } + + CStdOutStream & operator<<(char c) throw() + { + fputc((unsigned char)c, _stream); + return *this; + } + + CStdOutStream & operator<<(Int32 number) throw(); + CStdOutStream & operator<<(Int64 number) throw(); + CStdOutStream & operator<<(UInt32 number) throw(); + CStdOutStream & operator<<(UInt64 number) throw(); + + CStdOutStream & operator<<(const wchar_t *s); + void PrintUString(const UString &s, AString &temp); + + void Normalize_UString__LF_Allowed(UString &s); + void Normalize_UString(UString &s); + + void NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA); + void NormalizePrint_UString(const UString &s); + void NormalizePrint_wstr(const wchar_t *s); +}; + +CStdOutStream & endl(CStdOutStream & outStream) throw(); + +extern CStdOutStream g_StdOut; +extern CStdOutStream g_StdErr; + +void StdOut_Convert_UString_to_AString(const UString &s, AString &temp); + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/StringConvert.cpp b/other-licenses/7zstub/src/CPP/Common/StringConvert.cpp new file mode 100644 index 0000000000..b8f33cd63a --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StringConvert.cpp @@ -0,0 +1,319 @@ +// Common/StringConvert.cpp + +#include "StdAfx.h" + +#include "StringConvert.h" + +#ifndef _WIN32 +#include +#endif + +static const char k_DefultChar = '_'; + +#ifdef _WIN32 + +/* +MultiByteToWideChar(CodePage, DWORD dwFlags, + LPCSTR lpMultiByteStr, int cbMultiByte, + LPWSTR lpWideCharStr, int cchWideChar) + + if (cbMultiByte == 0) + return: 0. ERR: ERROR_INVALID_PARAMETER + + if (cchWideChar == 0) + return: the required buffer size in characters. + + if (supplied buffer size was not large enough) + return: 0. ERR: ERROR_INSUFFICIENT_BUFFER + The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex) + + If there are illegal characters: + if MB_ERR_INVALID_CHARS is set in dwFlags: + - the function stops conversion on illegal character. + - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION. + + if MB_ERR_INVALID_CHARS is NOT set in dwFlags: + before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0. + in Vista+: illegal character is not dropped (MSDN). Undocumented: illegal + character is converted to U+FFFD, which is REPLACEMENT CHARACTER. +*/ + + +void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) +{ + dest.Empty(); + if (src.IsEmpty()) + return; + { + /* + wchar_t *d = dest.GetBuf(src.Len()); + const char *s = (const char *)src; + unsigned i; + + for (i = 0;;) + { + Byte c = (Byte)s[i]; + if (c >= 0x80 || c == 0) + break; + d[i++] = (wchar_t)c; + } + + if (i != src.Len()) + { + unsigned len = MultiByteToWideChar(codePage, 0, s + i, + src.Len() - i, d + i, + src.Len() + 1 - i); + if (len == 0) + throw 282228; + i += len; + } + + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + */ + unsigned len = MultiByteToWideChar(codePage, 0, src, src.Len(), NULL, 0); + if (len == 0) + { + if (GetLastError() != 0) + throw 282228; + } + else + { + len = MultiByteToWideChar(codePage, 0, src, src.Len(), dest.GetBuf(len), len); + if (len == 0) + throw 282228; + dest.ReleaseBuf_SetEnd(len); + } + } +} + +/* + int WideCharToMultiByte( + UINT CodePage, DWORD dwFlags, + LPCWSTR lpWideCharStr, int cchWideChar, + LPSTR lpMultiByteStr, int cbMultiByte, + LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); + +if (lpDefaultChar == NULL), + - it uses system default value. + +if (CodePage == CP_UTF7 || CodePage == CP_UTF8) + if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL) + return: 0. ERR: ERROR_INVALID_PARAMETER. + +The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL) + +*/ + +static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + dest.Empty(); + defaultCharWasUsed = false; + if (src.IsEmpty()) + return; + { + /* + unsigned numRequiredBytes = src.Len() * 2; + char *d = dest.GetBuf(numRequiredBytes); + const wchar_t *s = (const wchar_t *)src; + unsigned i; + + for (i = 0;;) + { + wchar_t c = s[i]; + if (c >= 0x80 || c == 0) + break; + d[i++] = (char)c; + } + + if (i != src.Len()) + { + BOOL defUsed = FALSE; + defaultChar = defaultChar; + + bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); + unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i, + d + i, numRequiredBytes + 1 - i, + (isUtf ? NULL : &defaultChar), + (isUtf ? NULL : &defUsed)); + defaultCharWasUsed = (defUsed != FALSE); + if (len == 0) + throw 282229; + i += len; + } + + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + */ + + /* + if (codePage != CP_UTF7) + { + const wchar_t *s = (const wchar_t *)src; + unsigned i; + for (i = 0;; i++) + { + wchar_t c = s[i]; + if (c >= 0x80 || c == 0) + break; + } + + if (s[i] == 0) + { + char *d = dest.GetBuf(src.Len()); + for (i = 0;;) + { + wchar_t c = s[i]; + if (c == 0) + break; + d[i++] = (char)c; + } + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + return; + } + } + */ + + unsigned len = WideCharToMultiByte(codePage, 0, src, src.Len(), NULL, 0, NULL, NULL); + if (len == 0) + { + if (GetLastError() != 0) + throw 282228; + } + else + { + BOOL defUsed = FALSE; + bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); + // defaultChar = defaultChar; + len = WideCharToMultiByte(codePage, 0, src, src.Len(), + dest.GetBuf(len), len, + (isUtf ? NULL : &defaultChar), + (isUtf ? NULL : &defUsed) + ); + if (!isUtf) + defaultCharWasUsed = (defUsed != FALSE); + if (len == 0) + throw 282228; + dest.ReleaseBuf_SetEnd(len); + } + } +} + +/* +#ifndef UNDER_CE +AString SystemStringToOemString(const CSysString &src) +{ + AString dest; + const unsigned len = src.Len() * 2; + CharToOem(src, dest.GetBuf(len)); + dest.ReleaseBuf_CalcLen(len); + return dest; +} +#endif +*/ + +#else + +void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT /* codePage */) +{ + dest.Empty(); + if (src.IsEmpty()) + return; + + size_t limit = ((size_t)src.Len() + 1) * 2; + wchar_t *d = dest.GetBuf((unsigned)limit); + size_t len = mbstowcs(d, src, limit); + if (len != (size_t)-1) + { + dest.ReleaseBuf_SetEnd((unsigned)len); + return; + } + + { + unsigned i; + const char *s = (const char *)src; + for (i = 0;;) + { + Byte c = (Byte)s[i]; + if (c == 0) + break; + d[i++] = (wchar_t)c; + } + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + } +} + +static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT /* codePage */, char defaultChar, bool &defaultCharWasUsed) +{ + dest.Empty(); + defaultCharWasUsed = false; + if (src.IsEmpty()) + return; + + size_t limit = ((size_t)src.Len() + 1) * 6; + char *d = dest.GetBuf((unsigned)limit); + size_t len = wcstombs(d, src, limit); + if (len != (size_t)-1) + { + dest.ReleaseBuf_SetEnd((unsigned)len); + return; + } + + { + const wchar_t *s = (const wchar_t *)src; + unsigned i; + for (i = 0;;) + { + wchar_t c = s[i]; + if (c == 0) + break; + if (c >= 0x100) + { + c = defaultChar; + defaultCharWasUsed = true; + } + d[i++] = (char)c; + } + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + } +} + +#endif + + +UString MultiByteToUnicodeString(const AString &src, UINT codePage) +{ + UString dest; + MultiByteToUnicodeString2(dest, src, codePage); + return dest; +} + +UString MultiByteToUnicodeString(const char *src, UINT codePage) +{ + return MultiByteToUnicodeString(AString(src), codePage); +} + + +void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage) +{ + bool defaultCharWasUsed; + UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); +} + +AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + AString dest; + UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed); + return dest; +} + +AString UnicodeStringToMultiByte(const UString &src, UINT codePage) +{ + AString dest; + bool defaultCharWasUsed; + UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); + return dest; +} diff --git a/other-licenses/7zstub/src/CPP/Common/StringConvert.h b/other-licenses/7zstub/src/CPP/Common/StringConvert.h new file mode 100644 index 0000000000..05a21556d4 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StringConvert.h @@ -0,0 +1,88 @@ +// Common/StringConvert.h + +#ifndef __COMMON_STRING_CONVERT_H +#define __COMMON_STRING_CONVERT_H + +#include "MyString.h" +#include "MyWindows.h" + +UString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP); +UString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP); + +// optimized versions that work faster for ASCII strings +void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP); +// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed); +void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage); + +AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed); +AString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP); + +inline const wchar_t* GetUnicodeString(const wchar_t *u) { return u; } +inline const UString& GetUnicodeString(const UString &u) { return u; } + +inline UString GetUnicodeString(const AString &a) { return MultiByteToUnicodeString(a); } +inline UString GetUnicodeString(const char *a) { return MultiByteToUnicodeString(a); } + +inline UString GetUnicodeString(const AString &a, UINT codePage) + { return MultiByteToUnicodeString(a, codePage); } +inline UString GetUnicodeString(const char *a, UINT codePage) + { return MultiByteToUnicodeString(a, codePage); } + +inline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; } +inline const UString& GetUnicodeString(const UString &u, UINT) { return u; } + +inline const char* GetAnsiString(const char *a) { return a; } +inline const AString& GetAnsiString(const AString &a) { return a; } + +inline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); } +inline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); } + +/* +inline const char* GetOemString(const char* oem) + { return oem; } +inline const AString& GetOemString(const AString &oem) + { return oem; } +*/ +const char* GetOemString(const char* oem); +const AString& GetOemString(const AString &oem); +inline AString GetOemString(const UString &u) + { return UnicodeStringToMultiByte(u, CP_OEMCP); } + +#ifdef _UNICODE + inline const wchar_t* GetSystemString(const wchar_t *u) { return u;} + inline const UString& GetSystemString(const UString &u) { return u;} + inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;} + inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;} + + inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } + inline UString GetSystemString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } + inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); } + inline UString GetSystemString(const char *a) { return MultiByteToUnicodeString(a); } +#else + inline const char* GetSystemString(const char *a) { return a; } + inline const AString& GetSystemString(const AString &a) { return a; } + inline const char* GetSystemString(const char *a, UINT) { return a; } + inline const AString& GetSystemString(const AString &a, UINT) { return a; } + + inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); } + inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); } + inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); } + + + + /* + inline AString GetSystemString(const wchar_t *u) + { + UString s; + s = u; + return UnicodeStringToMultiByte(s); + } + */ + +#endif + +#ifndef UNDER_CE +AString SystemStringToOemString(const CSysString &src); +#endif + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/StringToInt.cpp b/other-licenses/7zstub/src/CPP/Common/StringToInt.cpp new file mode 100644 index 0000000000..295816e16f --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StringToInt.cpp @@ -0,0 +1,144 @@ +// Common/StringToInt.cpp + +#include "StdAfx.h" + +#include "StringToInt.h" + +static const UInt32 k_UInt32_max = 0xFFFFFFFF; +static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF); +// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1; + +#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \ + uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ + if (end) *end = s; \ + uintType res = 0; \ + for (;; s++) { \ + charTypeUnsigned c = (charTypeUnsigned)*s; \ + if (c < '0' || c > '9') { if (end) *end = s; return res; } \ + if (res > (k_ ## uintType ## _max) / 10) return 0; \ + res *= 10; \ + unsigned v = (c - '0'); \ + if (res > (k_ ## uintType ## _max) - v) return 0; \ + res += v; }} + +CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte) +CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t) +CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte) +CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t) + +Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() +{ + if (end) + *end = s; + const wchar_t *s2 = s; + if (*s == '-') + s2++; + if (*s2 == 0) + return 0; + const wchar_t *end2; + UInt32 res = ConvertStringToUInt32(s2, &end2); + if (*s == '-') + { + if (res > ((UInt32)1 << (32 - 1))) + return 0; + } + else if ((res & ((UInt32)1 << (32 - 1))) != 0) + return 0; + if (end) + *end = end2; + if (*s == '-') + return -(Int32)res; + return (Int32)res; +} + +UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw() +{ + if (end) + *end = s; + UInt32 res = 0; + for (;; s++) + { + unsigned c = (unsigned char)*s; + if (c < '0' || c > '7') + { + if (end) + *end = s; + return res; + } + if ((res & (UInt32)7 << (32 - 3)) != 0) + return 0; + res <<= 3; + res |= (unsigned)(c - '0'); + } +} + +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw() +{ + if (end) + *end = s; + UInt64 res = 0; + for (;; s++) + { + unsigned c = (unsigned char)*s; + if (c < '0' || c > '7') + { + if (end) + *end = s; + return res; + } + if ((res & (UInt64)7 << (64 - 3)) != 0) + return 0; + res <<= 3; + res |= (unsigned)(c - '0'); + } +} + +UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw() +{ + if (end) + *end = s; + UInt32 res = 0; + for (;; s++) + { + unsigned c = (Byte)*s; + unsigned v; + if (c >= '0' && c <= '9') v = (c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); + else + { + if (end) + *end = s; + return res; + } + if ((res & (UInt32)0xF << (32 - 4)) != 0) + return 0; + res <<= 4; + res |= v; + } +} + +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw() +{ + if (end) + *end = s; + UInt64 res = 0; + for (;; s++) + { + unsigned c = (Byte)*s; + unsigned v; + if (c >= '0' && c <= '9') v = (c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); + else + { + if (end) + *end = s; + return res; + } + if ((res & (UInt64)0xF << (64 - 4)) != 0) + return 0; + res <<= 4; + res |= v; + } +} diff --git a/other-licenses/7zstub/src/CPP/Common/StringToInt.h b/other-licenses/7zstub/src/CPP/Common/StringToInt.h new file mode 100644 index 0000000000..140d1ee2dd --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/StringToInt.h @@ -0,0 +1,21 @@ +// Common/StringToInt.h + +#ifndef __COMMON_STRING_TO_INT_H +#define __COMMON_STRING_TO_INT_H + +#include "MyTypes.h" + +UInt32 ConvertStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertStringToUInt64(const char *s, const char **end) throw(); +UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw(); +UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw(); + +Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw(); + +UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw(); + +UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw(); + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/TextConfig.cpp b/other-licenses/7zstub/src/CPP/Common/TextConfig.cpp new file mode 100644 index 0000000000..f54aa3f6d4 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/TextConfig.cpp @@ -0,0 +1,124 @@ +// Common/TextConfig.cpp + +#include "StdAfx.h" + +#include "TextConfig.h" +#include "UTFConvert.h" + +static inline bool IsDelimitChar(char c) +{ + return (c == ' ' || c == 0x0A || c == 0x0D || c == '\0' || c == '\t'); +} + +static AString GetIDString(const char *s, unsigned &finishPos) +{ + AString result; + for (finishPos = 0; ; finishPos++) + { + char c = s[finishPos]; + if (IsDelimitChar(c) || c == '=') + break; + result += c; + } + return result; +} + +static bool WaitNextLine(const AString &s, unsigned &pos) +{ + for (; pos < s.Len(); pos++) + if (s[pos] == 0x0A) + return true; + return false; +} + +static bool SkipSpaces(const AString &s, unsigned &pos) +{ + for (; pos < s.Len(); pos++) + { + char c = s[pos]; + if (!IsDelimitChar(c)) + { + if (c != ';') + return true; + if (!WaitNextLine(s, pos)) + return false; + } + } + return false; +} + +bool GetTextConfig(const AString &s, CObjectVector &pairs) +{ + pairs.Clear(); + unsigned pos = 0; + + ///////////////////// + // read strings + + for (;;) + { + if (!SkipSpaces(s, pos)) + break; + CTextConfigPair pair; + unsigned finishPos; + const AString temp (GetIDString(((const char *)s) + pos, finishPos)); + if (!ConvertUTF8ToUnicode(temp, pair.ID)) + return false; + if (finishPos == 0) + return false; + pos += finishPos; + if (!SkipSpaces(s, pos)) + return false; + if (s[pos] != '=') + return false; + pos++; + if (!SkipSpaces(s, pos)) + return false; + if (s[pos] != '\"') + return false; + pos++; + AString message; + for (;;) + { + if (pos >= s.Len()) + return false; + char c = s[pos++]; + if (c == '\"') + break; + if (c == '\\') + { + c = s[pos++]; + switch (c) + { + case 'n': message += '\n'; break; + case 't': message += '\t'; break; + case '\\': message += '\\'; break; + case '\"': message += '\"'; break; + default: message += '\\'; message += c; break; + } + } + else + message += c; + } + if (!ConvertUTF8ToUnicode(message, pair.String)) + return false; + pairs.Add(pair); + } + return true; +} + +int FindTextConfigItem(const CObjectVector &pairs, const char *id) throw() +{ + FOR_VECTOR (i, pairs) + if (pairs[i].ID.IsEqualTo(id)) + return i; + return -1; +} + +UString GetTextConfigValue(const CObjectVector &pairs, const char *id) +{ + int index = FindTextConfigItem(pairs, id); + if (index < 0) + return UString(); + return pairs[index].String; +} diff --git a/other-licenses/7zstub/src/CPP/Common/TextConfig.h b/other-licenses/7zstub/src/CPP/Common/TextConfig.h new file mode 100644 index 0000000000..c39e3634fb --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/TextConfig.h @@ -0,0 +1,19 @@ +// Common/TextConfig.h + +#ifndef __COMMON_TEXT_CONFIG_H +#define __COMMON_TEXT_CONFIG_H + +#include "MyString.h" + +struct CTextConfigPair +{ + UString ID; + UString String; +}; + +bool GetTextConfig(const AString &text, CObjectVector &pairs); + +int FindTextConfigItem(const CObjectVector &pairs, const char *id) throw(); +UString GetTextConfigValue(const CObjectVector &pairs, const char *id); + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/UTFConvert.cpp b/other-licenses/7zstub/src/CPP/Common/UTFConvert.cpp new file mode 100644 index 0000000000..b09bbcdb37 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/UTFConvert.cpp @@ -0,0 +1,288 @@ +// UTFConvert.cpp + +#include "StdAfx.h" + +#include "MyTypes.h" +#include "UTFConvert.h" + +#ifdef _WIN32 +#define _WCHART_IS_16BIT 1 +#endif + +/* + _UTF8_START(n) - is a base value for start byte (head), if there are (n) additional bytes after start byte + + n : _UTF8_START(n) : Bits of code point + + 0 : 0x80 : : unused + 1 : 0xC0 : 11 : + 2 : 0xE0 : 16 : Basic Multilingual Plane + 3 : 0xF0 : 21 : Unicode space + 3 : 0xF8 : 26 : + 5 : 0xFC : 31 : UCS-4 + 6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value + 7 : 0xFF : +*/ + +#define _UTF8_START(n) (0x100 - (1 << (7 - (n)))) + +#define _UTF8_HEAD_PARSE2(n) if (c < _UTF8_START((n) + 1)) { numBytes = (n); c -= _UTF8_START(n); } + +#define _UTF8_HEAD_PARSE \ + _UTF8_HEAD_PARSE2(1) \ + else _UTF8_HEAD_PARSE2(2) \ + else _UTF8_HEAD_PARSE2(3) \ + else _UTF8_HEAD_PARSE2(4) \ + else _UTF8_HEAD_PARSE2(5) \ + + // else _UTF8_HEAD_PARSE2(6) + +bool CheckUTF8(const char *src, bool allowReduced) throw() +{ + for (;;) + { + Byte c = *src++; + if (c == 0) + return true; + + if (c < 0x80) + continue; + if (c < 0xC0) // (c < 0xC0 + 2) // if we support only optimal encoding chars + return false; + + unsigned numBytes; + _UTF8_HEAD_PARSE + else + return false; + + UInt32 val = c; + + do + { + Byte c2 = *src++; + if (c2 < 0x80 || c2 >= 0xC0) + return allowReduced && c2 == 0; + val <<= 6; + val |= (c2 - 0x80); + } + while (--numBytes); + + if (val >= 0x110000) + return false; + } +} + + +#define _ERROR_UTF8 \ + { if (dest) dest[destPos] = (wchar_t)0xFFFD; destPos++; ok = false; continue; } + +static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim) throw() +{ + size_t destPos = 0; + bool ok = true; + + for (;;) + { + Byte c; + if (src == srcLim) + { + *destLen = destPos; + return ok; + } + c = *src++; + + if (c < 0x80) + { + if (dest) + dest[destPos] = (wchar_t)c; + destPos++; + continue; + } + if (c < 0xC0) + _ERROR_UTF8 + + unsigned numBytes; + _UTF8_HEAD_PARSE + else + _ERROR_UTF8 + + UInt32 val = c; + + do + { + Byte c2; + if (src == srcLim) + break; + c2 = *src; + if (c2 < 0x80 || c2 >= 0xC0) + break; + src++; + val <<= 6; + val |= (c2 - 0x80); + } + while (--numBytes); + + if (numBytes != 0) + _ERROR_UTF8 + + if (val < 0x10000) + { + if (dest) + dest[destPos] = (wchar_t)val; + destPos++; + } + else + { + val -= 0x10000; + if (val >= 0x100000) + _ERROR_UTF8 + if (dest) + { + dest[destPos + 0] = (wchar_t)(0xD800 + (val >> 10)); + dest[destPos + 1] = (wchar_t)(0xDC00 + (val & 0x3FF)); + } + destPos += 2; + } + } +} + +#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) + +#define _UTF8_HEAD(n, val) ((char)(_UTF8_START(n) + (val >> (6 * (n))))) +#define _UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F))) + +static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim) +{ + size_t size = srcLim - src; + for (;;) + { + if (src == srcLim) + return size; + + UInt32 val = *src++; + + if (val < 0x80) + continue; + + if (val < _UTF8_RANGE(1)) + { + size++; + continue; + } + + if (val >= 0xD800 && val < 0xDC00 && src != srcLim) + { + UInt32 c2 = *src; + if (c2 >= 0xDC00 && c2 < 0xE000) + { + src++; + size += 2; + continue; + } + } + + #ifdef _WCHART_IS_16BIT + + size += 2; + + #else + + if (val < _UTF8_RANGE(2)) size += 2; + else if (val < _UTF8_RANGE(3)) size += 3; + else if (val < _UTF8_RANGE(4)) size += 4; + else if (val < _UTF8_RANGE(5)) size += 5; + else size += 6; + + #endif + } +} + +static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim) +{ + for (;;) + { + if (src == srcLim) + return dest; + + UInt32 val = *src++; + + if (val < 0x80) + { + *dest++ = (char)val; + continue; + } + + if (val < _UTF8_RANGE(1)) + { + dest[0] = _UTF8_HEAD(1, val); + dest[1] = _UTF8_CHAR(0, val); + dest += 2; + continue; + } + + if (val >= 0xD800 && val < 0xDC00 && src != srcLim) + { + UInt32 c2 = *src; + if (c2 >= 0xDC00 && c2 < 0xE000) + { + src++; + val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; + dest[0] = _UTF8_HEAD(3, val); + dest[1] = _UTF8_CHAR(2, val); + dest[2] = _UTF8_CHAR(1, val); + dest[3] = _UTF8_CHAR(0, val); + dest += 4; + continue; + } + } + + #ifndef _WCHART_IS_16BIT + if (val < _UTF8_RANGE(2)) + #endif + { + dest[0] = _UTF8_HEAD(2, val); + dest[1] = _UTF8_CHAR(1, val); + dest[2] = _UTF8_CHAR(0, val); + dest += 3; + continue; + } + + #ifndef _WCHART_IS_16BIT + + UInt32 b; + unsigned numBits; + if (val < _UTF8_RANGE(3)) { numBits = 6 * 3; b = _UTF8_HEAD(3, val); } + else if (val < _UTF8_RANGE(4)) { numBits = 6 * 4; b = _UTF8_HEAD(4, val); } + else if (val < _UTF8_RANGE(5)) { numBits = 6 * 5; b = _UTF8_HEAD(5, val); } + else { numBits = 6 * 6; b = _UTF8_START(6); } + + *dest++ = (Byte)b; + + do + { + numBits -= 6; + *dest++ = (char)(0x80 + ((val >> numBits) & 0x3F)); + } + while (numBits != 0); + + #endif + } +} + +bool ConvertUTF8ToUnicode(const AString &src, UString &dest) +{ + dest.Empty(); + size_t destLen = 0; + Utf8_To_Utf16(NULL, &destLen, src, src.Ptr(src.Len())); + bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src.Ptr(src.Len())); + dest.ReleaseBuf_SetEnd((unsigned)destLen); + return res; +} + +void ConvertUnicodeToUTF8(const UString &src, AString &dest) +{ + dest.Empty(); + size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len())); + Utf16_To_Utf8(dest.GetBuf((unsigned)destLen), src, src.Ptr(src.Len())); + dest.ReleaseBuf_SetEnd((unsigned)destLen); +} diff --git a/other-licenses/7zstub/src/CPP/Common/UTFConvert.h b/other-licenses/7zstub/src/CPP/Common/UTFConvert.h new file mode 100644 index 0000000000..11831700c7 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/UTFConvert.h @@ -0,0 +1,12 @@ +// Common/UTFConvert.h + +#ifndef __COMMON_UTF_CONVERT_H +#define __COMMON_UTF_CONVERT_H + +#include "MyString.h" + +bool CheckUTF8(const char *src, bool allowReduced = false) throw(); +bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); +void ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/Wildcard.cpp b/other-licenses/7zstub/src/CPP/Common/Wildcard.cpp new file mode 100644 index 0000000000..43e4baa179 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/Wildcard.cpp @@ -0,0 +1,676 @@ +// Common/Wildcard.cpp + +#include "StdAfx.h" + +#include "Wildcard.h" + +bool g_CaseSensitive = + #ifdef _WIN32 + false; + #else + true; + #endif + + +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) +{ + if (g_CaseSensitive) + return IsString1PrefixedByString2(s1, s2); + return IsString1PrefixedByString2_NoCase(s1, s2); +} + +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW +{ + if (g_CaseSensitive) + return MyStringCompare(s1, s2); + return MyStringCompareNoCase(s1, s2); +} + +#ifndef USE_UNICODE_FSTRING +int CompareFileNames(const char *s1, const char *s2) +{ + const UString u1 = fs2us(s1); + const UString u2 = fs2us(s2); + if (g_CaseSensitive) + return MyStringCompare(u1, u2); + return MyStringCompareNoCase(u1, u2); +} +#endif + +// ----------------------------------------- +// this function compares name with mask +// ? - any char +// * - any char or empty + +static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) +{ + for (;;) + { + wchar_t m = *mask; + wchar_t c = *name; + if (m == 0) + return (c == 0); + if (m == '*') + { + if (EnhancedMaskTest(mask + 1, name)) + return true; + if (c == 0) + return false; + } + else + { + if (m == '?') + { + if (c == 0) + return false; + } + else if (m != c) + if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) + return false; + mask++; + } + name++; + } +} + +// -------------------------------------------------- +// Splits path to strings + +void SplitPathToParts(const UString &path, UStringVector &pathParts) +{ + pathParts.Clear(); + unsigned len = path.Len(); + if (len == 0) + return; + UString name; + unsigned prev = 0; + for (unsigned i = 0; i < len; i++) + if (IsPathSepar(path[i])) + { + name.SetFrom(path.Ptr(prev), i - prev); + pathParts.Add(name); + prev = i + 1; + } + name.SetFrom(path.Ptr(prev), len - prev); + pathParts.Add(name); +} + +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name) +{ + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsPathSepar(*(p - 1))) + break; + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; +} + +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name) +{ + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + if (p != start) + { + if (IsPathSepar(*(p - 1))) + p--; + for (; p != start; p--) + if (IsPathSepar(*(p - 1))) + break; + } + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; +} + +/* +UString ExtractDirPrefixFromPath(const UString &path) +{ + return path.Left(path.ReverseFind_PathSepar() + 1)); +} +*/ + +UString ExtractFileNameFromPath(const UString &path) +{ + return UString(path.Ptr(path.ReverseFind_PathSepar() + 1)); +} + + +bool DoesWildcardMatchName(const UString &mask, const UString &name) +{ + return EnhancedMaskTest(mask, name); +} + +bool DoesNameContainWildcard(const UString &path) +{ + for (unsigned i = 0; i < path.Len(); i++) + { + wchar_t c = path[i]; + if (c == '*' || c == '?') + return true; + } + return false; +} + + +// ----------------------------------------------------------' +// NWildcard + +namespace NWildcard { + +/* + +M = MaskParts.Size(); +N = TestNameParts.Size(); + + File Dir +ForFile rec M<=N [N-M, N) - +!ForDir nonrec M=N [0, M) - + +ForDir rec M 1) + return true; + } + return false; +} + +bool CCensorNode::AreThereIncludeItems() const +{ + if (IncludeItems.Size() > 0) + return true; + FOR_VECTOR (i, SubNodes) + if (SubNodes[i].AreThereIncludeItems()) + return true; + return false; +} + +bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const +{ + const CObjectVector &items = include ? IncludeItems : ExcludeItems; + FOR_VECTOR (i, items) + if (items[i].CheckPath(pathParts, isFile)) + return true; + return false; +} + +bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const +{ + if (CheckPathCurrent(false, pathParts, isFile)) + { + include = false; + return true; + } + include = true; + bool finded = CheckPathCurrent(true, pathParts, isFile); + if (pathParts.Size() <= 1) + return finded; + int index = FindSubNode(pathParts.Front()); + if (index >= 0) + { + UStringVector pathParts2 = pathParts; + pathParts2.Delete(0); + if (SubNodes[index].CheckPathVect(pathParts2, isFile, include)) + return true; + } + return finded; +} + +/* +bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const +{ + UStringVector pathParts; + SplitPathToParts(path, pathParts); + if (CheckPathVect(pathParts, isFile, include)) + { + if (!include || !isAltStream) + return true; + } + if (isAltStream && !pathParts.IsEmpty()) + { + UString &back = pathParts.Back(); + int pos = back.Find(L':'); + if (pos > 0) + { + back.DeleteFrom(pos); + return CheckPathVect(pathParts, isFile, include); + } + } + return false; +} + +bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const +{ + bool include; + if (CheckPath2(isAltStream, path, isFile, include)) + return include; + return false; +} +*/ + +bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const +{ + if (CheckPathCurrent(include, pathParts, isFile)) + return true; + if (Parent == 0) + return false; + pathParts.Insert(0, Name); + return Parent->CheckPathToRoot(include, pathParts, isFile); +} + +/* +bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const +{ + UStringVector pathParts; + SplitPathToParts(path, pathParts); + return CheckPathToRoot(include, pathParts, isFile); +} +*/ + +void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + if (path.IsEmpty()) + return; + bool forFile = true; + bool forFolder = true; + UString path2 (path); + if (IsPathSepar(path.Back())) + { + path2.DeleteBack(); + forFile = false; + } + AddItem(include, path2, recursive, forFile, forFolder, wildcardMatching); +} + +void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) +{ + ExcludeItems += fromNodes.ExcludeItems; + FOR_VECTOR (i, fromNodes.SubNodes) + { + const CCensorNode &node = fromNodes.SubNodes[i]; + int subNodeIndex = FindSubNode(node.Name); + if (subNodeIndex < 0) + subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); + SubNodes[subNodeIndex].ExtendExclude(node); + } +} + +int CCensor::FindPrefix(const UString &prefix) const +{ + FOR_VECTOR (i, Pairs) + if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) + return i; + return -1; +} + +#ifdef _WIN32 + +bool IsDriveColonName(const wchar_t *s) +{ + wchar_t c = s[0]; + return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); +} + +unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts) +{ + if (pathParts.IsEmpty()) + return 0; + + unsigned testIndex = 0; + if (pathParts[0].IsEmpty()) + { + if (pathParts.Size() < 4 + || !pathParts[1].IsEmpty() + || pathParts[2] != L"?") + return 0; + testIndex = 3; + } + if (NWildcard::IsDriveColonName(pathParts[testIndex])) + return testIndex + 1; + return 0; +} + +#endif + +static unsigned GetNumPrefixParts(const UStringVector &pathParts) +{ + if (pathParts.IsEmpty()) + return 0; + + #ifdef _WIN32 + + if (IsDriveColonName(pathParts[0])) + return 1; + if (!pathParts[0].IsEmpty()) + return 0; + + if (pathParts.Size() == 1) + return 1; + if (!pathParts[1].IsEmpty()) + return 1; + if (pathParts.Size() == 2) + return 2; + if (pathParts[2] == L".") + return 3; + + unsigned networkParts = 2; + if (pathParts[2] == L"?") + { + if (pathParts.Size() == 3) + return 3; + if (IsDriveColonName(pathParts[3])) + return 4; + if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC")) + return 3; + networkParts = 4; + } + + networkParts += + // 2; // server/share + 1; // server + if (pathParts.Size() <= networkParts) + return pathParts.Size(); + return networkParts; + + #else + + return pathParts[0].IsEmpty() ? 1 : 0; + + #endif +} + +void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + if (path.IsEmpty()) + throw "Empty file path"; + + UStringVector pathParts; + SplitPathToParts(path, pathParts); + + bool forFile = true; + if (pathParts.Back().IsEmpty()) + { + forFile = false; + pathParts.DeleteBack(); + } + + UString prefix; + + int ignoreWildcardIndex = -1; + + // #ifdef _WIN32 + // we ignore "?" wildcard in "\\?\" prefix. + if (pathParts.Size() >= 3 + && pathParts[0].IsEmpty() + && pathParts[1].IsEmpty() + && pathParts[2] == L"?") + ignoreWildcardIndex = 2; + // #endif + + if (pathMode != k_AbsPath) + { + ignoreWildcardIndex = -1; + + const unsigned numPrefixParts = GetNumPrefixParts(pathParts); + unsigned numSkipParts = numPrefixParts; + + if (pathMode != k_FullPath) + { + if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts) + numSkipParts = pathParts.Size() - 1; + } + { + int dotsIndex = -1; + for (unsigned i = numPrefixParts; i < pathParts.Size(); i++) + { + const UString &part = pathParts[i]; + if (part == L".." || part == L".") + dotsIndex = i; + } + + if (dotsIndex >= 0) + if (dotsIndex == (int)pathParts.Size() - 1) + numSkipParts = pathParts.Size(); + else + numSkipParts = pathParts.Size() - 1; + } + + for (unsigned i = 0; i < numSkipParts; i++) + { + { + const UString &front = pathParts.Front(); + // WIN32 doesn't support wildcards in file names + if (wildcardMatching) + if (i >= numPrefixParts && DoesNameContainWildcard(front)) + break; + prefix += front; + prefix.Add_PathSepar(); + } + pathParts.Delete(0); + } + } + + int index = FindPrefix(prefix); + if (index < 0) + index = Pairs.Add(CPair(prefix)); + + if (pathMode != k_AbsPath) + { + if (pathParts.IsEmpty() || pathParts.Size() == 1 && pathParts[0].IsEmpty()) + { + // we create universal item, if we skip all parts as prefix (like \ or L:\ ) + pathParts.Clear(); + pathParts.Add(UString("*")); + forFile = true; + wildcardMatching = true; + recursive = false; + } + } + + CItem item; + item.PathParts = pathParts; + item.ForDir = true; + item.ForFile = forFile; + item.Recursive = recursive; + item.WildcardMatching = wildcardMatching; + Pairs[index].Head.AddItem(include, item, ignoreWildcardIndex); +} + +/* +bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const +{ + bool finded = false; + FOR_VECTOR (i, Pairs) + { + bool include; + if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include)) + { + if (!include) + return false; + finded = true; + } + } + return finded; +} +*/ + +void CCensor::ExtendExclude() +{ + unsigned i; + for (i = 0; i < Pairs.Size(); i++) + if (Pairs[i].Prefix.IsEmpty()) + break; + if (i == Pairs.Size()) + return; + unsigned index = i; + for (i = 0; i < Pairs.Size(); i++) + if (index != i) + Pairs[i].Head.ExtendExclude(Pairs[index].Head); +} + +void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode) +{ + FOR_VECTOR(i, CensorPaths) + { + const CCensorPath &cp = CensorPaths[i]; + AddItem(censorPathMode, cp.Include, cp.Path, cp.Recursive, cp.WildcardMatching); + } + CensorPaths.Clear(); +} + +void CCensor::AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + CCensorPath &cp = CensorPaths.AddNew(); + cp.Path = path; + cp.Include = include; + cp.Recursive = recursive; + cp.WildcardMatching = wildcardMatching; +} + +} diff --git a/other-licenses/7zstub/src/CPP/Common/Wildcard.h b/other-licenses/7zstub/src/CPP/Common/Wildcard.h new file mode 100644 index 0000000000..6e5f013418 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/Wildcard.h @@ -0,0 +1,149 @@ +// Common/Wildcard.h + +#ifndef __COMMON_WILDCARD_H +#define __COMMON_WILDCARD_H + +#include "MyString.h" + +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW; +#ifndef USE_UNICODE_FSTRING + int CompareFileNames(const char *s1, const char *s2); +#endif + +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2); + +void SplitPathToParts(const UString &path, UStringVector &pathParts); +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name); +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path) + +UString ExtractDirPrefixFromPath(const UString &path); +UString ExtractFileNameFromPath(const UString &path); + +bool DoesNameContainWildcard(const UString &path); +bool DoesWildcardMatchName(const UString &mask, const UString &name); + +namespace NWildcard { + +#ifdef _WIN32 +// returns true, if name is like "a:", "c:", ... +bool IsDriveColonName(const wchar_t *s); +unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts); +#endif + +struct CItem +{ + UStringVector PathParts; + bool Recursive; + bool ForFile; + bool ForDir; + bool WildcardMatching; + + #ifdef _WIN32 + bool IsDriveItem() const + { + return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]); + } + #endif + + // CItem(): WildcardMatching(true) {} + + bool AreAllAllowed() const; + bool CheckPath(const UStringVector &pathParts, bool isFile) const; +}; + +class CCensorNode +{ + CCensorNode *Parent; + + bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; + void AddItemSimple(bool include, CItem &item); +public: + bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const; + + CCensorNode(): Parent(0) { }; + CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; + + UString Name; // WIN32 doesn't support wildcards in file names + CObjectVector SubNodes; + CObjectVector IncludeItems; + CObjectVector ExcludeItems; + + bool AreAllAllowed() const; + + int FindSubNode(const UString &path) const; + + void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1); + void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching); + void AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching); + + bool NeedCheckSubDirs() const; + bool AreThereIncludeItems() const; + + // bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const; + // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; + + bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; + // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; + void ExtendExclude(const CCensorNode &fromNodes); +}; + +struct CPair +{ + UString Prefix; + CCensorNode Head; + + CPair(const UString &prefix): Prefix(prefix) { }; +}; + +enum ECensorPathMode +{ + k_RelatPath, // absolute prefix as Prefix, remain path in Tree + k_FullPath, // drive prefix as Prefix, remain path in Tree + k_AbsPath // full path in Tree +}; + +struct CCensorPath +{ + UString Path; + bool Include; + bool Recursive; + bool WildcardMatching; + + CCensorPath(): + Include(true), + Recursive(false), + WildcardMatching(true) + {} +}; + +class CCensor +{ + int FindPrefix(const UString &prefix) const; +public: + CObjectVector Pairs; + + CObjectVector CensorPaths; + + bool AllAreRelative() const + { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } + + void AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching); + // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; + void ExtendExclude(); + + void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode); + void AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching); + void AddPreItem(const UString &path) + { + AddPreItem(true, path, false, false); + } + void AddPreItem_Wildcard() + { + AddPreItem(true, UString("*"), false, true); + } +}; + + +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Common/XzCrc64Init.cpp b/other-licenses/7zstub/src/CPP/Common/XzCrc64Init.cpp new file mode 100644 index 0000000000..1eae72ad9b --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/XzCrc64Init.cpp @@ -0,0 +1,7 @@ +// XzCrc64Init.cpp + +#include "StdAfx.h" + +#include "../../C/XzCrc64.h" + +static struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; diff --git a/other-licenses/7zstub/src/CPP/Common/XzCrc64Reg.cpp b/other-licenses/7zstub/src/CPP/Common/XzCrc64Reg.cpp new file mode 100644 index 0000000000..92fce0a1a0 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Common/XzCrc64Reg.cpp @@ -0,0 +1,42 @@ +// XzCrc64Reg.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" +#include "../../C/XzCrc64.h" + +#include "../Common/MyCom.h" + +#include "../7zip/Common/RegisterCodec.h" + +class CXzCrc64Hasher: + public IHasher, + public CMyUnknownImp +{ + UInt64 _crc; + Byte mtDummy[1 << 7]; + +public: + CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {} + + MY_UNKNOWN_IMP1(IHasher) + INTERFACE_IHasher(;) +}; + +STDMETHODIMP_(void) CXzCrc64Hasher::Init() throw() +{ + _crc = CRC64_INIT_VAL; +} + +STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size) throw() +{ + _crc = Crc64Update(_crc, data, size); +} + +STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest) throw() +{ + UInt64 val = CRC64_GET_DIGEST(_crc); + SetUi64(digest, val); +} + +REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8) diff --git a/other-licenses/7zstub/src/CPP/Windows/COM.h b/other-licenses/7zstub/src/CPP/Windows/COM.h new file mode 100644 index 0000000000..e2cb002bf7 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/COM.h @@ -0,0 +1,70 @@ +// Windows/COM.h + +#ifndef __WINDOWS_COM_H +#define __WINDOWS_COM_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NCOM { + +#ifdef _WIN32 + +class CComInitializer +{ +public: + CComInitializer() + { + #ifdef UNDER_CE + CoInitializeEx(NULL, COINIT_MULTITHREADED); + #else + // it's single thread. Do we need multithread? + CoInitialize(NULL); + #endif + }; + ~CComInitializer() { CoUninitialize(); } +}; + +class CStgMedium +{ + STGMEDIUM _object; +public: + bool _mustBeReleased; + CStgMedium(): _mustBeReleased(false) {} + ~CStgMedium() { Free(); } + void Free() + { + if (_mustBeReleased) + ReleaseStgMedium(&_object); + _mustBeReleased = false; + } + const STGMEDIUM* operator->() const { return &_object;} + STGMEDIUM* operator->() { return &_object;} + STGMEDIUM* operator&() { return &_object; } +}; + +#endif + +/* +////////////////////////////////// +// GUID <--> String Conversions +UString GUIDToStringW(REFGUID guid); +AString GUIDToStringA(REFGUID guid); +#ifdef UNICODE + #define GUIDToString GUIDToStringW +#else + #define GUIDToString GUIDToStringA +#endif + +HRESULT StringToGUIDW(const wchar_t *string, GUID &classID); +HRESULT StringToGUIDA(const char *string, GUID &classID); +#ifdef UNICODE + #define StringToGUID StringToGUIDW +#else + #define StringToGUID StringToGUIDA +#endif +*/ + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/CommonDialog.cpp b/other-licenses/7zstub/src/CPP/Windows/CommonDialog.cpp new file mode 100644 index 0000000000..8b3828cf76 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/CommonDialog.cpp @@ -0,0 +1,185 @@ +// Windows/CommonDialog.cpp + +#include "StdAfx.h" + +#include "../Common/MyWindows.h" + +#ifdef UNDER_CE +#include +#endif + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "CommonDialog.h" +#include "Defs.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef _UNICODE + +class CDoubleZeroStringListA +{ + LPTSTR Buf; + unsigned Size; +public: + CDoubleZeroStringListA(LPSTR buf, unsigned size): Buf(buf), Size(size) {} + bool Add(LPCSTR s) throw(); + void Finish() { *Buf = 0; } +}; + +bool CDoubleZeroStringListA::Add(LPCSTR s) throw() +{ + unsigned len = MyStringLen(s) + 1; + if (len >= Size) + return false; + MyStringCopy(Buf, s); + Buf += len; + Size -= len; + return true; +} + +#endif + +class CDoubleZeroStringListW +{ + LPWSTR Buf; + unsigned Size; +public: + CDoubleZeroStringListW(LPWSTR buf, unsigned size): Buf(buf), Size(size) {} + bool Add(LPCWSTR s) throw(); + void Finish() { *Buf = 0; } +}; + +bool CDoubleZeroStringListW::Add(LPCWSTR s) throw() +{ + unsigned len = MyStringLen(s) + 1; + if (len >= Size) + return false; + MyStringCopy(Buf, s); + Buf += len; + Size -= len; + return true; +} + +#define MY__OFN_PROJECT 0x00400000 +#define MY__OFN_SHOW_ALL 0x01000000 + +/* if (lpstrFilter == NULL && nFilterIndex == 0) + MSDN : "the system doesn't show any files", + but WinXP-64 shows all files. Why ??? */ + +/* +structures + OPENFILENAMEW + OPENFILENAMEA +contain additional members: +#if (_WIN32_WINNT >= 0x0500) + void *pvReserved; + DWORD dwReserved; + DWORD FlagsEx; +#endif + +If we compile the source code with (_WIN32_WINNT >= 0x0500), some functions +will not work at NT 4.0, if we use sizeof(OPENFILENAME*). +So we use size of old version of structure. */ + +#if defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500) +// || !defined(WINVER) + #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA) + #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW) +#else + #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A + #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W +#endif + +#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; } + +bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, + LPCWSTR initialDir, + LPCWSTR filePath, + LPCWSTR filterDescription, + LPCWSTR filter, + UString &resPath + #ifdef UNDER_CE + , bool openFolder + #endif + ) +{ + const unsigned kBufSize = MAX_PATH * 2; + const unsigned kFilterBufSize = MAX_PATH; + if (!filter) + filter = L"*.*"; + #ifndef _UNICODE + if (!g_IsNT) + { + CHAR buf[kBufSize]; + MyStringCopy(buf, (const char *)GetSystemString(filePath)); + // OPENFILENAME_NT4A + OPENFILENAMEA p; + memset(&p, 0, sizeof(p)); + p.lStructSize = my_compatib_OPENFILENAMEA_size; + p.hwndOwner = hwnd; + CHAR filterBuf[kFilterBufSize]; + { + CDoubleZeroStringListA dz(filterBuf, kFilterBufSize); + dz.Add(GetSystemString(filterDescription ? filterDescription : filter)); + dz.Add(GetSystemString(filter)); + dz.Finish(); + p.lpstrFilter = filterBuf; + p.nFilterIndex = 1; + } + + p.lpstrFile = buf; + p.nMaxFile = kBufSize; + CONV_U_To_A(p.lpstrInitialDir, initialDir, initialDirA); + CONV_U_To_A(p.lpstrTitle, title, titleA); + p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY; + + bool res = BOOLToBool(::GetOpenFileNameA(&p)); + resPath = GetUnicodeString(buf); + return res; + } + else + #endif + { + WCHAR buf[kBufSize]; + MyStringCopy(buf, filePath); + // OPENFILENAME_NT4W + OPENFILENAMEW p; + memset(&p, 0, sizeof(p)); + p.lStructSize = my_compatib_OPENFILENAMEW_size; + p.hwndOwner = hwnd; + + WCHAR filterBuf[kFilterBufSize]; + { + CDoubleZeroStringListW dz(filterBuf, kFilterBufSize); + dz.Add(filterDescription ? filterDescription : filter); + dz.Add(filter); + dz.Finish(); + p.lpstrFilter = filterBuf; + p.nFilterIndex = 1; + } + + p.lpstrFile = buf; + p.nMaxFile = kBufSize; + p.lpstrInitialDir = initialDir; + p.lpstrTitle = title; + p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY + #ifdef UNDER_CE + | (openFolder ? (MY__OFN_PROJECT | MY__OFN_SHOW_ALL) : 0) + #endif + ; + + bool res = BOOLToBool(::GetOpenFileNameW(&p)); + resPath = buf; + return res; + } +} + +} diff --git a/other-licenses/7zstub/src/CPP/Windows/CommonDialog.h b/other-licenses/7zstub/src/CPP/Windows/CommonDialog.h new file mode 100644 index 0000000000..2bfec28d91 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/CommonDialog.h @@ -0,0 +1,23 @@ +// Windows/CommonDialog.h + +#ifndef __WINDOWS_COMMON_DIALOG_H +#define __WINDOWS_COMMON_DIALOG_H + +#include "../Common/MyString.h" + +namespace NWindows { + +bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, + LPCWSTR initialDir, // can be NULL, so dir prefix in filePath will be used + LPCWSTR filePath, // full path + LPCWSTR filterDescription, // like "All files (*.*)" + LPCWSTR filter, // like "*.exe" + UString &resPath + #ifdef UNDER_CE + , bool openFolder = false + #endif +); + +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/ComboBox.cpp b/other-licenses/7zstub/src/CPP/Windows/Control/ComboBox.cpp new file mode 100644 index 0000000000..6ab4717122 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ComboBox.cpp @@ -0,0 +1,66 @@ +// Windows/Control/ComboBox.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +#include "ComboBox.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +LRESULT CComboBox::GetLBText(int index, CSysString &s) +{ + s.Empty(); + LRESULT len = GetLBTextLen(index); // length, excluding the terminating null character + if (len == CB_ERR) + return len; + LRESULT len2 = GetLBText(index, s.GetBuf((unsigned)len)); + if (len2 == CB_ERR) + return len; + if (len > len2) + len = len2; + s.ReleaseBuf_CalcLen((unsigned)len); + return len; +} + +#ifndef _UNICODE +LRESULT CComboBox::AddString(LPCWSTR s) +{ + if (g_IsNT) + return SendMsgW(CB_ADDSTRING, 0, (LPARAM)s); + return AddString(GetSystemString(s)); +} + +LRESULT CComboBox::GetLBText(int index, UString &s) +{ + s.Empty(); + if (g_IsNT) + { + LRESULT len = SendMsgW(CB_GETLBTEXTLEN, index, 0); + if (len == CB_ERR) + return len; + LRESULT len2 = SendMsgW(CB_GETLBTEXT, index, (LPARAM)s.GetBuf((unsigned)len)); + if (len2 == CB_ERR) + return len; + if (len > len2) + len = len2; + s.ReleaseBuf_CalcLen((unsigned)len); + return len; + } + AString sa; + LRESULT len = GetLBText(index, sa); + if (len == CB_ERR) + return len; + s = GetUnicodeString(sa); + return s.Len(); +} +#endif + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/ComboBox.h b/other-licenses/7zstub/src/CPP/Windows/Control/ComboBox.h new file mode 100644 index 0000000000..3439655fe1 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ComboBox.h @@ -0,0 +1,65 @@ +// Windows/Control/ComboBox.h + +#ifndef __WINDOWS_CONTROL_COMBOBOX_H +#define __WINDOWS_CONTROL_COMBOBOX_H + +#include "../../Common/MyWindows.h" + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CComboBox: public CWindow +{ +public: + void ResetContent() { SendMsg(CB_RESETCONTENT, 0, 0); } + LRESULT AddString(LPCTSTR s) { return SendMsg(CB_ADDSTRING, 0, (LPARAM)s); } + #ifndef _UNICODE + LRESULT AddString(LPCWSTR s); + #endif + LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, index, 0); } + int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); } + int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); } + + LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, index, 0); } + LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, index, (LPARAM)s); } + LRESULT GetLBText(int index, CSysString &s); + #ifndef _UNICODE + LRESULT GetLBText(int index, UString &s); + #endif + + LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, index, lParam); } + LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, index, 0); } + + LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); } + + void ShowDropDown(bool show = true) { SendMsg(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); } +}; + +#ifndef UNDER_CE + +class CComboBoxEx: public CComboBox +{ +public: + bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); } + + LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, index, 0); } + LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); } + #ifndef _UNICODE + LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); } + #endif + + LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_SETITEM, 0, (LPARAM)item); } + DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMsg(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); } + HWND GetEditControl() { return (HWND)SendMsg(CBEM_GETEDITCONTROL, 0, 0); } + HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMsg(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); } +}; + +#endif + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/CommandBar.h b/other-licenses/7zstub/src/CPP/Windows/Control/CommandBar.h new file mode 100644 index 0000000000..c4355680a7 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/CommandBar.h @@ -0,0 +1,52 @@ +// Windows/Control/CommandBar.h + +#ifndef __WINDOWS_CONTROL_COMMANDBAR_H +#define __WINDOWS_CONTROL_COMMANDBAR_H + +#ifdef UNDER_CE + +#include "../../Common/MyWindows.h" + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CCommandBar: public NWindows::CWindow +{ +public: + bool Create(HINSTANCE hInst, HWND hwndParent, int idCmdBar) + { + _window = ::CommandBar_Create(hInst, hwndParent, idCmdBar); + return (_window != NULL); + } + + // Macros + // void Destroy() { CommandBar_Destroy(_window); } + // bool AddButtons(UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMsg(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); } + bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMsg(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); } + BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMsg(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); } + void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); } + + bool AddAdornments(DWORD dwFlags) { return BOOLToBool(::CommandBar_AddAdornments(_window, dwFlags, 0)); } + int AddBitmap(HINSTANCE hInst, int idBitmap, int iNumImages, int iImageWidth, int iImageHeight) { return ::CommandBar_AddBitmap(_window, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight); } + bool DrawMenuBar(WORD iButton) { return BOOLToBool(::CommandBar_DrawMenuBar(_window, iButton)); } + HMENU GetMenu(WORD iButton) { return ::CommandBar_GetMenu(_window, iButton); } + int Height() { return CommandBar_Height(_window); } + HWND InsertComboBox(HINSTANCE hInst, int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton) { return ::CommandBar_InsertComboBox(_window, hInst, iWidth, dwStyle, idComboBox, iButton); } + bool InsertMenubar(HINSTANCE hInst, WORD idMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubar(_window, hInst, idMenu, iButton)); } + bool InsertMenubarEx(HINSTANCE hInst, LPTSTR pszMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubarEx(_window, hInst, pszMenu, iButton)); } + bool Show(bool cmdShow) { return BOOLToBool(::CommandBar_Show(_window, BoolToBOOL(cmdShow))); } + + + // CE 4.0 + void AlignAdornments() { CommandBar_AlignAdornments(_window); } +}; + +}} + +#endif + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/Dialog.cpp b/other-licenses/7zstub/src/CPP/Windows/Control/Dialog.cpp new file mode 100644 index 0000000000..8e61a2b2c8 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/Dialog.cpp @@ -0,0 +1,251 @@ +// Windows/Control/Dialog.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +#include "Dialog.h" + +extern HINSTANCE g_hInstance; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +static INT_PTR APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempDialog(dialogHWND); + if (message == WM_INITDIALOG) + tempDialog.SetUserDataLongPtr(lParam); + CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); + if (dialog == NULL) + return FALSE; + if (message == WM_INITDIALOG) + dialog->Attach(dialogHWND); + try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } + catch(...) { return TRUE; } +} + +bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: return OnInit(); + case WM_COMMAND: return OnCommand(wParam, lParam); + case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam); + case WM_TIMER: return OnTimer(wParam, lParam); + case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam)); + case WM_HELP: OnHelp(); return true; + /* + OnHelp( + #ifdef UNDER_CE + (void *) + #else + (LPHELPINFO) + #endif + lParam); + return true; + */ + default: return false; + } +} + +bool CDialog::OnCommand(WPARAM wParam, LPARAM lParam) +{ + return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam); +} + +bool CDialog::OnCommand(int code, int itemID, LPARAM lParam) +{ + if (code == BN_CLICKED) + return OnButtonClicked(itemID, (HWND)lParam); + return false; +} + +bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */) +{ + switch (buttonID) + { + case IDOK: OnOK(); break; + case IDCANCEL: OnCancel(); break; + case IDCLOSE: OnClose(); break; + case IDHELP: OnHelp(); break; + default: return false; + } + return true; +} + +static bool GetWorkAreaRect(RECT *rect) +{ + // use another function for multi-monitor. + return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, 0, rect, 0)); +} + +bool IsDialogSizeOK(int xSize, int ySize) +{ + // it returns for system font. Real font uses another values + LONG v = GetDialogBaseUnits(); + int x = LOWORD(v); + int y = HIWORD(v); + + RECT rect; + GetWorkAreaRect(&rect); + int wx = RECT_SIZE_X(rect); + int wy = RECT_SIZE_Y(rect); + return + xSize / 4 * x <= wx && + ySize / 8 * y <= wy; +} + +bool CDialog::GetMargins(int margin, int &x, int &y) +{ + x = margin; + y = margin; + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = margin; + rect.bottom = margin; + if (!MapRect(&rect)) + return false; + x = rect.right - rect.left; + y = rect.bottom - rect.top; + return true; +} + +int CDialog::Units_To_Pixels_X(int units) +{ + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = units; + rect.bottom = units; + if (!MapRect(&rect)) + return units * 3 / 2; + return rect.right - rect.left; +} + +bool CDialog::GetItemSizes(int id, int &x, int &y) +{ + RECT rect; + if (!::GetWindowRect(GetItem(id), &rect)) + return false; + x = RECT_SIZE_X(rect); + y = RECT_SIZE_Y(rect); + return true; +} + +void CDialog::GetClientRectOfItem(int id, RECT &rect) +{ + ::GetWindowRect(GetItem(id), &rect); + ScreenToClient(&rect); +} + +bool CDialog::MoveItem(int id, int x, int y, int width, int height, bool repaint) +{ + return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint))); +} + +void CDialog::NormalizeSize(bool fullNormalize) +{ + RECT workRect; + GetWorkAreaRect(&workRect); + int xSize = RECT_SIZE_X(workRect); + int ySize = RECT_SIZE_Y(workRect); + RECT rect; + GetWindowRect(&rect); + int xSize2 = RECT_SIZE_X(rect); + int ySize2 = RECT_SIZE_Y(rect); + bool needMove = (xSize2 > xSize || ySize2 > ySize); + if (xSize2 > xSize || (needMove && fullNormalize)) + { + rect.left = workRect.left; + rect.right = workRect.right; + xSize2 = xSize; + } + if (ySize2 > ySize || (needMove && fullNormalize)) + { + rect.top = workRect.top; + rect.bottom = workRect.bottom; + ySize2 = ySize; + } + if (needMove) + { + if (fullNormalize) + Show(SW_SHOWMAXIMIZED); + else + Move(rect.left, rect.top, xSize2, ySize2, true); + } +} + +void CDialog::NormalizePosition() +{ + RECT workRect, rect; + GetWorkAreaRect(&workRect); + GetWindowRect(&rect); + if (rect.bottom > workRect.bottom && rect.top > workRect.top) + Move(rect.left, workRect.top, RECT_SIZE_X(rect), RECT_SIZE_Y(rect), true); +} + +bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow) +{ + HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); + if (aHWND == 0) + return false; + Attach(aHWND); + return true; +} + +INT_PTR CModalDialog::Create(LPCTSTR templateName, HWND parentWindow) +{ + return DialogBoxParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); +} + +#ifndef _UNICODE + +bool CModelessDialog::Create(LPCWSTR templateName, HWND parentWindow) +{ + HWND aHWND; + if (g_IsNT) + aHWND = CreateDialogParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); + else + { + AString name; + LPCSTR templateNameA; + if (IS_INTRESOURCE(templateName)) + templateNameA = (LPCSTR)templateName; + else + { + name = GetSystemString(templateName); + templateNameA = name; + } + aHWND = CreateDialogParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this); + } + if (aHWND == 0) + return false; + Attach(aHWND); + return true; +} + +INT_PTR CModalDialog::Create(LPCWSTR templateName, HWND parentWindow) +{ + if (g_IsNT) + return DialogBoxParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); + AString name; + LPCSTR templateNameA; + if (IS_INTRESOURCE(templateName)) + templateNameA = (LPCSTR)templateName; + else + { + name = GetSystemString(templateName); + templateNameA = name; + } + return DialogBoxParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this); +} +#endif + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/Dialog.h b/other-licenses/7zstub/src/CPP/Windows/Control/Dialog.h new file mode 100644 index 0000000000..f9c3442fdd --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/Dialog.h @@ -0,0 +1,170 @@ +// Windows/Control/Dialog.h + +#ifndef __WINDOWS_CONTROL_DIALOG_H +#define __WINDOWS_CONTROL_DIALOG_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CDialog: public CWindow +{ +public: + CDialog(HWND wnd = NULL): CWindow(wnd){}; + virtual ~CDialog() {}; + + HWND GetItem(int itemID) const + { return GetDlgItem(_window, itemID); } + + bool EnableItem(int itemID, bool enable) const + { return BOOLToBool(::EnableWindow(GetItem(itemID), BoolToBOOL(enable))); } + + bool ShowItem(int itemID, int cmdShow) const + { return BOOLToBool(::ShowWindow(GetItem(itemID), cmdShow)); } + + bool ShowItem_Bool(int itemID, bool show) const + { return ShowItem(itemID, show ? SW_SHOW: SW_HIDE); } + + bool HideItem(int itemID) const { return ShowItem(itemID, SW_HIDE); } + + bool SetItemText(int itemID, LPCTSTR s) + { return BOOLToBool(SetDlgItemText(_window, itemID, s)); } + + #ifndef _UNICODE + bool SetItemText(int itemID, LPCWSTR s) + { + CWindow window(GetItem(itemID)); + return window.SetText(s); + } + #endif + + UINT GetItemText(int itemID, LPTSTR string, int maxCount) + { return GetDlgItemText(_window, itemID, string, maxCount); } + #ifndef _UNICODE + /* + bool GetItemText(int itemID, LPWSTR string, int maxCount) + { + CWindow window(GetItem(itemID)); + return window.GetText(string, maxCount); + } + */ + #endif + + bool SetItemInt(int itemID, UINT value, bool isSigned) + { return BOOLToBool(SetDlgItemInt(_window, itemID, value, BoolToBOOL(isSigned))); } + bool GetItemInt(int itemID, bool isSigned, UINT &value) + { + BOOL result; + value = GetDlgItemInt(_window, itemID, &result, BoolToBOOL(isSigned)); + return BOOLToBool(result); + } + + HWND GetNextGroupItem(HWND control, bool previous) + { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); } + HWND GetNextTabItem(HWND control, bool previous) + { return GetNextDlgTabItem(_window, control, BoolToBOOL(previous)); } + + bool MapRect(LPRECT rect) + { return BOOLToBool(MapDialogRect(_window, rect)); } + + bool IsMessage(LPMSG message) + { return BOOLToBool(IsDialogMessage(_window, message)); } + + LRESULT SendItemMessage(int itemID, UINT message, WPARAM wParam, LPARAM lParam) + { return SendDlgItemMessage(_window, itemID, message, wParam, lParam); } + + bool CheckButton(int buttonID, UINT checkState) + { return BOOLToBool(CheckDlgButton(_window, buttonID, checkState)); } + bool CheckButton(int buttonID, bool checkState) + { return CheckButton(buttonID, UINT(checkState ? BST_CHECKED : BST_UNCHECKED)); } + + UINT IsButtonChecked(int buttonID) const + { return IsDlgButtonChecked(_window, buttonID); } + bool IsButtonCheckedBool(int buttonID) const + { return (IsButtonChecked(buttonID) == BST_CHECKED); } + + bool CheckRadioButton(int firstButtonID, int lastButtonID, int checkButtonID) + { return BOOLToBool(::CheckRadioButton(_window, firstButtonID, lastButtonID, checkButtonID)); } + + virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnInit() { return true; } + virtual bool OnCommand(WPARAM wParam, LPARAM lParam); + virtual bool OnCommand(int code, int itemID, LPARAM lParam); + virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; } + + /* + #ifdef UNDER_CE + virtual void OnHelp(void *) { OnHelp(); } + #else + virtual void OnHelp(LPHELPINFO) { OnHelp(); } + #endif + */ + virtual void OnHelp() {}; + + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK() {}; + virtual void OnCancel() {}; + virtual void OnClose() {} + virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; } + virtual bool OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { return false; } + + LONG_PTR SetMsgResult(LONG_PTR newLongPtr ) + { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); } + LONG_PTR GetMsgResult() const + { return GetLongPtr(DWLP_MSGRESULT); } + + bool GetMargins(int margin, int &x, int &y); + int Units_To_Pixels_X(int units); + bool GetItemSizes(int id, int &x, int &y); + void GetClientRectOfItem(int id, RECT &rect); + bool MoveItem(int id, int x, int y, int width, int height, bool repaint = true); + + void NormalizeSize(bool fullNormalize = false); + void NormalizePosition(); +}; + +class CModelessDialog: public CDialog +{ +public: + bool Create(LPCTSTR templateName, HWND parentWindow); + bool Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); } + #ifndef _UNICODE + bool Create(LPCWSTR templateName, HWND parentWindow); + #endif + virtual void OnOK() { Destroy(); } + virtual void OnCancel() { Destroy(); } + virtual void OnClose() { Destroy(); } +}; + +class CModalDialog: public CDialog +{ +public: + INT_PTR Create(LPCTSTR templateName, HWND parentWindow); + INT_PTR Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); } + #ifndef _UNICODE + INT_PTR Create(LPCWSTR templateName, HWND parentWindow); + #endif + + bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); } + virtual void OnOK() { End(IDOK); } + virtual void OnCancel() { End(IDCANCEL); } + virtual void OnClose() { End(IDCLOSE); } +}; + +class CDialogChildControl: public NWindows::CWindow +{ + int m_ID; +public: + void Init(const NWindows::NControl::CDialog &parentDialog, int id) + { + m_ID = id; + Attach(parentDialog.GetItem(id)); + } +}; + +bool IsDialogSizeOK(int xSize, int ySize); + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/Edit.h b/other-licenses/7zstub/src/CPP/Windows/Control/Edit.h new file mode 100644 index 0000000000..4f503aa7a5 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/Edit.h @@ -0,0 +1,19 @@ +// Windows/Control/Edit.h + +#ifndef __WINDOWS_CONTROL_EDIT_H +#define __WINDOWS_CONTROL_EDIT_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CEdit: public CWindow +{ +public: + void SetPasswordChar(WPARAM c) { SendMsg(EM_SETPASSWORDCHAR, c); } +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/ImageList.cpp b/other-licenses/7zstub/src/CPP/Windows/Control/ImageList.cpp new file mode 100644 index 0000000000..d201c8fd7e --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ImageList.cpp @@ -0,0 +1,10 @@ +// Windows/Control/ImageList.cpp + +#include "StdAfx.h" + +#include "ImageList.h" + +namespace NWindows { +namespace NControl { + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/ImageList.h b/other-licenses/7zstub/src/CPP/Windows/Control/ImageList.h new file mode 100644 index 0000000000..f72ea0d199 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ImageList.h @@ -0,0 +1,87 @@ +// Windows/Control/ImageList.h + +#ifndef __WINDOWS_CONTROL_IMAGE_LIST_H +#define __WINDOWS_CONTROL_IMAGE_LIST_H + +#include + +#include "../Defs.h" + +namespace NWindows { +namespace NControl { + +class CImageList +{ + HIMAGELIST m_Object; +public: + operator HIMAGELIST() const {return m_Object; } + CImageList(): m_Object(NULL) {} + bool Attach(HIMAGELIST imageList) + { + if (imageList == NULL) + return false; + m_Object = imageList; + return true; + } + + HIMAGELIST Detach() + { + HIMAGELIST imageList = m_Object; + m_Object = NULL; + return imageList; + } + + bool Create(int width, int height, UINT flags, int initialNumber, int grow) + { + HIMAGELIST a = ImageList_Create(width, height, flags, + initialNumber, grow); + if (a == NULL) + return false; + return Attach(a); + } + + bool Destroy() // DeleteImageList() in MFC + { + if (m_Object == NULL) + return false; + return BOOLToBool(ImageList_Destroy(Detach())); + } + + ~CImageList() + { Destroy(); } + + int GetImageCount() const + { return ImageList_GetImageCount(m_Object); } + + bool GetImageInfo(int index, IMAGEINFO* imageInfo) const + { return BOOLToBool(ImageList_GetImageInfo(m_Object, index, imageInfo)); } + + int Add(HBITMAP hbmImage, HBITMAP hbmMask = 0) + { return ImageList_Add(m_Object, hbmImage, hbmMask); } + int AddMasked(HBITMAP hbmImage, COLORREF mask) + { return ImageList_AddMasked(m_Object, hbmImage, mask); } + int AddIcon(HICON icon) + { return ImageList_AddIcon(m_Object, icon); } + int Replace(int index, HICON icon) + { return ImageList_ReplaceIcon(m_Object, index, icon); } + + // If index is -1, the function removes all images. + bool Remove(int index) + { return BOOLToBool(ImageList_Remove(m_Object, index)); } + bool RemoveAll() + { return BOOLToBool(ImageList_RemoveAll(m_Object)); } + + HICON ExtractIcon(int index) + { return ImageList_ExtractIcon(NULL, m_Object, index); } + HICON GetIcon(int index, UINT flags) + { return ImageList_GetIcon(m_Object, index, flags); } + + bool GetIconSize(int &width, int &height) const + { return BOOLToBool(ImageList_GetIconSize(m_Object, &width, &height)); } + bool SetIconSize(int width, int height) + { return BOOLToBool(ImageList_SetIconSize(m_Object, width, height)); } +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/ListView.cpp b/other-licenses/7zstub/src/CPP/Windows/Control/ListView.cpp new file mode 100644 index 0000000000..fb22f95c1b --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ListView.cpp @@ -0,0 +1,155 @@ +// Windows/Control/ListView.cpp + +#include "StdAfx.h" + +#include "ListView.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +bool CListView::CreateEx(DWORD exStyle, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) +{ + return CWindow::CreateEx(exStyle, WC_LISTVIEW, TEXT(""), style, x, y, width, + height, parentWindow, idOrHMenu, instance, createParam); +} + +bool CListView::GetItemParam(int index, LPARAM ¶m) const +{ + LVITEM item; + item.iItem = index; + item.iSubItem = 0; + item.mask = LVIF_PARAM; + bool aResult = GetItem(&item); + param = item.lParam; + return aResult; +} + +int CListView::InsertColumn(int columnIndex, LPCTSTR text, int width) +{ + LVCOLUMN ci; + ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + ci.pszText = (LPTSTR)text; + ci.iSubItem = columnIndex; + ci.cx = width; + return InsertColumn(columnIndex, &ci); +} + +int CListView::InsertItem(int index, LPCTSTR text) +{ + LVITEM item; + item.mask = LVIF_TEXT | LVIF_PARAM; + item.iItem = index; + item.lParam = index; + item.pszText = (LPTSTR)text; + item.iSubItem = 0; + return InsertItem(&item); +} + +int CListView::SetSubItem(int index, int subIndex, LPCTSTR text) +{ + LVITEM item; + item.mask = LVIF_TEXT; + item.iItem = index; + item.pszText = (LPTSTR)text; + item.iSubItem = subIndex; + return SetItem(&item); +} + +#ifndef _UNICODE + +int CListView::InsertColumn(int columnIndex, LPCWSTR text, int width) +{ + LVCOLUMNW ci; + ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + ci.pszText = (LPWSTR)text; + ci.iSubItem = columnIndex; + ci.cx = width; + return InsertColumn(columnIndex, &ci); +} + +int CListView::InsertItem(int index, LPCWSTR text) +{ + LVITEMW item; + item.mask = LVIF_TEXT | LVIF_PARAM; + item.iItem = index; + item.lParam = index; + item.pszText = (LPWSTR)text; + item.iSubItem = 0; + return InsertItem(&item); +} + +int CListView::SetSubItem(int index, int subIndex, LPCWSTR text) +{ + LVITEMW item; + item.mask = LVIF_TEXT; + item.iItem = index; + item.pszText = (LPWSTR)text; + item.iSubItem = subIndex; + return SetItem(&item); +} + +#endif + +static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow window(hwnd); + CListView2 *w = (CListView2 *)(window.GetUserDataLongPtr()); + if (w == NULL) + return 0; + return w->OnMessage(message, wParam, lParam); +} + +LRESULT CListView2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + #ifndef _UNICODE + if (g_IsNT) + return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam); + else + #endif + return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); +} + +void CListView2::SetWindowProc() +{ + SetUserDataLongPtr((LONG_PTR)this); + #ifndef _UNICODE + if (g_IsNT) + _origWindowProc = (WNDPROC)SetLongPtrW(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc); + else + #endif + _origWindowProc = (WNDPROC)SetLongPtr(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc); +} + +/* +LRESULT CListView3::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT res = CListView2::OnMessage(message, wParam, lParam); + if (message == WM_GETDLGCODE) + { + // when user presses RETURN, windows sends default (first) button command to parent dialog. + // we disable this: + MSG *msg = (MSG *)lParam; + WPARAM key = wParam; + bool change = false; + if (msg) + { + if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) + change = true; + } + else if (wParam == VK_RETURN) + change = true; + if (change) + res |= DLGC_WANTALLKEYS; + } + return res; +} +*/ + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/ListView.h b/other-licenses/7zstub/src/CPP/Windows/Control/ListView.h new file mode 100644 index 0000000000..1ed496d7e6 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ListView.h @@ -0,0 +1,146 @@ +// Windows/Control/ListView.h + +#ifndef __WINDOWS_CONTROL_LISTVIEW_H +#define __WINDOWS_CONTROL_LISTVIEW_H + +#include "../../Common/MyWindows.h" + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CListView: public NWindows::CWindow +{ +public: + bool CreateEx(DWORD exStyle, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam); + + void SetUnicodeFormat() + { + #ifndef UNDER_CE + ListView_SetUnicodeFormat(_window, TRUE); + #endif + } + + bool DeleteAllItems() { return BOOLToBool(ListView_DeleteAllItems(_window)); } + bool DeleteColumn(int columnIndex) { return BOOLToBool(ListView_DeleteColumn(_window, columnIndex)); } + + int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); } + int InsertColumn(int columnIndex, LPCTSTR text, int width); + bool SetColumnOrderArray(int count, const int *columns) { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, columns)); } + + /* + int GetNumColumns() + { + HWND header = ListView_GetHeader(_window); + if (!header) + return -1; + return Header_GetItemCount(header); + } + */ + + int InsertItem(const LVITEM* item) { return ListView_InsertItem(_window, item); } + int InsertItem(int index, LPCTSTR text); + bool SetItem(const LVITEM* item) { return BOOLToBool(ListView_SetItem(_window, item)); } + int SetSubItem(int index, int subIndex, LPCTSTR text); + + #ifndef _UNICODE + + int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMsg(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); } + int InsertColumn(int columnIndex, LPCWSTR text, int width); + int InsertItem(const LV_ITEMW* item) { return (int)SendMsg(LVM_INSERTITEMW, 0, (LPARAM)item); } + int InsertItem(int index, LPCWSTR text); + bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMsg(LVM_SETITEMW, 0, (LPARAM)item)); } + int SetSubItem(int index, int subIndex, LPCWSTR text); + + #endif + + bool DeleteItem(int itemIndex) { return BOOLToBool(ListView_DeleteItem(_window, itemIndex)); } + + UINT GetSelectedCount() const { return ListView_GetSelectedCount(_window); } + int GetItemCount() const { return ListView_GetItemCount(_window); } + + INT GetSelectionMark() const { return ListView_GetSelectionMark(_window); } + + void SetItemCount(int numItems) { ListView_SetItemCount(_window, numItems); } + void SetItemCountEx(int numItems, DWORD flags) { ListView_SetItemCountEx(_window, numItems, flags); } + + int GetNextItem(int startIndex, UINT flags) const { return ListView_GetNextItem(_window, startIndex, flags); } + int GetNextSelectedItem(int startIndex) const { return GetNextItem(startIndex, LVNI_SELECTED); } + int GetFocusedItem() const { return GetNextItem(-1, LVNI_FOCUSED); } + + bool GetItem(LVITEM* item) const { return BOOLToBool(ListView_GetItem(_window, item)); } + bool GetItemParam(int itemIndex, LPARAM ¶m) const; + void GetItemText(int itemIndex, int subItemIndex, LPTSTR text, int textSizeMax) const + { ListView_GetItemText(_window, itemIndex, subItemIndex, text, textSizeMax); } + bool SortItems(PFNLVCOMPARE compareFunction, LPARAM dataParam) + { return BOOLToBool(ListView_SortItems(_window, compareFunction, dataParam)); } + + void SetItemState(int index, UINT state, UINT mask) { ListView_SetItemState(_window, index, state, mask); } + void SetItemState_Selected(int index, bool select) { SetItemState(index, select ? LVIS_SELECTED : 0, LVIS_SELECTED); } + void SetItemState_Selected(int index) { SetItemState(index, LVIS_SELECTED, LVIS_SELECTED); } + void SelectAll() { SetItemState_Selected(-1); } + void SetItemState_FocusedSelected(int index) { SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); } + UINT GetItemState(int index, UINT mask) const { return ListView_GetItemState(_window, index, mask); } + bool IsItemSelected(int index) const { return GetItemState(index, LVIS_SELECTED) == LVIS_SELECTED; } + + bool GetColumn(int columnIndex, LVCOLUMN* columnInfo) const + { return BOOLToBool(ListView_GetColumn(_window, columnIndex, columnInfo)); } + + HIMAGELIST SetImageList(HIMAGELIST imageList, int imageListType) + { return ListView_SetImageList(_window, imageList, imageListType); } + + // version 4.70: NT5 | (NT4 + ie3) | w98 | (w95 + ie3) + DWORD GetExtendedListViewStyle() { return ListView_GetExtendedListViewStyle(_window); } + void SetExtendedListViewStyle(DWORD exStyle) { ListView_SetExtendedListViewStyle(_window, exStyle); } + void SetExtendedListViewStyle(DWORD exMask, DWORD exStyle) { ListView_SetExtendedListViewStyleEx(_window, exMask, exStyle); } + + void SetCheckState(UINT index, bool checkState) { ListView_SetCheckState(_window, index, BoolToBOOL(checkState)); } + bool GetCheckState(UINT index) { return BOOLToBool(ListView_GetCheckState(_window, index)); } + + bool EnsureVisible(int index, bool partialOK) { return BOOLToBool(ListView_EnsureVisible(_window, index, BoolToBOOL(partialOK))); } + + bool GetItemRect(int index, RECT *rect, int code) { return BOOLToBool(ListView_GetItemRect(_window, index, rect, code)); } + + HWND GetEditControl() { return ListView_GetEditControl(_window) ; } + HWND EditLabel(int itemIndex) { return ListView_EditLabel(_window, itemIndex) ; } + + bool RedrawItems(int firstIndex, int lastIndex) { return BOOLToBool(ListView_RedrawItems(_window, firstIndex, lastIndex)); } + bool RedrawAllItems() + { + if (GetItemCount() > 0) + return RedrawItems(0, GetItemCount() - 1); + return true; + } + bool RedrawItem(int index) { return RedrawItems(index, index); } + + int HitTest(LPLVHITTESTINFO info) { return ListView_HitTest(_window, info); } + COLORREF GetBkColor() { return ListView_GetBkColor(_window); } + bool SetColumnWidth(int iCol, int cx) { return BOOLToBool(ListView_SetColumnWidth(_window, iCol, cx)); } + bool SetColumnWidthAuto(int iCol) { return SetColumnWidth(iCol, LVSCW_AUTOSIZE); } +}; + +class CListView2: public CListView +{ + WNDPROC _origWindowProc; +public: + void SetWindowProc(); + virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; + +/* +class CListView3: public CListView2 +{ +public: + virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; +*/ + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/ProgressBar.h b/other-licenses/7zstub/src/CPP/Windows/Control/ProgressBar.h new file mode 100644 index 0000000000..f18d89c14f --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ProgressBar.h @@ -0,0 +1,35 @@ +// Windows/Control/ProgressBar.h + +#ifndef __WINDOWS_CONTROL_PROGRESSBAR_H +#define __WINDOWS_CONTROL_PROGRESSBAR_H + +#include "../../Common/MyWindows.h" + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CProgressBar: public CWindow +{ +public: + LRESULT SetPos(int pos) { return SendMsg(PBM_SETPOS, pos, 0); } + LRESULT DeltaPos(int increment) { return SendMsg(PBM_DELTAPOS, increment, 0); } + UINT GetPos() { return (UINT)SendMsg(PBM_GETPOS, 0, 0); } + LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMsg(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); } + DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMsg(PBM_SETRANGE32, minValue, maxValue); } + int SetStep(int step) { return (int)SendMsg(PBM_SETSTEP, step, 0); } + LRESULT StepIt() { return SendMsg(PBM_STEPIT, 0, 0); } + INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMsg(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); } + + #ifndef UNDER_CE + COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBARCOLOR, 0, color); } + COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBKCOLOR, 0, color); } + #endif +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/PropertyPage.cpp b/other-licenses/7zstub/src/CPP/Windows/Control/PropertyPage.cpp new file mode 100644 index 0000000000..48947c018d --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/PropertyPage.cpp @@ -0,0 +1,143 @@ +// Windows/Control/PropertyPage.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +#include "PropertyPage.h" + +extern HINSTANCE g_hInstance; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +static INT_PTR APIENTRY MyProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempDialog(dialogHWND); + if (message == WM_INITDIALOG) + tempDialog.SetUserDataLongPtr(((PROPSHEETPAGE *)lParam)->lParam); + CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); + if (dialog == NULL) + return FALSE; + if (message == WM_INITDIALOG) + dialog->Attach(dialogHWND); + try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } + catch(...) { return TRUE; } +} + +bool CPropertyPage::OnNotify(UINT /* controlID */, LPNMHDR lParam) +{ + switch (lParam->code) + { + case PSN_APPLY: SetMsgResult(OnApply(LPPSHNOTIFY(lParam))); break; + case PSN_KILLACTIVE: SetMsgResult(BoolToBOOL(OnKillActive(LPPSHNOTIFY(lParam)))); break; + case PSN_SETACTIVE: SetMsgResult(OnSetActive(LPPSHNOTIFY(lParam))); break; + case PSN_RESET: OnReset(LPPSHNOTIFY(lParam)); break; + case PSN_HELP: OnNotifyHelp(LPPSHNOTIFY(lParam)); break; + default: return false; + } + return true; +} + +INT_PTR MyPropertySheet(const CObjectVector &pagesInfo, HWND hwndParent, const UString &title) +{ + #ifndef _UNICODE + AStringVector titles; + #endif + #ifndef _UNICODE + CRecordVector pagesA; + #endif + CRecordVector pagesW; + + unsigned i; + #ifndef _UNICODE + for (i = 0; i < pagesInfo.Size(); i++) + titles.Add(GetSystemString(pagesInfo[i].Title)); + #endif + + for (i = 0; i < pagesInfo.Size(); i++) + { + const CPageInfo &pageInfo = pagesInfo[i]; + #ifndef _UNICODE + { + PROPSHEETPAGE page; + page.dwSize = sizeof(page); + page.dwFlags = PSP_HASHELP; + page.hInstance = g_hInstance; + page.pszTemplate = MAKEINTRESOURCE(pageInfo.ID); + page.pszIcon = NULL; + page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure; + + if (titles[i].IsEmpty()) + page.pszTitle = NULL; + else + { + page.dwFlags |= PSP_USETITLE; + page.pszTitle = titles[i]; + } + page.lParam = (LPARAM)pageInfo.Page; + page.pfnCallback = NULL; + pagesA.Add(page); + } + #endif + { + PROPSHEETPAGEW page; + page.dwSize = sizeof(page); + page.dwFlags = PSP_HASHELP; + page.hInstance = g_hInstance; + page.pszTemplate = MAKEINTRESOURCEW(pageInfo.ID); + page.pszIcon = NULL; + page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure; + + if (pageInfo.Title.IsEmpty()) + page.pszTitle = NULL; + else + { + page.dwFlags |= PSP_USETITLE; + page.pszTitle = pageInfo.Title; + } + page.lParam = (LPARAM)pageInfo.Page; + page.pfnCallback = NULL; + pagesW.Add(page); + } + } + + #ifndef _UNICODE + if (!g_IsNT) + { + PROPSHEETHEADER sheet; + sheet.dwSize = sizeof(sheet); + sheet.dwFlags = PSH_PROPSHEETPAGE; + sheet.hwndParent = hwndParent; + sheet.hInstance = g_hInstance; + AString titleA (GetSystemString(title)); + sheet.pszCaption = titleA; + sheet.nPages = pagesInfo.Size(); + sheet.nStartPage = 0; + sheet.ppsp = &pagesA.Front(); + sheet.pfnCallback = NULL; + return ::PropertySheetA(&sheet); + } + else + #endif + { + PROPSHEETHEADERW sheet; + sheet.dwSize = sizeof(sheet); + sheet.dwFlags = PSH_PROPSHEETPAGE; + sheet.hwndParent = hwndParent; + sheet.hInstance = g_hInstance; + sheet.pszCaption = title; + sheet.nPages = pagesInfo.Size(); + sheet.nStartPage = 0; + sheet.ppsp = &pagesW.Front(); + sheet.pfnCallback = NULL; + return ::PropertySheetW(&sheet); + } +} + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/PropertyPage.h b/other-licenses/7zstub/src/CPP/Windows/Control/PropertyPage.h new file mode 100644 index 0000000000..551c95994c --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/PropertyPage.h @@ -0,0 +1,50 @@ +// Windows/Control/PropertyPage.h + +#ifndef __WINDOWS_CONTROL_PROPERTYPAGE_H +#define __WINDOWS_CONTROL_PROPERTYPAGE_H + +#include "../../Common/MyWindows.h" + +#include + +#include "Dialog.h" + +namespace NWindows { +namespace NControl { + +INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam); + +class CPropertyPage: public CDialog +{ +public: + CPropertyPage(HWND window = NULL): CDialog(window){}; + + void Changed() { PropSheet_Changed(GetParent(), (HWND)*this); } + void UnChanged() { PropSheet_UnChanged(GetParent(), (HWND)*this); } + + virtual bool OnNotify(UINT controlID, LPNMHDR lParam); + + virtual bool OnKillActive() { return false; } // false = OK + virtual bool OnKillActive(const PSHNOTIFY *) { return OnKillActive(); } + virtual LONG OnSetActive() { return false; } // false = OK + virtual LONG OnSetActive(const PSHNOTIFY *) { return OnSetActive(); } + virtual LONG OnApply() { return PSNRET_NOERROR; } + virtual LONG OnApply(const PSHNOTIFY *) { return OnApply(); } + virtual void OnNotifyHelp() {} + virtual void OnNotifyHelp(const PSHNOTIFY *) { OnNotifyHelp(); } + virtual void OnReset() {} + virtual void OnReset(const PSHNOTIFY *) { OnReset(); } +}; + +struct CPageInfo +{ + CPropertyPage *Page; + UString Title; + UINT ID; +}; + +INT_PTR MyPropertySheet(const CObjectVector &pagesInfo, HWND hwndParent, const UString &title); + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/ReBar.h b/other-licenses/7zstub/src/CPP/Windows/Control/ReBar.h new file mode 100644 index 0000000000..26fa311053 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ReBar.h @@ -0,0 +1,34 @@ +// Windows/Control/ReBar.h + +#ifndef __WINDOWS_CONTROL_REBAR_H +#define __WINDOWS_CONTROL_REBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CReBar: public NWindows::CWindow +{ +public: + bool SetBarInfo(LPREBARINFO barInfo) + { return LRESULTToBool(SendMsg(RB_SETBARINFO, 0, (LPARAM)barInfo)); } + bool InsertBand(int index, LPREBARBANDINFO bandInfo) + { return LRESULTToBool(SendMsg(RB_INSERTBAND, index, (LPARAM)bandInfo)); } + bool SetBandInfo(unsigned index, LPREBARBANDINFO bandInfo) + { return LRESULTToBool(SendMsg(RB_SETBANDINFO, index, (LPARAM)bandInfo)); } + void MaximizeBand(unsigned index, bool ideal) + { SendMsg(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); } + bool SizeToRect(LPRECT rect) + { return LRESULTToBool(SendMsg(RB_SIZETORECT, 0, (LPARAM)rect)); } + UINT GetHeight() + { return (UINT)SendMsg(RB_GETBARHEIGHT); } + UINT GetBandCount() + { return (UINT)SendMsg(RB_GETBANDCOUNT); } + bool DeleteBand(UINT index) + { return LRESULTToBool(SendMsg(RB_DELETEBAND, index)); } +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/Static.h b/other-licenses/7zstub/src/CPP/Windows/Control/Static.h new file mode 100644 index 0000000000..936dd3c881 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/Static.h @@ -0,0 +1,28 @@ +// Windows/Control/Static.h + +#ifndef __WINDOWS_CONTROL_STATIC_H +#define __WINDOWS_CONTROL_STATIC_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CStatic: public CWindow +{ +public: + HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMsg(STM_SETIMAGE, imageType, (LPARAM)handle); } + HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMsg(STM_GETIMAGE, imageType, 0); } + + #ifdef UNDER_CE + HICON SetIcon(HICON icon) { return (HICON)SetImage(IMAGE_ICON, icon); } + HICON GetIcon() { return (HICON)GetImage(IMAGE_ICON); } + #else + HICON SetIcon(HICON icon) { return (HICON)SendMsg(STM_SETICON, (WPARAM)icon, 0); } + HICON GetIcon() { return (HICON)SendMsg(STM_GETICON, 0, 0); } + #endif +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/StatusBar.h b/other-licenses/7zstub/src/CPP/Windows/Control/StatusBar.h new file mode 100644 index 0000000000..7f7d66b0bf --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/StatusBar.h @@ -0,0 +1,42 @@ +// Windows/Control/StatusBar.h + +#ifndef __WINDOWS_CONTROL_STATUSBAR_H +#define __WINDOWS_CONTROL_STATUSBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CStatusBar: public NWindows::CWindow +{ +public: + bool Create(LONG style, LPCTSTR text, HWND hwndParent, UINT id) + { return (_window = ::CreateStatusWindow(style, text, hwndParent, id)) != 0; } + bool SetText(LPCTSTR text) + { return CWindow::SetText(text); } + bool SetText(unsigned index, LPCTSTR text, UINT type) + { return LRESULTToBool(SendMsg(SB_SETTEXT, index | type, (LPARAM)text)); } + bool SetText(unsigned index, LPCTSTR text) + { return SetText(index, text, 0); } + + #ifndef _UNICODE + bool Create(LONG style, LPCWSTR text, HWND hwndParent, UINT id) + { return (_window = ::CreateStatusWindowW(style, text, hwndParent, id)) != 0; } + bool SetText(LPCWSTR text) + { return CWindow::SetText(text); } + bool SetText(unsigned index, LPCWSTR text, UINT type) + { return LRESULTToBool(SendMsg(SB_SETTEXTW, index | type, (LPARAM)text)); } + bool SetText(unsigned index, LPCWSTR text) + { return SetText(index, text, 0); } + #endif + + bool SetParts(unsigned numParts, const int *edgePostions) + { return LRESULTToBool(SendMsg(SB_SETPARTS, numParts, (LPARAM)edgePostions)); } + void Simple(bool simple) + { SendMsg(SB_SIMPLE, BoolToBOOL(simple), 0); } +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/StdAfx.h b/other-licenses/7zstub/src/CPP/Windows/Control/StdAfx.h new file mode 100644 index 0000000000..42a088f121 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/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/Windows/Control/ToolBar.h b/other-licenses/7zstub/src/CPP/Windows/Control/ToolBar.h new file mode 100644 index 0000000000..02ed9a1423 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/ToolBar.h @@ -0,0 +1,43 @@ +// Windows/Control/ToolBar.h + +#ifndef __WINDOWS_CONTROL_TOOLBAR_H +#define __WINDOWS_CONTROL_TOOLBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CToolBar: public NWindows::CWindow +{ +public: + void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); } + DWORD GetButtonSize() { return (DWORD)SendMsg(TB_GETBUTTONSIZE, 0, 0); } + + bool GetMaxSize(LPSIZE size) + #ifdef UNDER_CE + { + // maybe it must be fixed for more than 1 buttons + DWORD val = GetButtonSize(); + size->cx = LOWORD(val); + size->cy = HIWORD(val); + return true; + } + #else + { + return LRESULTToBool(SendMsg(TB_GETMAXSIZE, 0, (LPARAM)size)); + } + #endif + + bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMsg(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); } + void ButtonStructSize() { SendMsg(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); } + HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMsg(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); } + bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); } + #ifndef _UNICODE + bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); } + #endif +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/Trackbar.h b/other-licenses/7zstub/src/CPP/Windows/Control/Trackbar.h new file mode 100644 index 0000000000..afc9bf25c5 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/Trackbar.h @@ -0,0 +1,27 @@ +// Windows/Control/Trackbar.h + +#ifndef __WINDOWS_CONTROL_TRACKBAR_H +#define __WINDOWS_CONTROL_TRACKBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CTrackbar: public CWindow +{ +public: + void SetRange(int minimum, int maximum, bool redraw = true) + { SendMsg(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); } + void SetPos(int pos, bool redraw = true) + { SendMsg(TBM_SETPOS, BoolToBOOL(redraw), pos); } + void SetTicFreq(int freq) + { SendMsg(TBM_SETTICFREQ, freq); } + + int GetPos() + { return (int)SendMsg(TBM_GETPOS); } +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/Window2.cpp b/other-licenses/7zstub/src/CPP/Windows/Control/Window2.cpp new file mode 100644 index 0000000000..b6e6d67daf --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/Window2.cpp @@ -0,0 +1,200 @@ +// Windows/Control/Window2.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +#include "Window2.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef _UNICODE +ATOM MyRegisterClass(CONST WNDCLASSW *wndClass); +#endif + +namespace NControl { + +#ifdef UNDER_CE +#define MY_START_WM_CREATE WM_CREATE +#else +#define MY_START_WM_CREATE WM_NCCREATE +#endif + +static LRESULT CALLBACK WindowProcedure(HWND aHWND, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempWindow(aHWND); + if (message == MY_START_WM_CREATE) + tempWindow.SetUserDataLongPtr((LONG_PTR)(((LPCREATESTRUCT)lParam)->lpCreateParams)); + CWindow2 *window = (CWindow2 *)(tempWindow.GetUserDataLongPtr()); + if (window != NULL && message == MY_START_WM_CREATE) + window->Attach(aHWND); + if (window == 0) + { + #ifndef _UNICODE + if (g_IsNT) + return DefWindowProcW(aHWND, message, wParam, lParam); + else + #endif + return DefWindowProc(aHWND, message, wParam, lParam); + } + return window->OnMessage(message, wParam, lParam); +} + +bool CWindow2::CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName, + DWORD style, int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance) +{ + WNDCLASS wc; + if (!::GetClassInfo(instance, className, &wc)) + { + // wc.style = CS_HREDRAW | CS_VREDRAW; + wc.style = 0; + wc.lpfnWndProc = WindowProcedure; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = instance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = className; + if (::RegisterClass(&wc) == 0) + return false; + } + return CWindow::CreateEx(exStyle, className, windowName, style, + x, y, width, height, parentWindow, idOrHMenu, instance, this); +} + +#ifndef _UNICODE + +bool CWindow2::CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName, + DWORD style, int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance) +{ + bool needRegister; + if (g_IsNT) + { + WNDCLASSW wc; + needRegister = ::GetClassInfoW(instance, className, &wc) == 0; + } + else + { + WNDCLASSA windowClassA; + AString classNameA; + LPCSTR classNameP; + if (IS_INTRESOURCE(className)) + classNameP = (LPCSTR)className; + else + { + classNameA = GetSystemString(className); + classNameP = classNameA; + } + needRegister = ::GetClassInfoA(instance, classNameP, &windowClassA) == 0; + } + if (needRegister) + { + WNDCLASSW wc; + // wc.style = CS_HREDRAW | CS_VREDRAW; + wc.style = 0; + wc.lpfnWndProc = WindowProcedure; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = instance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = className; + if (MyRegisterClass(&wc) == 0) + return false; + } + return CWindow::CreateEx(exStyle, className, windowName, style, + x, y, width, height, parentWindow, idOrHMenu, instance, this); +} + +#endif + +LRESULT CWindow2::DefProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + #ifndef _UNICODE + if (g_IsNT) + return DefWindowProcW(_window, message, wParam, lParam); + else + #endif + return DefWindowProc(_window, message, wParam, lParam); +} + +LRESULT CWindow2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT result; + switch (message) + { + case WM_CREATE: + if (!OnCreate((CREATESTRUCT *)lParam)) + return -1; + break; + case WM_COMMAND: + if (OnCommand(wParam, lParam, result)) + return result; + break; + case WM_NOTIFY: + if (OnNotify((UINT)wParam, (LPNMHDR) lParam, result)) + return result; + break; + case WM_DESTROY: + OnDestroy(); + break; + case WM_CLOSE: + OnClose(); + return 0; + case WM_SIZE: + if (OnSize(wParam, LOWORD(lParam), HIWORD(lParam))) + return 0; + } + return DefProc(message, wParam, lParam); +} + +bool CWindow2::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result) +{ + return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam, result); +} + +bool CWindow2::OnCommand(int /* code */, int /* itemID */, LPARAM /* lParam */, LRESULT & /* result */) +{ + return false; + // return DefProc(message, wParam, lParam); + /* + if (code == BN_CLICKED) + return OnButtonClicked(itemID, (HWND)lParam); + */ +} + +/* +bool CDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + case IDOK: + OnOK(); + break; + case IDCANCEL: + OnCancel(); + break; + case IDHELP: + OnHelp(); + break; + default: + return false; + } + return true; +} + +*/ + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Control/Window2.h b/other-licenses/7zstub/src/CPP/Windows/Control/Window2.h new file mode 100644 index 0000000000..d632b86fea --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Control/Window2.h @@ -0,0 +1,51 @@ +// Windows/Control/Window2.h + +#ifndef __WINDOWS_CONTROL_WINDOW2_H +#define __WINDOWS_CONTROL_WINDOW2_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CWindow2: public CWindow +{ + LRESULT DefProc(UINT message, WPARAM wParam, LPARAM lParam); +public: + CWindow2(HWND newWindow = NULL): CWindow(newWindow){}; + virtual ~CWindow2() {}; + + bool CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName, + DWORD style, int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance); + + #ifndef _UNICODE + bool CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName, + DWORD style, int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance); + #endif + + virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnCreate(CREATESTRUCT * /* createStruct */) { return true; } + // virtual LRESULT OnCommand(WPARAM wParam, LPARAM lParam); + virtual bool OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result); + virtual bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result); + virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; } + virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */, LRESULT & /* result */) { return false; } + virtual void OnDestroy() { PostQuitMessage(0); } + virtual void OnClose() { Destroy(); } + /* + virtual LRESULT OnHelp(LPHELPINFO helpInfo) { OnHelp(); } + virtual LRESULT OnHelp() {}; + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK() {}; + virtual void OnCancel() {}; + */ + + LONG_PTR SetMsgResult(LONG_PTR newLongPtr) { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); } + LONG_PTR GetMsgResult() const { return GetLongPtr(DWLP_MSGRESULT); } +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/DLL.cpp b/other-licenses/7zstub/src/CPP/Windows/DLL.cpp new file mode 100644 index 0000000000..efee379b7e --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/DLL.cpp @@ -0,0 +1,109 @@ +// Windows/DLL.cpp + +#include "StdAfx.h" + +#include "DLL.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +extern HINSTANCE g_hInstance; + +namespace NWindows { +namespace NDLL { + +bool CLibrary::Free() throw() +{ + if (_module == 0) + return true; + if (!::FreeLibrary(_module)) + return false; + _module = 0; + return true; +} + +bool CLibrary::LoadEx(CFSTR path, DWORD flags) throw() +{ + if (!Free()) + return false; + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibraryEx(fs2fas(path), NULL, flags); + } + else + #endif + { + _module = ::LoadLibraryExW(fs2us(path), NULL, flags); + } + return (_module != NULL); +} + +bool CLibrary::Load(CFSTR path) throw() +{ + if (!Free()) + return false; + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibrary(fs2fas(path)); + } + else + #endif + { + _module = ::LoadLibraryW(fs2us(path)); + } + return (_module != NULL); +} + +bool MyGetModuleFileName(FString &path) +{ + HMODULE hModule = g_hInstance; + path.Empty(); + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = fas2fs(s); + return true; + } + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = us2fs(s); + return true; + } + } + return false; +} + +#ifndef _SFX + +FString GetModuleDirPrefix() +{ + FString s; + if (MyGetModuleFileName(s)) + { + int pos = s.ReverseFind_PathSepar(); + if (pos >= 0) + s.DeleteFrom(pos + 1); + } + if (s.IsEmpty()) + s = "." STRING_PATH_SEPARATOR; + return s; +} + +#endif + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/DLL.h b/other-licenses/7zstub/src/CPP/Windows/DLL.h new file mode 100644 index 0000000000..58bcf19549 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/DLL.h @@ -0,0 +1,58 @@ +// Windows/DLL.h + +#ifndef __WINDOWS_DLL_H +#define __WINDOWS_DLL_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NDLL { + +#ifdef UNDER_CE +#define My_GetProcAddress(module, procName) ::GetProcAddressA(module, procName) +#else +#define My_GetProcAddress(module, procName) ::GetProcAddress(module, procName) +#endif + +/* Win32: Don't call CLibrary::Free() and FreeLibrary() from another + FreeLibrary() code: detaching code in DLL entry-point or in + destructors of global objects in DLL module. */ + +class CLibrary +{ + HMODULE _module; + + // CLASS_NO_COPY(CLibrary); +public: + CLibrary(): _module(NULL) {}; + ~CLibrary() { Free(); } + + operator HMODULE() const { return _module; } + HMODULE* operator&() { return &_module; } + bool IsLoaded() const { return (_module != NULL); } + + void Attach(HMODULE m) + { + Free(); + _module = m; + } + HMODULE Detach() + { + HMODULE m = _module; + _module = NULL; + return m; + } + + bool Free() throw(); + bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw(); + bool Load(CFSTR path) throw(); + FARPROC GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } +}; + +bool MyGetModuleFileName(FString &path); + +FString GetModuleDirPrefix(); + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Defs.h b/other-licenses/7zstub/src/CPP/Windows/Defs.h new file mode 100644 index 0000000000..f3d692f3dd --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Defs.h @@ -0,0 +1,17 @@ +// Windows/Defs.h + +#ifndef __WINDOWS_DEFS_H +#define __WINDOWS_DEFS_H + +#include "../Common/MyWindows.h" + +#ifdef _WIN32 +inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); } +inline bool BOOLToBool(BOOL v) { return (v != FALSE); } +inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); } +#endif + +inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); } +inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); } + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/ErrorMsg.cpp b/other-licenses/7zstub/src/CPP/Windows/ErrorMsg.cpp new file mode 100644 index 0000000000..6434ec2f7d --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/ErrorMsg.cpp @@ -0,0 +1,66 @@ +// Windows/ErrorMsg.h + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "ErrorMsg.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NError { + +static bool MyFormatMessage(DWORD errorCode, UString &message) +{ + LPVOID msgBuf; + #ifndef _UNICODE + if (!g_IsNT) + { + if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0) + return false; + message = GetUnicodeString((LPCTSTR)msgBuf); + } + else + #endif + { + if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) + return false; + message = (LPCWSTR)msgBuf; + } + ::LocalFree(msgBuf); + return true; +} + +UString MyFormatMessage(DWORD errorCode) +{ + UString m; + if (!MyFormatMessage(errorCode, m) || m.IsEmpty()) + { + char s[16]; + for (int i = 0; i < 8; i++) + { + unsigned t = errorCode & 0xF; + errorCode >>= 4; + s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[8] = 0; + m += "Error #"; + m += s; + } + else if (m.Len() >= 2 + && m[m.Len() - 1] == 0x0A + && m[m.Len() - 2] == 0x0D) + m.DeleteFrom(m.Len() - 2); + return m; +} + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/ErrorMsg.h b/other-licenses/7zstub/src/CPP/Windows/ErrorMsg.h new file mode 100644 index 0000000000..e05e950438 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/ErrorMsg.h @@ -0,0 +1,15 @@ +// Windows/ErrorMsg.h + +#ifndef __WINDOWS_ERROR_MSG_H +#define __WINDOWS_ERROR_MSG_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NError { + +UString MyFormatMessage(DWORD errorCode); + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/FileDir.cpp b/other-licenses/7zstub/src/CPP/Windows/FileDir.cpp new file mode 100644 index 0000000000..124569e3f5 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileDir.cpp @@ -0,0 +1,714 @@ +// Windows/FileDir.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "FileDir.h" +#include "FileFind.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +namespace NWindows { +namespace NFile { +namespace NDir { + +#ifndef UNDER_CE + +bool GetWindowsDir(FString &path) +{ + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectory(s, MAX_PATH + 1); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +bool GetSystemDir(FString &path) +{ + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectory(s, MAX_PATH + 1); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); +} +#endif + +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + #endif + + HANDLE hDir = INVALID_HANDLE_VALUE; + IF_USE_MAIN_PATH + hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + #ifdef WIN_LONG_PATH + if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + } + #endif + + bool res = false; + if (hDir != INVALID_HANDLE_VALUE) + { + res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); + ::CloseHandle(hDir); + } + return res; +} + +bool SetFileAttrib(CFSTR path, DWORD attrib) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::SetFileAttributes(fs2fas(path), attrib)) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::SetFileAttributesW(fs2us(path), attrib)) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return BOOLToBool(::SetFileAttributesW(superPath, attrib)); + } + #endif + } + return false; +} + + +bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) +{ + if ((attrib & 0xF0000000) != 0) + attrib &= 0x3FFF; + return SetFileAttrib(path, attrib); +} + + +bool RemoveDir(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::RemoveDirectory(fs2fas(path))) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::RemoveDirectoryW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return BOOLToBool(::RemoveDirectoryW(superPath)); + } + #endif + } + return false; +} + +bool MyMoveFile(CFSTR oldFile, CFSTR newFile) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::MoveFile(fs2fas(oldFile), fs2fas(newFile))) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH_2(oldFile, newFile) + if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(::MoveFileW(d1, d2)); + } + #endif + } + return false; +} + +#ifndef UNDER_CE + +EXTERN_C_BEGIN +typedef BOOL (WINAPI *Func_CreateHardLinkW)( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); +EXTERN_C_END + +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + /* + if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL)) + return true; + */ + } + else + #endif + { + Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW) + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); + if (!my_CreateHardLinkW) + return false; + IF_USE_MAIN_PATH_2(newFileName, existFileName) + if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL)); + } + #endif + } + return false; +} + +#endif + +/* +WinXP-64 CreateDir(): + "" - ERROR_PATH_NOT_FOUND + \ - ERROR_ACCESS_DENIED + C:\ - ERROR_ACCESS_DENIED, if there is such drive, + + D:\folder - ERROR_PATH_NOT_FOUND, if there is no such drive, + C:\nonExistent\folder - ERROR_PATH_NOT_FOUND + + C:\existFolder - ERROR_ALREADY_EXISTS + C:\existFolder\ - ERROR_ALREADY_EXISTS + + C:\folder - OK + C:\folder\ - OK + + \\Server\nonExistent - ERROR_BAD_NETPATH + \\Server\Share_Readonly - ERROR_ACCESS_DENIED + \\Server\Share - ERROR_ALREADY_EXISTS + + \\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED + \\Server\Share_FAT_drive - ERROR_ALREADY_EXISTS +*/ + +bool CreateDir(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::CreateDirectory(fs2fas(path), NULL)) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::CreateDirectoryW(fs2us(path), NULL)) + return true; + #ifdef WIN_LONG_PATH + if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return BOOLToBool(::CreateDirectoryW(superPath, NULL)); + } + #endif + } + return false; +} + +/* + CreateDir2 returns true, if directory can contain files after the call (two cases): + 1) the directory already exists + 2) the directory was created + path must be WITHOUT trailing path separator. + + We need CreateDir2, since fileInfo.Find() for reserved names like "com8" + returns FILE instead of DIRECTORY. And we need to use SuperPath */ + +static bool CreateDir2(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::CreateDirectory(fs2fas(path), NULL)) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::CreateDirectoryW(fs2us(path), NULL)) + return true; + #ifdef WIN_LONG_PATH + if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + { + if (::CreateDirectoryW(superPath, NULL)) + return true; + if (::GetLastError() != ERROR_ALREADY_EXISTS) + return false; + NFind::CFileInfo fi; + if (!fi.Find(us2fs(superPath))) + return false; + return fi.IsDir(); + } + } + #endif + } + if (::GetLastError() != ERROR_ALREADY_EXISTS) + return false; + NFind::CFileInfo fi; + if (!fi.Find(path)) + return false; + return fi.IsDir(); +} + +bool CreateComplexDir(CFSTR _path) +{ + #ifdef _WIN32 + + { + DWORD attrib = NFind::GetFileAttrib(_path); + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + return true; + } + + #ifndef UNDER_CE + + if (IsDriveRootPath_SuperAllowed(_path)) + return false; + + unsigned prefixSize = GetRootPrefixSize(_path); + + #endif + + #endif + + FString path (_path); + + int pos = path.ReverseFind_PathSepar(); + if (pos >= 0 && (unsigned)pos == path.Len() - 1) + { + if (path.Len() == 1) + return true; + path.DeleteBack(); + } + + const FString path2 (path); + pos = path.Len(); + + for (;;) + { + if (CreateDir2(path)) + break; + if (::GetLastError() == ERROR_ALREADY_EXISTS) + return false; + pos = path.ReverseFind_PathSepar(); + if (pos < 0 || pos == 0) + return false; + + #if defined(_WIN32) && !defined(UNDER_CE) + if (pos == 1 && IS_PATH_SEPAR(path[0])) + return false; + if (prefixSize >= (unsigned)pos + 1) + return false; + #endif + + path.DeleteFrom(pos); + } + + while (pos < (int)path2.Len()) + { + int pos2 = NName::FindSepar(path2.Ptr(pos + 1)); + if (pos2 < 0) + pos = path2.Len(); + else + pos += 1 + pos2; + path.SetFrom(path2, pos); + if (!CreateDir(path)) + return false; + } + + return true; +} + +bool DeleteFileAlways(CFSTR path) +{ + /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete. + SetFileAttrib("name:stream", ) changes attributes of main file. */ + { + DWORD attrib = NFind::GetFileAttrib(path); + if (attrib != INVALID_FILE_ATTRIBUTES + && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0 + && (attrib & FILE_ATTRIBUTE_READONLY) != 0) + { + if (!SetFileAttrib(path, attrib & ~FILE_ATTRIBUTE_READONLY)) + return false; + } + } + + #ifndef _UNICODE + if (!g_IsNT) + { + if (::DeleteFile(fs2fas(path))) + return true; + } + else + #endif + { + /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")). + Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */ + IF_USE_MAIN_PATH + if (::DeleteFileW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return BOOLToBool(::DeleteFileW(superPath)); + } + #endif + } + return false; +} + +bool RemoveDirWithSubItems(const FString &path) +{ + bool needRemoveSubItems = true; + { + NFind::CFileInfo fi; + if (!fi.Find(path)) + return false; + if (!fi.IsDir()) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + if (fi.HasReparsePoint()) + needRemoveSubItems = false; + } + + if (needRemoveSubItems) + { + FString s (path); + s.Add_PathSepar(); + const unsigned prefixSize = s.Len(); + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(s); + NFind::CFileInfo fi; + while (enumerator.Next(fi)) + { + s.DeleteFrom(prefixSize); + s += fi.Name; + if (fi.IsDir()) + { + if (!RemoveDirWithSubItems(s)) + return false; + } + else if (!DeleteFileAlways(s)) + return false; + } + } + + if (!SetFileAttrib(path, 0)) + return false; + return RemoveDir(path); +} + +#ifdef UNDER_CE + +bool MyGetFullPathName(CFSTR path, FString &resFullPath) +{ + resFullPath = path; + return true; +} + +#else + +bool MyGetFullPathName(CFSTR path, FString &resFullPath) +{ + return GetFullPath(path, resFullPath); +} + +bool SetCurrentDir(CFSTR path) +{ + // SetCurrentDirectory doesn't support \\?\ prefix + #ifndef _UNICODE + if (!g_IsNT) + { + return BOOLToBool(::SetCurrentDirectory(fs2fas(path))); + } + else + #endif + { + return BOOLToBool(::SetCurrentDirectoryW(fs2us(path))); + } +} + +bool GetCurrentDir(FString &path) +{ + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +#endif + +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) +{ + bool res = MyGetFullPathName(path, resDirPrefix); + if (!res) + resDirPrefix = path; + int pos = resDirPrefix.ReverseFind_PathSepar(); + resFileName = resDirPrefix.Ptr(pos + 1); + resDirPrefix.DeleteFrom(pos + 1); + return res; +} + +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) +{ + FString resFileName; + return GetFullPathAndSplit(path, resDirPrefix, resFileName); +} + +bool MyGetTempPath(FString &path) +{ + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPath(MAX_PATH + 1, s); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPathW(MAX_PATH + 1, s);; + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) +{ + UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + for (unsigned i = 0; i < 100; i++) + { + path = prefix; + if (addRandom) + { + char s[16]; + UInt32 val = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = val & 0xF; + val >>= 4; + s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + if (outFile) + path += '.'; + path += s; + UInt32 step = GetTickCount() + 2; + if (step == 0) + step = 1; + d += step; + } + addRandom = true; + if (outFile) + path += ".tmp"; + if (NFind::DoesFileOrDirExist(path)) + { + SetLastError(ERROR_ALREADY_EXISTS); + continue; + } + if (outFile) + { + if (outFile->Create(path, false)) + return true; + } + else + { + if (CreateDir(path)) + return true; + } + DWORD error = GetLastError(); + if (error != ERROR_FILE_EXISTS && + error != ERROR_ALREADY_EXISTS) + break; + } + path.Empty(); + return false; +} + +bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) +{ + if (!Remove()) + return false; + if (!CreateTempFile(prefix, false, _path, outFile)) + return false; + _mustBeDeleted = true; + return true; +} + +bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile) +{ + if (!Remove()) + return false; + FString tempPath; + if (!MyGetTempPath(tempPath)) + return false; + if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile)) + return false; + _mustBeDeleted = true; + return true; +} + +bool CTempFile::Remove() +{ + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !DeleteFileAlways(_path); + return !_mustBeDeleted; +} + +bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) +{ + // DWORD attrib = 0; + if (deleteDestBefore) + { + if (NFind::DoesFileExist(name)) + { + // attrib = NFind::GetFileAttrib(name); + if (!DeleteFileAlways(name)) + return false; + } + } + DisableDeleting(); + return MyMoveFile(_path, name); + + /* + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) + { + DWORD attrib2 = NFind::GetFileAttrib(name); + if (attrib2 != INVALID_FILE_ATTRIBUTES) + SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY); + } + */ +} + +bool CTempDir::Create(CFSTR prefix) +{ + if (!Remove()) + return false; + FString tempPath; + if (!MyGetTempPath(tempPath)) + return false; + if (!CreateTempFile(tempPath + prefix, true, _path, NULL)) + return false; + _mustBeDeleted = true; + return true; +} + +bool CTempDir::Remove() +{ + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !RemoveDirWithSubItems(_path); + return !_mustBeDeleted; +} + +}}} diff --git a/other-licenses/7zstub/src/CPP/Windows/FileDir.h b/other-licenses/7zstub/src/CPP/Windows/FileDir.h new file mode 100644 index 0000000000..8d2b56a6aa --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileDir.h @@ -0,0 +1,117 @@ +// Windows/FileDir.h + +#ifndef __WINDOWS_FILE_DIR_H +#define __WINDOWS_FILE_DIR_H + +#include "../Common/MyString.h" + +#include "FileIO.h" + +namespace NWindows { +namespace NFile { +namespace NDir { + +bool GetWindowsDir(FString &path); +bool GetSystemDir(FString &path); + +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); + + +bool SetFileAttrib(CFSTR path, DWORD attrib); + +/* + Some programs store posix attributes in high 16 bits of windows attributes field. + Also some programs use additional flag markers: 0x8000 or 0x4000. + SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute + bits that are related to current system only. +*/ + +bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib); + + +bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); + +#ifndef UNDER_CE +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); +#endif + +bool RemoveDir(CFSTR path); +bool CreateDir(CFSTR path); + +/* CreateComplexDir returns true, if directory can contain files after the call (two cases): + 1) the directory already exists (network shares and drive paths are supported) + 2) the directory was created + path can be WITH or WITHOUT trailing path separator. */ + +bool CreateComplexDir(CFSTR path); + +bool DeleteFileAlways(CFSTR name); +bool RemoveDirWithSubItems(const FString &path); + +bool MyGetFullPathName(CFSTR path, FString &resFullPath); +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix); + +#ifndef UNDER_CE + +bool SetCurrentDir(CFSTR path); +bool GetCurrentDir(FString &resultPath); + +#endif + +bool MyGetTempPath(FString &resultPath); + +class CTempFile +{ + bool _mustBeDeleted; + FString _path; + void DisableDeleting() { _mustBeDeleted = false; } +public: + CTempFile(): _mustBeDeleted(false) {} + ~CTempFile() { Remove(); } + const FString &GetPath() const { return _path; } + bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix + bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); + bool Remove(); + bool MoveTo(CFSTR name, bool deleteDestBefore); +}; + +class CTempDir +{ + bool _mustBeDeleted; + FString _path; +public: + CTempDir(): _mustBeDeleted(false) {} + ~CTempDir() { Remove(); } + const FString &GetPath() const { return _path; } + void DisableDeleting() { _mustBeDeleted = false; } + bool Create(CFSTR namePrefix) ; + bool Remove(); +}; + +#if !defined(UNDER_CE) +class CCurrentDirRestorer +{ + FString _path; +public: + bool NeedRestore; + + CCurrentDirRestorer(): NeedRestore(true) + { + GetCurrentDir(_path); + } + ~CCurrentDirRestorer() + { + if (!NeedRestore) + return; + FString s; + if (GetCurrentDir(s)) + if (s != _path) + SetCurrentDir(_path); + } +}; +#endif + +}}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/FileFind.cpp b/other-licenses/7zstub/src/CPP/Windows/FileFind.cpp new file mode 100644 index 0000000000..8c6255bda5 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileFind.cpp @@ -0,0 +1,749 @@ +// Windows/FileFind.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "FileFind.h" +#include "FileIO.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +#if defined(_WIN32) && !defined(UNDER_CE) + +EXTERN_C_BEGIN + +typedef enum +{ + My_FindStreamInfoStandard, + My_FindStreamInfoMaxInfoLevel +} MY_STREAM_INFO_LEVELS; + +typedef struct +{ + LARGE_INTEGER StreamSize; + WCHAR cStreamName[MAX_PATH + 36]; +} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA; + +typedef WINBASEAPI HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel, + LPVOID findStreamData, DWORD flags); + +typedef WINBASEAPI BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData); + +EXTERN_C_END + +#endif + +namespace NWindows { +namespace NFile { + +#ifdef SUPPORT_DEVICE_FILE +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif + +namespace NFind { + +bool CFileInfo::IsDots() const throw() +{ + if (!IsDir() || Name.IsEmpty()) + return false; + if (Name[0] != '.') + return false; + return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.'); +} + +#define WIN_FD_TO_MY_FI(fi, fd) \ + fi.Attrib = fd.dwFileAttributes; \ + fi.CTime = fd.ftCreationTime; \ + fi.ATime = fd.ftLastAccessTime; \ + fi.MTime = fd.ftLastWriteTime; \ + fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \ + fi.IsAltStream = false; \ + fi.IsDevice = false; + + /* + #ifdef UNDER_CE + fi.ObjectID = fd.dwOID; + #else + fi.ReparseTag = fd.dwReserved0; + #endif + */ + +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi) +{ + WIN_FD_TO_MY_FI(fi, fd); + fi.Name = us2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = us2fs(fd.cAlternateFileName); + #endif +} + +#ifndef _UNICODE + +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) +{ + WIN_FD_TO_MY_FI(fi, fd); + fi.Name = fas2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = fas2fs(fd.cAlternateFileName); + #endif +} +#endif + +//////////////////////////////// +// CFindFile + +bool CFindFileBase::Close() throw() +{ + if (_handle == INVALID_HANDLE_VALUE) + return true; + if (!::FindClose(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + +/* +WinXP-64 FindFirstFile(): + "" - ERROR_PATH_NOT_FOUND + folder\ - ERROR_FILE_NOT_FOUND + \ - ERROR_FILE_NOT_FOUND + c:\ - ERROR_FILE_NOT_FOUND + c: - ERROR_FILE_NOT_FOUND, if current dir is ROOT ( c:\ ) + c: - OK, if current dir is NOT ROOT ( c:\folder ) + folder - OK + + \\ - ERROR_INVALID_NAME + \\Server - ERROR_INVALID_NAME + \\Server\ - ERROR_INVALID_NAME + + \\Server\Share - ERROR_BAD_NETPATH + \\Server\Share - ERROR_BAD_NET_NAME (Win7). + !!! There is problem : Win7 makes some requests for "\\Server\Shar" (look in Procmon), + when we call it for "\\Server\Share" + + \\Server\Share\ - ERROR_FILE_NOT_FOUND + + \\?\UNC\Server\Share - ERROR_INVALID_NAME + \\?\UNC\Server\Share - ERROR_BAD_PATHNAME (Win7) + \\?\UNC\Server\Share\ - ERROR_FILE_NOT_FOUND + + \\Server\Share_RootDrive - ERROR_INVALID_NAME + \\Server\Share_RootDrive\ - ERROR_INVALID_NAME + + c:\* - ERROR_FILE_NOT_FOUND, if thare are no item in that folder +*/ + +bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi) +{ + if (!Close()) + return false; + #ifndef _UNICODE + if (!g_IsNT) + { + WIN32_FIND_DATAA fd; + _handle = ::FindFirstFileA(fs2fas(path), &fd); + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + else + #endif + { + WIN32_FIND_DATAW fd; + + IF_USE_MAIN_PATH + _handle = ::FindFirstFileW(fs2us(path), &fd); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = ::FindFirstFileW(superPath, &fd); + } + #endif + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + return true; +} + +bool CFindFile::FindNext(CFileInfo &fi) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + WIN32_FIND_DATAA fd; + if (!::FindNextFileA(_handle, &fd)) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + else + #endif + { + WIN32_FIND_DATAW fd; + if (!::FindNextFileW(_handle, &fd)) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + return true; +} + +#if defined(_WIN32) && !defined(UNDER_CE) + +//////////////////////////////// +// AltStreams + +static FindFirstStreamW_Ptr g_FindFirstStreamW; +static FindNextStreamW_Ptr g_FindNextStreamW; + +struct CFindStreamLoader +{ + CFindStreamLoader() + { + g_FindFirstStreamW = (FindFirstStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindFirstStreamW"); + g_FindNextStreamW = (FindNextStreamW_Ptr)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "FindNextStreamW"); + } +} g_FindStreamLoader; + +bool CStreamInfo::IsMainStream() const throw() +{ + return StringsAreEqualNoCase_Ascii(Name, "::$DATA"); +}; + +UString CStreamInfo::GetReducedName() const +{ + // remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA" + UString s (Name); + if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA")) + s.DeleteFrom(s.Len() - 6); + return s; +} + +/* +UString CStreamInfo::GetReducedName2() const +{ + UString s = GetReducedName(); + if (!s.IsEmpty() && s[0] == ':') + s.Delete(0); + return s; +} +*/ + +static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si) +{ + si.Size = sd.StreamSize.QuadPart; + si.Name = sd.cStreamName; +} + +/* + WinXP-64 FindFirstStream(): + "" - ERROR_PATH_NOT_FOUND + folder\ - OK + folder - OK + \ - OK + c:\ - OK + c: - OK, if current dir is ROOT ( c:\ ) + c: - OK, if current dir is NOT ROOT ( c:\folder ) + \\Server\Share - OK + \\Server\Share\ - OK + + \\ - ERROR_INVALID_NAME + \\Server - ERROR_INVALID_NAME + \\Server\ - ERROR_INVALID_NAME +*/ + +bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si) +{ + if (!Close()) + return false; + if (!g_FindFirstStreamW) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + SetLastError(0); + IF_USE_MAIN_PATH + _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0); + if (_handle == INVALID_HANDLE_VALUE) + { + if (::GetLastError() == ERROR_HANDLE_EOF) + return false; + // long name can be tricky for path like ".\dirName". + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = g_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0); + } + #endif + } + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); + } + return true; +} + +bool CFindStream::FindNext(CStreamInfo &si) +{ + if (!g_FindNextStreamW) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + if (!g_FindNextStreamW(_handle, &sd)) + return false; + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); + } + return true; +} + +bool CStreamEnumerator::Next(CStreamInfo &si, bool &found) +{ + bool res; + if (_find.IsHandleAllocated()) + res = _find.FindNext(si); + else + res = _find.FindFirst(_filePath, si); + if (res) + { + found = true; + return true; + } + found = false; + return (::GetLastError() == ERROR_HANDLE_EOF); +} + +#endif + + +#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; + +void CFileInfoBase::ClearBase() throw() +{ + Size = 0; + MY_CLEAR_FILETIME(CTime); + MY_CLEAR_FILETIME(ATime); + MY_CLEAR_FILETIME(MTime); + Attrib = 0; + IsAltStream = false; + IsDevice = false; +} + +/* +WinXP-64 GetFileAttributes(): + If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code + + \ - OK + C:\ - OK, if there is such drive, + D:\ - ERROR_PATH_NOT_FOUND, if there is no such drive, + + C:\folder - OK + C:\folder\ - OK + C:\folderBad - ERROR_FILE_NOT_FOUND + + \\Server\BadShare - ERROR_BAD_NETPATH + \\Server\Share - WORKS OK, but MSDN says: + GetFileAttributes for a network share, the function fails, and GetLastError + returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share. +*/ + +DWORD GetFileAttrib(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + return ::GetFileAttributes(fs2fas(path)); + else + #endif + { + IF_USE_MAIN_PATH + { + DWORD dw = ::GetFileAttributesW(fs2us(path)); + if (dw != INVALID_FILE_ATTRIBUTES) + return dw; + } + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return ::GetFileAttributesW(superPath); + } + #endif + return INVALID_FILE_ATTRIBUTES; + } +} + +/* if path is "c:" or "c::" then CFileInfo::Find() returns name of current folder for that disk + so instead of absolute path we have relative path in Name. That is not good in some calls */ + +/* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */ + +/* CFileInfo::Find() +We alow the following paths (as FindFirstFile): + C:\folder + c: - if current dir is NOT ROOT ( c:\folder ) + +also we support paths that are not supported by FindFirstFile: + \ + \\.\c: + c:\ - Name will be without tail slash ( c: ) + \\?\c:\ - Name will be without tail slash ( c: ) + \\Server\Share + \\?\UNC\Server\Share + + c:\folder:stream - Name = folder:stream + c:\:stream - Name = :stream + c::stream - Name = c::stream +*/ + +bool CFileInfo::Find(CFSTR path) +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDevicePath(path)) + { + ClearBase(); + Name = path + 4; + IsDevice = true; + + if (NName::IsDrivePath2(path + 4) && path[6] == 0) + { + FChar drive[4] = { path[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize)) + { + Size = totalSize; + return true; + } + } + + NIO::CInFile inFile; + // ::OutputDebugStringW(path); + if (!inFile.Open(path)) + return false; + // ::OutputDebugStringW(L"---"); + if (inFile.SizeDefined) + Size = inFile.Size; + return true; + } + #endif + + #if defined(_WIN32) && !defined(UNDER_CE) + + int colonPos = FindAltStreamColon(path); + if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0) + { + UString streamName = fs2us(path + (unsigned)colonPos); + FString filePath (path); + filePath.DeleteFrom(colonPos); + /* we allow both cases: + name:stream + name:stream:$DATA + */ + const unsigned kPostfixSize = 6; + if (streamName.Len() <= kPostfixSize + || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA")) + streamName += ":$DATA"; + + bool isOk = true; + + if (IsDrivePath2(filePath) && + (colonPos == 2 || colonPos == 3 && filePath[2] == '\\')) + { + // FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT) + ClearBase(); + Name.Empty(); + if (colonPos == 2) + Name = filePath; + } + else + isOk = Find(filePath); + + if (isOk) + { + Attrib &= ~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT); + Size = 0; + CStreamEnumerator enumerator(filePath); + for (;;) + { + CStreamInfo si; + bool found; + if (!enumerator.Next(si, found)) + return false; + if (!found) + { + ::SetLastError(ERROR_FILE_NOT_FOUND); + return false; + } + if (si.Name.IsEqualTo_NoCase(streamName)) + { + // we delete postfix, if alt stream name is not "::$DATA" + if (si.Name.Len() > kPostfixSize + 1) + si.Name.DeleteFrom(si.Name.Len() - kPostfixSize); + Name += us2fs(si.Name); + Size = si.Size; + IsAltStream = true; + return true; + } + } + } + } + + #endif + + CFindFile finder; + + #if defined(_WIN32) && !defined(UNDER_CE) + { + /* + DWORD lastError = GetLastError(); + if (lastError == ERROR_FILE_NOT_FOUND + || lastError == ERROR_BAD_NETPATH // XP64: "\\Server\Share" + || lastError == ERROR_BAD_NET_NAME // Win7: "\\Server\Share" + || lastError == ERROR_INVALID_NAME // XP64: "\\?\UNC\Server\Share" + || lastError == ERROR_BAD_PATHNAME // Win7: "\\?\UNC\Server\Share" + ) + */ + + unsigned rootSize = 0; + if (IsSuperPath(path)) + rootSize = kSuperPathPrefixSize; + + if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0) + { + DWORD attrib = GetFileAttrib(path); + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + ClearBase(); + Attrib = attrib; + Name = path + rootSize; + Name.DeleteFrom(2); // we don't need backslash (C:) + return true; + } + } + else if (IS_PATH_SEPAR(path[0])) + if (path[1] == 0) + { + DWORD attrib = GetFileAttrib(path); + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + ClearBase(); + Name.Empty(); + Attrib = attrib; + return true; + } + } + else + { + const unsigned prefixSize = GetNetworkServerPrefixSize(path); + if (prefixSize > 0 && path[prefixSize] != 0) + { + if (NName::FindSepar(path + prefixSize) < 0) + { + FString s (path); + s.Add_PathSepar(); + s += '*'; // CHAR_ANY_MASK + + bool isOK = false; + if (finder.FindFirst(s, *this)) + { + if (Name == FTEXT(".")) + { + Name = path + prefixSize; + return true; + } + isOK = true; + /* if "\\server\share" maps to root folder "d:\", there is no "." item. + But it's possible that there are another items */ + } + { + DWORD attrib = GetFileAttrib(path); + if (isOK || attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + ClearBase(); + if (attrib != INVALID_FILE_ATTRIBUTES) + Attrib = attrib; + else + SetAsDir(); + Name = path + prefixSize; + return true; + } + } + // ::SetLastError(lastError); + } + } + } + } + #endif + + return finder.FindFirst(path, *this); +} + + +bool DoesFileExist(CFSTR name) +{ + CFileInfo fi; + return fi.Find(name) && !fi.IsDir(); +} + +bool DoesDirExist(CFSTR name) +{ + CFileInfo fi; + return fi.Find(name) && fi.IsDir(); +} + +bool DoesFileOrDirExist(CFSTR name) +{ + CFileInfo fi; + return fi.Find(name); +} + + +void CEnumerator::SetDirPrefix(const FString &dirPrefix) +{ + _wildcard = dirPrefix; + _wildcard += '*'; +} + +bool CEnumerator::NextAny(CFileInfo &fi) +{ + if (_findFile.IsHandleAllocated()) + return _findFile.FindNext(fi); + else + return _findFile.FindFirst(_wildcard, fi); +} + +bool CEnumerator::Next(CFileInfo &fi) +{ + for (;;) + { + if (!NextAny(fi)) + return false; + if (!fi.IsDots()) + return true; + } +} + +bool CEnumerator::Next(CFileInfo &fi, bool &found) +{ + if (Next(fi)) + { + found = true; + return true; + } + found = false; + return (::GetLastError() == ERROR_NO_MORE_FILES); +} + +//////////////////////////////// +// CFindChangeNotification +// FindFirstChangeNotification can return 0. MSDN doesn't tell about it. + +bool CFindChangeNotification::Close() throw() +{ + if (!IsHandleAllocated()) + return true; + if (!::FindCloseChangeNotification(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + +HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter) +{ + #ifndef _UNICODE + if (!g_IsNT) + _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter); + else + #endif + { + IF_USE_MAIN_PATH + _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter); + #ifdef WIN_LONG_PATH + if (!IsHandleAllocated()) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter); + } + #endif + } + return _handle; +} + +#ifndef UNDER_CE + +bool MyGetLogicalDriveStrings(CObjectVector &driveStrings) +{ + driveStrings.Clear(); + #ifndef _UNICODE + if (!g_IsNT) + { + driveStrings.Clear(); + UINT32 size = GetLogicalDriveStrings(0, NULL); + if (size == 0) + return false; + CObjArray buf(size); + UINT32 newSize = GetLogicalDriveStrings(size, buf); + if (newSize == 0 || newSize > size) + return false; + AString s; + UINT32 prev = 0; + for (UINT32 i = 0; i < newSize; i++) + { + if (buf[i] == 0) + { + s = buf + prev; + prev = i + 1; + driveStrings.Add(fas2fs(s)); + } + } + return prev == newSize; + } + else + #endif + { + UINT32 size = GetLogicalDriveStringsW(0, NULL); + if (size == 0) + return false; + CObjArray buf(size); + UINT32 newSize = GetLogicalDriveStringsW(size, buf); + if (newSize == 0 || newSize > size) + return false; + UString s; + UINT32 prev = 0; + for (UINT32 i = 0; i < newSize; i++) + { + if (buf[i] == 0) + { + s = buf + prev; + prev = i + 1; + driveStrings.Add(us2fs(s)); + } + } + return prev == newSize; + } +} + +#endif + +}}} diff --git a/other-licenses/7zstub/src/CPP/Windows/FileFind.h b/other-licenses/7zstub/src/CPP/Windows/FileFind.h new file mode 100644 index 0000000000..77d8dc35c7 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileFind.h @@ -0,0 +1,161 @@ +// Windows/FileFind.h + +#ifndef __WINDOWS_FILE_FIND_H +#define __WINDOWS_FILE_FIND_H + +#include "../Common/MyString.h" +#include "Defs.h" + +namespace NWindows { +namespace NFile { +namespace NFind { + +namespace NAttributes +{ + inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } + inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; } + inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; } + inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } + inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } + inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } + inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } +} + +class CFileInfoBase +{ + bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } +public: + UInt64 Size; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + DWORD Attrib; + bool IsAltStream; + bool IsDevice; + + /* + #ifdef UNDER_CE + DWORD ObjectID; + #else + UINT32 ReparseTag; + #endif + */ + + CFileInfoBase() { ClearBase(); } + void ClearBase() throw(); + + void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } + + bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } + bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } + bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } + bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } + bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } + bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } + bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } + bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } + bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } + bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } + bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } + bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } +}; + +struct CFileInfo: public CFileInfoBase +{ + FString Name; + #if defined(_WIN32) && !defined(UNDER_CE) + // FString ShortName; + #endif + + bool IsDots() const throw(); + bool Find(CFSTR path); +}; + +class CFindFileBase +{ +protected: + HANDLE _handle; +public: + bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } + CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {} + ~CFindFileBase() { Close(); } + bool Close() throw(); +}; + +class CFindFile: public CFindFileBase +{ +public: + bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo); + bool FindNext(CFileInfo &fileInfo); +}; + +#if defined(_WIN32) && !defined(UNDER_CE) + +struct CStreamInfo +{ + UString Name; + UInt64 Size; + + UString GetReducedName() const; // returns ":Name" + // UString GetReducedName2() const; // returns "Name" + bool IsMainStream() const throw(); +}; + +class CFindStream: public CFindFileBase +{ +public: + bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo); + bool FindNext(CStreamInfo &streamInfo); +}; + +class CStreamEnumerator +{ + CFindStream _find; + FString _filePath; + + bool NextAny(CFileInfo &fileInfo); +public: + CStreamEnumerator(const FString &filePath): _filePath(filePath) {} + bool Next(CStreamInfo &streamInfo, bool &found); +}; + +#endif + +bool DoesFileExist(CFSTR name); +bool DoesDirExist(CFSTR name); +bool DoesFileOrDirExist(CFSTR name); + +DWORD GetFileAttrib(CFSTR path); + +class CEnumerator +{ + CFindFile _findFile; + FString _wildcard; + + bool NextAny(CFileInfo &fileInfo); +public: + void SetDirPrefix(const FString &dirPrefix); + bool Next(CFileInfo &fileInfo); + bool Next(CFileInfo &fileInfo, bool &found); +}; + +class CFindChangeNotification +{ + HANDLE _handle; +public: + operator HANDLE () { return _handle; } + bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } + CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} + ~CFindChangeNotification() { Close(); } + bool Close() throw(); + HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter); + bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } +}; + +#ifndef UNDER_CE +bool MyGetLogicalDriveStrings(CObjectVector &driveStrings); +#endif + +}}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/FileIO.cpp b/other-licenses/7zstub/src/CPP/Windows/FileIO.cpp new file mode 100644 index 0000000000..a1d52c0fe0 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileIO.cpp @@ -0,0 +1,432 @@ +// Windows/FileIO.cpp + +#include "StdAfx.h" + +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" +#endif + +#include "FileIO.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +namespace NWindows { +namespace NFile { + +#ifdef SUPPORT_DEVICE_FILE + +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif + +namespace NIO { + +/* +WinXP-64 CreateFile(): + "" - ERROR_PATH_NOT_FOUND + :stream - OK + .:stream - ERROR_PATH_NOT_FOUND + .\:stream - OK + + folder\:stream - ERROR_INVALID_NAME + folder:stream - OK + + c:\:stream - OK + + c::stream - ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 ) + c::stream - OK, if current dir is ROOT ( c:\ ) +*/ + +bool CFileBase::Create(CFSTR path, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +{ + if (!Close()) + return false; + + #ifdef SUPPORT_DEVICE_FILE + IsDeviceFile = false; + #endif + + #ifndef _UNICODE + if (!g_IsNT) + { + _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + } + else + #endif + { + IF_USE_MAIN_PATH + _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = ::CreateFileW(superPath, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + } + #endif + } + return (_handle != INVALID_HANDLE_VALUE); +} + +bool CFileBase::Close() throw() +{ + if (_handle == INVALID_HANDLE_VALUE) + return true; + if (!::CloseHandle(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + +bool CFileBase::GetPosition(UInt64 &position) const throw() +{ + return Seek(0, FILE_CURRENT, position); +} + +bool CFileBase::GetLength(UInt64 &length) const throw() +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceFile && SizeDefined) + { + length = Size; + return true; + } + #endif + + DWORD sizeHigh; + DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + if (::GetLastError() != NO_ERROR) + return false; + length = (((UInt64)sizeHigh) << 32) + sizeLow; + return true; +} + +bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw() +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceFile && SizeDefined && moveMethod == FILE_END) + { + distanceToMove += Size; + moveMethod = FILE_BEGIN; + } + #endif + + LONG high = (LONG)(distanceToMove >> 32); + DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod); + if (low == 0xFFFFFFFF) + if (::GetLastError() != NO_ERROR) + return false; + newPosition = (((UInt64)(UInt32)high) << 32) + low; + return true; +} + +bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw() +{ + return Seek(position, FILE_BEGIN, newPosition); +} + +bool CFileBase::SeekToBegin() const throw() +{ + UInt64 newPosition; + return Seek(0, newPosition); +} + +bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw() +{ + return Seek(0, FILE_END, newPosition); +} + +// ---------- CInFile --------- + +#ifdef SUPPORT_DEVICE_FILE + +void CInFile::CorrectDeviceSize() +{ + // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail + static const UInt32 kClusterSize = 1 << 14; + UInt64 pos = Size & ~(UInt64)(kClusterSize - 1); + UInt64 realNewPosition; + if (!Seek(pos, realNewPosition)) + return; + Byte *buf = (Byte *)MidAlloc(kClusterSize); + + bool needbackward = true; + + for (;;) + { + UInt32 processed = 0; + // up test is slow for "PhysicalDrive". + // processed size for latest block for "PhysicalDrive0" is 0. + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed == 0) + break; + needbackward = false; + Size = pos + processed; + if (processed != kClusterSize) + break; + pos += kClusterSize; + } + + if (needbackward && pos != 0) + { + pos -= kClusterSize; + for (;;) + { + // break; + if (!Seek(pos, realNewPosition)) + break; + if (!buf) + { + buf = (Byte *)MidAlloc(kClusterSize); + if (!buf) + break; + } + UInt32 processed = 0; + // that code doesn't work for "PhysicalDrive0" + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed != 0) + { + Size = pos + processed; + break; + } + if (pos == 0) + break; + pos -= kClusterSize; + } + } + MidFree(buf); +} + + +void CInFile::CalcDeviceSize(CFSTR s) +{ + SizeDefined = false; + Size = 0; + if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile) + return; + #ifdef UNDER_CE + + SizeDefined = true; + Size = 128 << 20; + + #else + + PARTITION_INFORMATION partInfo; + bool needCorrectSize = true; + + /* + WinXP 64-bit: + + HDD \\.\PhysicalDrive0 (MBR): + GetPartitionInfo == GeometryEx : corrrect size? (includes tail) + Geometry : smaller than GeometryEx (no tail, maybe correct too?) + MyGetDiskFreeSpace : FAIL + Size correction is slow and block size (kClusterSize) must be small? + + HDD partition \\.\N: (NTFS): + MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction + GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS + Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition) + + CD-ROM drive (ISO): + MyGetDiskFreeSpace : correct size. Same size can be calculated after correction + Geometry == CdRomGeometry : smaller than corrrect size + GetPartitionInfo == GeometryEx : larger than corrrect size + + Floppy \\.\a: (FAT): + Geometry : correct size. + CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL + correction works OK for FAT. + correction works OK for non-FAT, if kClusterSize = 512. + */ + + if (GetPartitionInfo(&partInfo)) + { + Size = partInfo.PartitionLength.QuadPart; + SizeDefined = true; + needCorrectSize = false; + if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0) + { + FChar path[4] = { s[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize)) + Size = totalSize; + else + needCorrectSize = true; + } + } + + if (!SizeDefined) + { + my_DISK_GEOMETRY_EX geomEx; + SizeDefined = GetGeometryEx(&geomEx); + if (SizeDefined) + Size = geomEx.DiskSize.QuadPart; + else + { + DISK_GEOMETRY geom; + SizeDefined = GetGeometry(&geom); + if (!SizeDefined) + SizeDefined = GetCdRomGeometry(&geom); + if (SizeDefined) + Size = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; + } + } + + if (needCorrectSize && SizeDefined && Size != 0) + { + CorrectDeviceSize(); + SeekToBegin(); + } + + // SeekToBegin(); + #endif +} + +// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && + +#define MY_DEVICE_EXTRA_CODE \ + IsDeviceFile = IsDevicePath(fileName); \ + CalcDeviceSize(fileName); +#else +#define MY_DEVICE_EXTRA_CODE +#endif + +bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +{ + bool res = Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); + MY_DEVICE_EXTRA_CODE + return res; +} + +bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite) +{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } + +bool CInFile::Open(CFSTR fileName) + { return OpenShared(fileName, false); } + +// ReadFile and WriteFile functions in Windows have BUG: +// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) +// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES +// (Insufficient system resources exist to complete the requested service). + +// Probably in some version of Windows there are problems with other sizes: +// for 32 MB (maybe also for 16 MB). +// And message can be "Network connection was lost" + +static UInt32 kChunkSizeMax = (1 << 22); + +bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw() +{ + DWORD processedLoc = 0; + bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); + processedSize = (UInt32)processedLoc; + return res; +} + +bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw() +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + return Read1(data, size, processedSize); +} + +bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw() +{ + processedSize = 0; + do + { + UInt32 processedLoc = 0; + bool res = ReadPart(data, size, processedLoc); + processedSize += processedLoc; + if (!res) + return false; + if (processedLoc == 0) + return true; + data = (void *)((unsigned char *)data + processedLoc); + size -= processedLoc; + } + while (size > 0); + return true; +} + +// ---------- COutFile --------- + +static inline DWORD GetCreationDisposition(bool createAlways) + { return createAlways? CREATE_ALWAYS: CREATE_NEW; } + +bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) + { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } + +bool COutFile::Open(CFSTR fileName, DWORD creationDisposition) + { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } + +bool COutFile::Create(CFSTR fileName, bool createAlways) + { return Open(fileName, GetCreationDisposition(createAlways)); } + +bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes) + { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); } + +bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() + { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } + +bool COutFile::SetMTime(const FILETIME *mTime) throw() { return SetTime(NULL, NULL, mTime); } + +bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw() +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + DWORD processedLoc = 0; + bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); + processedSize = (UInt32)processedLoc; + return res; +} + +bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw() +{ + processedSize = 0; + do + { + UInt32 processedLoc = 0; + bool res = WritePart(data, size, processedLoc); + processedSize += processedLoc; + if (!res) + return false; + if (processedLoc == 0) + return true; + data = (const void *)((const unsigned char *)data + processedLoc); + size -= processedLoc; + } + while (size > 0); + return true; +} + +bool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); } + +bool COutFile::SetLength(UInt64 length) throw() +{ + UInt64 newPosition; + if (!Seek(length, newPosition)) + return false; + if (newPosition != length) + return false; + return SetEndOfFile(); +} + +}}} diff --git a/other-licenses/7zstub/src/CPP/Windows/FileIO.h b/other-licenses/7zstub/src/CPP/Windows/FileIO.h new file mode 100644 index 0000000000..e31bc20cc3 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileIO.h @@ -0,0 +1,212 @@ +// Windows/FileIO.h + +#ifndef __WINDOWS_FILE_IO_H +#define __WINDOWS_FILE_IO_H + +#include "../Common/MyWindows.h" + +#if defined(_WIN32) && !defined(UNDER_CE) +#include +#endif + +#include "../Common/MyString.h" +#include "../Common/MyBuffer.h" + +#include "Defs.h" + +#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL) + +#define _my_SYMLINK_FLAG_RELATIVE 1 + +#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER + +namespace NWindows { +namespace NFile { + +#if defined(_WIN32) && !defined(UNDER_CE) +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink); +#endif + +struct CReparseShortInfo +{ + unsigned Offset; + unsigned Size; + + bool Parse(const Byte *p, size_t size); +}; + +struct CReparseAttr +{ + UInt32 Tag; + UInt32 Flags; + UString SubsName; + UString PrintName; + + CReparseAttr(): Tag(0), Flags(0) {} + + // Parse() + // returns true and (errorCode = 0), if (correct MOUNT_POINT or SYMLINK) + // returns false and (errorCode = ERROR_REPARSE_TAG_MISMATCH), if not (MOUNT_POINT or SYMLINK) + bool Parse(const Byte *p, size_t size, DWORD &errorCode); + + bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction + bool IsSymLink() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } + bool IsRelative() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } + // bool IsVolume() const; + + bool IsOkNamePair() const; + UString GetPath() const; +}; + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); + +class CFileBase +{ +protected: + HANDLE _handle; + + bool Create(CFSTR path, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + +public: + + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, + LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const + { + return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, + outBuffer, outSize, bytesReturned, overlapped)); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const + { + return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const + { + DWORD bytesReturned; + return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned); + } + +public: + #ifdef SUPPORT_DEVICE_FILE + bool IsDeviceFile; + bool SizeDefined; + UInt64 Size; // it can be larger than real available size + #endif + + CFileBase(): _handle(INVALID_HANDLE_VALUE) {}; + ~CFileBase() { Close(); } + + bool Close() throw(); + + bool GetPosition(UInt64 &position) const throw(); + bool GetLength(UInt64 &length) const throw(); + + bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw(); + bool Seek(UInt64 position, UInt64 &newPosition) const throw(); + bool SeekToBegin() const throw(); + bool SeekToEnd(UInt64 &newPosition) const throw(); + + bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const + { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } + + static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) + { + NIO::CFileBase file; + if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) + return false; + return file.GetFileInformation(info); + } +}; + +#ifndef UNDER_CE +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) +// #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) + +// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP +#define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) + +struct my_DISK_GEOMETRY_EX +{ + DISK_GEOMETRY Geometry; + LARGE_INTEGER DiskSize; + BYTE Data[1]; +}; +#endif + +class CInFile: public CFileBase +{ + #ifdef SUPPORT_DEVICE_FILE + + #ifndef UNDER_CE + + bool GetGeometry(DISK_GEOMETRY *res) const + { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } + + bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const + { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } + + bool GetCdRomGeometry(DISK_GEOMETRY *res) const + { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } + + bool GetPartitionInfo(PARTITION_INFORMATION *res) + { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } + + #endif + + void CorrectDeviceSize(); + void CalcDeviceSize(CFSTR name); + + #endif + +public: + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool OpenShared(CFSTR fileName, bool shareForWrite); + bool Open(CFSTR fileName); + + #ifndef UNDER_CE + + bool OpenReparse(CFSTR fileName) + { + // 17.02 fix: to support Windows XP compatibility junctions: + // we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ + return + Create(fileName, 0, + // Open(fileName, + FILE_SHARE_READ, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); + } + + #endif + + bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); +}; + +class COutFile: public CFileBase +{ +public: + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(CFSTR fileName, DWORD creationDisposition); + bool Create(CFSTR fileName, bool createAlways); + bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); + + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); + bool SetMTime(const FILETIME *mTime) throw(); + bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool SetEndOfFile() throw(); + bool SetLength(UInt64 length) throw(); +}; + +}}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/FileLink.cpp b/other-licenses/7zstub/src/CPP/Windows/FileLink.cpp new file mode 100644 index 0000000000..b5e47e73c5 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileLink.cpp @@ -0,0 +1,440 @@ +// Windows/FileLink.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" +#endif + +#include "FileDir.h" +#include "FileFind.h" +#include "FileIO.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { + +using namespace NName; + +/* + Reparse Points (Junctions and Symbolic Links): + struct + { + UInt32 Tag; + UInt16 Size; // not including starting 8 bytes + UInt16 Reserved; // = 0 + + UInt16 SubstituteOffset; // offset in bytes from start of namesChars + UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL + UInt16 PrintOffset; // offset in bytes from start of namesChars + UInt16 PrintLen; // size in bytes, it doesn't include tailed NUL + + [UInt32] Flags; // for Symbolic Links only. + + UInt16 namesChars[] + } + + MOUNT_POINT (Junction point): + 1) there is NUL wchar after path + 2) Default Order in table: + Substitute Path + Print Path + 3) pathnames can not contain dot directory names + + SYMLINK: + 1) there is no NUL wchar after path + 2) Default Order in table: + Print Path + Substitute Path +*/ + +/* +static const UInt32 kReparseFlags_Alias = (1 << 29); +static const UInt32 kReparseFlags_HighLatency = (1 << 30); +static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); + +#define _my_IO_REPARSE_TAG_HSM (0xC0000004L) +#define _my_IO_REPARSE_TAG_HSM2 (0x80000006L) +#define _my_IO_REPARSE_TAG_SIS (0x80000007L) +#define _my_IO_REPARSE_TAG_WIM (0x80000008L) +#define _my_IO_REPARSE_TAG_CSV (0x80000009L) +#define _my_IO_REPARSE_TAG_DFS (0x8000000AL) +#define _my_IO_REPARSE_TAG_DFSR (0x80000012L) +*/ + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +#define Set16(p, v) SetUi16(p, v) +#define Set32(p, v) SetUi32(p, v) + +static const wchar_t * const k_LinkPrefix = L"\\??\\"; +static const unsigned k_LinkPrefix_Size = 4; + +static const bool IsLinkPrefix(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_LinkPrefix); +} + +/* +static const wchar_t * const k_VolumePrefix = L"Volume{"; +static const bool IsVolumeName(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_VolumePrefix); +} +*/ + +void WriteString(Byte *dest, const wchar_t *path) +{ + for (;;) + { + wchar_t c = *path++; + if (c == 0) + return; + Set16(dest, (UInt16)c); + dest += 2; + } +} + +#if defined(_WIN32) && !defined(UNDER_CE) + +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink) +{ + bool isAbs = IsAbsolutePath(path); + if (!isAbs && !isSymLink) + return false; + + bool needPrintName = true; + + if (IsSuperPath(path)) + { + path += kSuperPathPrefixSize; + if (!IsDrivePath(path)) + needPrintName = false; + } + + const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; + + unsigned len2 = MyStringLen(path) * 2; + const unsigned len1 = len2 + add_Prefix_Len * 2; + if (!needPrintName) + len2 = 0; + + unsigned totalNamesSize = (len1 + len2); + + /* some WIM imagex software uses old scheme for symbolic links. + so we can old scheme for byte to byte compatibility */ + + bool newOrderScheme = isSymLink; + // newOrderScheme = false; + + if (!newOrderScheme) + totalNamesSize += 2 * 2; + + const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; + dest.Alloc(size); + memset(dest, 0, size); + const UInt32 tag = isSymLink ? + _my_IO_REPARSE_TAG_SYMLINK : + _my_IO_REPARSE_TAG_MOUNT_POINT; + Byte *p = dest; + Set32(p, tag); + Set16(p + 4, (UInt16)(size - 8)); + Set16(p + 6, 0); + p += 8; + + unsigned subOffs = 0; + unsigned printOffs = 0; + if (newOrderScheme) + subOffs = len2; + else + printOffs = len1 + 2; + + Set16(p + 0, (UInt16)subOffs); + Set16(p + 2, (UInt16)len1); + Set16(p + 4, (UInt16)printOffs); + Set16(p + 6, (UInt16)len2); + + p += 8; + if (isSymLink) + { + UInt32 flags = isAbs ? 0 : _my_SYMLINK_FLAG_RELATIVE; + Set32(p, flags); + p += 4; + } + + if (add_Prefix_Len != 0) + WriteString(p + subOffs, k_LinkPrefix); + WriteString(p + subOffs + add_Prefix_Len * 2, path); + if (needPrintName) + WriteString(p + printOffs, path); + return true; +} + +#endif + +static void GetString(const Byte *p, unsigned len, UString &res) +{ + wchar_t *s = res.GetBuf(len); + unsigned i; + for (i = 0; i < len; i++) + { + wchar_t c = Get16(p + i * 2); + if (c == 0) + break; + s[i] = c; + } + s[i] = 0; + res.ReleaseBuf_SetLen(i); +} + +bool CReparseAttr::Parse(const Byte *p, size_t size, DWORD &errorCode) +{ + errorCode = ERROR_INVALID_REPARSE_DATA; + if (size < 8) + return false; + Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + { + errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID + return false; + } + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + GetString(p + subOffs, subLen >> 1, SubsName); + GetString(p + printOffs, printLen >> 1, PrintName); + + errorCode = 0; + return true; +} + +bool CReparseShortInfo::Parse(const Byte *p, size_t size) +{ + const Byte *start = p; + Offset= 0; + Size = 0; + if (size < 8) + return false; + UInt32 Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + // return true; + return false; + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + // UInt32 Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + // Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + + Offset = (unsigned)(p - start) + subOffs; + Size = subLen; + return true; +} + +bool CReparseAttr::IsOkNamePair() const +{ + if (IsLinkPrefix(SubsName)) + { + if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) + return PrintName.IsEmpty(); + if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) + return true; + } + return wcscmp(SubsName, PrintName) == 0; +} + +/* +bool CReparseAttr::IsVolume() const +{ + if (!IsLinkPrefix(SubsName)) + return false; + return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size)); +} +*/ + +UString CReparseAttr::GetPath() const +{ + UString s (SubsName); + if (IsLinkPrefix(s)) + { + s.ReplaceOneCharAtPos(1, '\\'); + if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) + s.DeleteFrontal(k_LinkPrefix_Size); + } + return s; +} + + +#ifdef SUPPORT_DEVICE_FILE + +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif + +#ifndef UNDER_CE + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo) +{ + reparseData.Free(); + CInFile file; + if (!file.OpenReparse(path)) + return false; + + if (fileInfo) + file.GetFileInformation(fileInfo); + + const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + CByteArr buf(kBufSize); + DWORD returnedSize; + if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) + return false; + reparseData.CopyFrom(buf, returnedSize); + return true; +} + +static bool CreatePrefixDirOfFile(CFSTR path) +{ + FString path2 (path); + int pos = path2.ReverseFind_PathSepar(); + if (pos < 0) + return true; + #ifdef _WIN32 + if (pos == 2 && path2[1] == L':') + return true; // we don't create Disk folder; + #endif + path2.DeleteFrom(pos); + return NDir::CreateComplexDir(path2); +} + +// If there is Reprase data already, it still writes new Reparse data +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) +{ + NFile::NFind::CFileInfo fi; + if (fi.Find(path)) + { + if (fi.IsDir() != isDir) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + } + else + { + if (isDir) + { + if (!NDir::CreateComplexDir(path)) + return false; + } + else + { + CreatePrefixDirOfFile(path); + COutFile file; + if (!file.Create(path, CREATE_NEW)) + return false; + } + } + + COutFile file; + if (!file.Open(path, + FILE_SHARE_WRITE, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) + return false; + + DWORD returnedSize; + if (!file.DeviceIoControl(my_FSCTL_SET_REPARSE_POINT, (void *)data, size, NULL, 0, &returnedSize)) + return false; + return true; +} + +} + +#endif + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/FileMapping.cpp b/other-licenses/7zstub/src/CPP/Windows/FileMapping.cpp new file mode 100644 index 0000000000..01c4a943d4 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileMapping.cpp @@ -0,0 +1,12 @@ +// Windows/FileMapping.cpp + +#include "StdAfx.h" + +#include "FileMapping.h" + +namespace NWindows { +namespace NFile { +namespace NMapping { + + +}}} diff --git a/other-licenses/7zstub/src/CPP/Windows/FileMapping.h b/other-licenses/7zstub/src/CPP/Windows/FileMapping.h new file mode 100644 index 0000000000..27d076b83b --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileMapping.h @@ -0,0 +1,66 @@ +// Windows/FileMapping.h + +#ifndef __WINDOWS_FILEMAPPING_H +#define __WINDOWS_FILEMAPPING_H + +#include "../Common/MyTypes.h" + +#include "Handle.h" + +namespace NWindows { + +class CFileMapping: public CHandle +{ +public: + WRes Create(DWORD protect, UInt64 maxSize, LPCTSTR name) + { + _handle = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, protect, (DWORD)(maxSize >> 32), (DWORD)maxSize, name); + return ::GetLastError(); + } + + WRes Open(DWORD + #ifndef UNDER_CE + desiredAccess + #endif + , LPCTSTR name) + { + #ifdef UNDER_CE + WRes res = Create(PAGE_READONLY, 0, name); + if (res == ERROR_ALREADY_EXISTS) + return 0; + Close(); + if (res == 0) + res = ERROR_FILE_NOT_FOUND; + return res; + #else + _handle = ::OpenFileMapping(desiredAccess, FALSE, name); + if (_handle != 0) + return 0; + return ::GetLastError(); + #endif + } + + LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap) + { + return ::MapViewOfFile(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap); + } + + #ifndef UNDER_CE + LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) + { + return ::MapViewOfFileEx(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap, baseAddress); + } + #endif +}; + +class CFileUnmapper +{ + const void *_data; +public: + CFileUnmapper(const void *data) : _data(data) {} + ~CFileUnmapper() { ::UnmapViewOfFile(_data); } +}; + +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/FileName.cpp b/other-licenses/7zstub/src/CPP/Windows/FileName.cpp new file mode 100644 index 0000000000..2a227dc600 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileName.cpp @@ -0,0 +1,839 @@ +// Windows/FileName.cpp + +#include "StdAfx.h" + +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { +namespace NName { + +#define IS_SEPAR(c) IS_PATH_SEPAR(c) + +int FindSepar(const wchar_t *s) throw() +{ + for (const wchar_t *p = s;; p++) + { + const wchar_t c = *p; + if (c == 0) + return -1; + if (IS_SEPAR(c)) + return (int)(p - s); + } +} + +#ifndef USE_UNICODE_FSTRING +int FindSepar(const FChar *s) throw() +{ + for (const FChar *p = s;; p++) + { + const FChar c = *p; + if (c == 0) + return -1; + if (IS_SEPAR(c)) + return (int)(p - s); + } +} +#endif + +#ifndef USE_UNICODE_FSTRING +void NormalizeDirPathPrefix(FString &dirPath) +{ + if (dirPath.IsEmpty()) + return; + if (!IsPathSepar(dirPath.Back())) + dirPath.Add_PathSepar(); +} +#endif + +void NormalizeDirPathPrefix(UString &dirPath) +{ + if (dirPath.IsEmpty()) + return; + if (!IsPathSepar(dirPath.Back())) + dirPath.Add_PathSepar(); +} + +#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') + +bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } + +bool IsAltPathPrefix(CFSTR s) throw() +{ + unsigned len = MyStringLen(s); + if (len == 0) + return false; + if (s[len - 1] != ':') + return false; + + #if defined(_WIN32) && !defined(UNDER_CE) + if (IsDevicePath(s)) + return false; + if (IsSuperPath(s)) + { + s += kSuperPathPrefixSize; + len -= kSuperPathPrefixSize; + } + if (len == 2 && IsDrivePath2(s)) + return false; + #endif + + return true; +} + +#if defined(_WIN32) && !defined(UNDER_CE) + +const char * const kSuperPathPrefix = "\\\\?\\"; +static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; + +#define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3])) +#define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3])) +#define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3])) + +#define IS_UNC_WITH_SLASH(s) ( \ + ((s)[0] == 'U' || (s)[0] == 'u') \ + && ((s)[1] == 'N' || (s)[1] == 'n') \ + && ((s)[2] == 'C' || (s)[2] == 'c') \ + && IS_SEPAR((s)[3])) + +bool IsDevicePath(CFSTR s) throw() +{ + #ifdef UNDER_CE + + s = s; + return false; + /* + // actually we don't know the way to open device file in WinCE. + unsigned len = MyStringLen(s); + if (len < 5 || len > 5 || !IsString1PrefixedByString2(s, "DSK")) + return false; + if (s[4] != ':') + return false; + // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); + */ + + #else + + if (!IS_DEVICE_PATH(s)) + return false; + unsigned len = MyStringLen(s); + if (len == 6 && s[5] == ':') + return true; + if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive")) + return false; + for (unsigned i = 17; i < len; i++) + if (s[i] < '0' || s[i] > '9') + return false; + return true; + + #endif +} + +bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } +bool IsNetworkPath(CFSTR s) throw() +{ + if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1])) + return false; + if (IsSuperUncPath(s)) + return true; + FChar c = s[2]; + return (c != '.' && c != '?'); +} + +unsigned GetNetworkServerPrefixSize(CFSTR s) throw() +{ + if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1])) + return 0; + unsigned prefixSize = 2; + if (IsSuperUncPath(s)) + prefixSize = kSuperUncPathPrefixSize; + else + { + FChar c = s[2]; + if (c == '.' || c == '?') + return 0; + } + int pos = FindSepar(s + prefixSize); + if (pos < 0) + return 0; + return prefixSize + pos + 1; +} + +bool IsNetworkShareRootPath(CFSTR s) throw() +{ + unsigned prefixSize = GetNetworkServerPrefixSize(s); + if (prefixSize == 0) + return false; + s += prefixSize; + int pos = FindSepar(s); + if (pos < 0) + return true; + return s[(unsigned)pos + 1] == 0; +} + +static const unsigned kDrivePrefixSize = 3; /* c:\ */ + +bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } +// bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } +bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } +// bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } +// bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } +bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } +bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } +#endif // USE_UNICODE_FSTRING + +bool IsDrivePath_SuperAllowed(CFSTR s) throw() +{ + if (IsSuperPath(s)) + s += kSuperPathPrefixSize; + return IsDrivePath(s); +} + +bool IsDriveRootPath_SuperAllowed(CFSTR s) throw() +{ + if (IsSuperPath(s)) + s += kSuperPathPrefixSize; + return IsDrivePath(s) && s[kDrivePrefixSize] == 0; +} + +bool IsAbsolutePath(const wchar_t *s) throw() +{ + return IS_SEPAR(s[0]) || IsDrivePath2(s); +} + +int FindAltStreamColon(CFSTR path) throw() +{ + unsigned i = 0; + if (IsDrivePath2(path)) + i = 2; + int colonPos = -1; + for (;; i++) + { + FChar c = path[i]; + if (c == 0) + return colonPos; + if (c == ':') + { + if (colonPos < 0) + colonPos = i; + continue; + } + if (IS_SEPAR(c)) + colonPos = -1; + } +} + +#ifndef USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) +{ + // Network path: we look "server\path\" as root prefix + int pos = FindSepar(s); + if (pos < 0) + return 0; + int pos2 = FindSepar(s + (unsigned)pos + 1); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (!IS_SEPAR(s[0])) + return 0; + if (s[1] == 0 || !IS_SEPAR(s[1])) + return 1; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindSepar(s + kSuperPathPrefixSize); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(CFSTR s) throw() +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#endif // USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() +{ + // Network path: we look "server\path\" as root prefix + int pos = FindSepar(s); + if (pos < 0) + return 0; + int pos2 = FindSepar(s + (unsigned)pos + 1); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (!IS_SEPAR(s[0])) + return 0; + if (s[1] == 0 || !IS_SEPAR(s[1])) + return 1; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindSepar(s + kSuperPathPrefixSize); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(const wchar_t *s) throw() +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#else // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); } + +#ifndef USE_UNICODE_FSTRING +unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; } +#endif +unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; } + +#endif // _WIN32 + + +#ifndef UNDER_CE + +static bool GetCurDir(UString &path) +{ + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fs2us(fas2fs(s)); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = s; + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +static bool ResolveDotsFolders(UString &s) +{ + #ifdef _WIN32 + // s.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + + for (unsigned i = 0;;) + { + const wchar_t c = s[i]; + if (c == 0) + return true; + if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1]))) + { + const wchar_t c1 = s[i + 1]; + if (c1 == '.') + { + const wchar_t c2 = s[i + 2]; + if (IS_SEPAR(c2) || c2 == 0) + { + if (i == 0) + return false; + int k = i - 2; + i += 2; + + for (;; k--) + { + if (k < 0) + return false; + if (!IS_SEPAR(s[(unsigned)k])) + break; + } + + do + k--; + while (k >= 0 && !IS_SEPAR(s[(unsigned)k])); + + unsigned num; + + if (k >= 0) + { + num = i - k; + i = k; + } + else + { + num = (c2 == 0 ? i : (i + 1)); + i = 0; + } + + s.Delete(i, num); + continue; + } + } + else if (IS_SEPAR(c1) || c1 == 0) + { + unsigned num = 2; + if (i != 0) + i--; + else if (c1 == 0) + num = 1; + s.Delete(i, num); + continue; + } + } + + i++; + } +} + +#endif // UNDER_CE + +#define LONG_PATH_DOTS_FOLDERS_PARSING + + +/* +Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\ +To solve that problem we check such path: + - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper + - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain +*/ +#ifdef LONG_PATH_DOTS_FOLDERS_PARSING +#ifndef UNDER_CE +static bool AreThereDotsFolders(CFSTR s) +{ + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return false; + if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1]))) + { + FChar c1 = s[i + 1]; + if (c1 == 0 || IS_SEPAR(c1) || + (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2])))) + return true; + } + } +} +#endif +#endif // LONG_PATH_DOTS_FOLDERS_PARSING + +#ifdef WIN_LONG_PATH + +/* +Most of Windows versions have problems, if some file or dir name +contains '.' or ' ' at the end of name (Bad Path). +To solve that problem, we always use Super Path ("\\?\" prefix and full path) +in such cases. Note that "." and ".." are not bad names. + +There are 3 cases: + 1) If the path is already Super Path, we use that path + 2) If the path is not Super Path : + 2.1) Bad Path; we use only Super Path. + 2.2) Good Path; we use Main Path. If it fails, we use Super Path. + + NeedToUseOriginalPath returns: + kSuperPathType_UseOnlyMain : Super already + kSuperPathType_UseOnlySuper : not Super, Bad Path + kSuperPathType_UseMainAndSuper : not Super, Good Path +*/ + +int GetUseSuperPathType(CFSTR s) throw() +{ + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + if ((s)[2] != '.') + if (AreThereDotsFolders(s + kSuperPathPrefixSize)) + return kSuperPathType_UseOnlySuper; + #endif + return kSuperPathType_UseOnlyMain; + } + + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return kSuperPathType_UseMainAndSuper; + if (c == '.' || c == ' ') + { + FChar c2 = s[i + 1]; + if (c2 == 0 || IS_SEPAR(c2)) + { + // if it's "." or "..", it's not bad name. + if (c == '.') + { + if (i == 0 || IS_SEPAR(s[i - 1])) + continue; + if (s[i - 1] == '.') + { + if (i - 1 == 0 || IS_SEPAR(s[i - 2])) + continue; + } + } + return kSuperPathType_UseOnlySuper; + } + } + } +} + + +/* + returns false in two cases: + - if GetCurDir was used, and GetCurDir returned error. + - if we can't resolve ".." name. + if path is ".", "..", res is empty. + if it's Super Path already, res is empty. + for \**** , and if GetCurDir is not drive (c:\), res is empty + for absolute paths, returns true, res is Super path. +*/ + + +static bool GetSuperPathBase(CFSTR s, UString &res) +{ + res.Empty(); + + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + + if ((s)[2] == '.') + return true; + + // we will return true here, so we will try to use these problem paths. + + if (!AreThereDotsFolders(s + kSuperPathPrefixSize)) + return true; + + UString temp = fs2us(s); + unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); + if (fixedSize == 0) + return true; + + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return true; + + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + + #endif + + return true; + } + + if (IS_SEPAR(c)) + { + if (IS_SEPAR(s[1])) + { + UString temp = fs2us(s + 2); + unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); + // we ignore that error to allow short network paths server\share? + /* + if (fixedSize == 0) + return false; + */ + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return false; + res += kSuperUncPrefix; + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + return true; + } + } + else + { + if (IsDrivePath2(s)) + { + UString temp = fs2us(s); + unsigned prefixSize = 2; + if (IsDrivePath(s)) + prefixSize = kDrivePrefixSize; + UString rem = temp.Ptr(prefixSize); + if (!ResolveDotsFolders(rem)) + return true; + res += kSuperPathPrefix; + temp.DeleteFrom(prefixSize); + res += temp; + res += rem; + return true; + } + } + + UString curDir; + if (!GetCurDir(curDir)) + return false; + NormalizeDirPathPrefix(curDir); + + unsigned fixedSizeStart = 0; + unsigned fixedSize = 0; + const char *superMarker = NULL; + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + { + superMarker = kSuperPathPrefix; + fixedSize = kDrivePrefixSize; + } + else + { + if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1])) + return false; + fixedSizeStart = 2; + fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2)); + if (fixedSize == 0) + return false; + superMarker = kSuperUncPrefix; + } + } + + UString temp; + if (IS_SEPAR(c)) + { + temp = fs2us(s + 1); + } + else + { + temp += &curDir[fixedSizeStart + fixedSize]; + temp += fs2us(s); + } + if (!ResolveDotsFolders(temp)) + return false; + if (superMarker) + res += superMarker; + res += curDir.Mid(fixedSizeStart, fixedSize); + res += temp; + return true; +} + + +/* + In that case if GetSuperPathBase doesn't return new path, we don't need + to use same path that was used as main path + + GetSuperPathBase superPath.IsEmpty() onlyIfNew + false * * GetCurDir Error + true false * use Super path + true true true don't use any path, we already used mainPath + true true false use main path as Super Path, we don't try mainMath + That case is possible now if GetCurDir returns unknow + type of path (not drive and not network) + + We can change that code if we want to try mainPath, if GetSuperPathBase returns error, + and we didn't try mainPath still. + If we want to work that way, we don't need to use GetSuperPathBase return code. +*/ + +bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew) +{ + if (GetSuperPathBase(path, superPath)) + { + if (superPath.IsEmpty()) + { + // actually the only possible when onlyIfNew == true and superPath is empty + // is case when + + if (onlyIfNew) + return false; + superPath = fs2us(path); + } + return true; + } + return false; +} + +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew) +{ + if (!GetSuperPathBase(s1, d1) || + !GetSuperPathBase(s2, d2)) + return false; + if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew) + return false; + if (d1.IsEmpty()) d1 = fs2us(s1); + if (d2.IsEmpty()) d2 = fs2us(s2); + return true; +} + + +/* +// returns true, if we need additional use with New Super path. +bool GetSuperPath(CFSTR path, UString &superPath) +{ + if (GetSuperPathBase(path, superPath)) + return !superPath.IsEmpty(); + return false; +} +*/ +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) +{ + res = s; + + #ifdef UNDER_CE + + if (!IS_SEPAR(s[0])) + { + if (!dirPrefix) + return false; + res = dirPrefix; + res += s; + } + + #else + + unsigned prefixSize = GetRootPrefixSize(s); + if (prefixSize != 0) + { + if (!AreThereDotsFolders(s + prefixSize)) + return true; + + UString rem = fs2us(s + prefixSize); + if (!ResolveDotsFolders(rem)) + return true; // maybe false; + res.DeleteFrom(prefixSize); + res += us2fs(rem); + return true; + } + + /* + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + if (IS_SEPAR(c) && IS_SEPAR(s[1])) + return true; + if (IsDrivePath(s)) + return true; + */ + + UString curDir; + if (dirPrefix) + curDir = fs2us(dirPrefix); + else + { + if (!GetCurDir(curDir)) + return false; + } + NormalizeDirPathPrefix(curDir); + + unsigned fixedSize = 0; + + #ifdef _WIN32 + + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + fixedSize = kDrivePrefixSize; + else + { + if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1])) + return false; + fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2)); + if (fixedSize == 0) + return false; + fixedSize += 2; + } + } + + #endif // _WIN32 + + UString temp; + if (IS_SEPAR(s[0])) + { + temp = fs2us(s + 1); + } + else + { + temp += curDir.Ptr(fixedSize); + temp += fs2us(s); + } + if (!ResolveDotsFolders(temp)) + return false; + curDir.DeleteFrom(fixedSize); + res = us2fs(curDir); + res += us2fs(temp); + + #endif // UNDER_CE + + return true; +} + +bool GetFullPath(CFSTR path, FString &fullPath) +{ + return GetFullPath(NULL, path, fullPath); +} + +}}} diff --git a/other-licenses/7zstub/src/CPP/Windows/FileName.h b/other-licenses/7zstub/src/CPP/Windows/FileName.h new file mode 100644 index 0000000000..1e47098632 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileName.h @@ -0,0 +1,115 @@ +// Windows/FileName.h + +#ifndef __WINDOWS_FILE_NAME_H +#define __WINDOWS_FILE_NAME_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NFile { +namespace NName { + +int FindSepar(const wchar_t *s) throw(); +#ifndef USE_UNICODE_FSTRING +int FindSepar(const FChar *s) throw(); +#endif + +void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty +void NormalizeDirPathPrefix(UString &dirPath); + +bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars like "a:\\" + +bool IsAltPathPrefix(CFSTR s) throw(); /* name: */ + +#if defined(_WIN32) && !defined(UNDER_CE) + +extern const char * const kSuperPathPrefix; /* \\?\ */ +const unsigned kDevicePathPrefixSize = 4; +const unsigned kSuperPathPrefixSize = 4; +const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; + +bool IsDevicePath(CFSTR s) throw(); /* \\.\ */ +bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */ +bool IsNetworkPath(CFSTR s) throw(); /* \\?\UNC\ or \\SERVER */ + +/* GetNetworkServerPrefixSize() returns size of server prefix: + \\?\UNC\SERVER\ + \\SERVER\ + in another cases it returns 0 +*/ + +unsigned GetNetworkServerPrefixSize(CFSTR s) throw(); + +bool IsNetworkShareRootPath(CFSTR s) throw(); /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */ + +bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\" +bool IsDriveRootPath_SuperAllowed(CFSTR s) throw(); // exact drive root path "a:\" or "\\?\a:\" + +bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:" +// bool IsDriveName2(const wchar_t *s) throw(); // is drive name like "a:" +bool IsSuperPath(const wchar_t *s) throw(); +bool IsSuperOrDevicePath(const wchar_t *s) throw(); + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath2(CFSTR s) throw(); // first 2 chars are drive chars like "a:" +// bool IsDriveName2(CFSTR s) throw(); // is drive name like "a:" +bool IsDrivePath(CFSTR s) throw(); +bool IsSuperPath(CFSTR s) throw(); +bool IsSuperOrDevicePath(CFSTR s) throw(); + +/* GetRootPrefixSize() returns size of ROOT PREFIX for cases: + \ + \\.\ + C:\ + \\?\C:\ + \\?\UNC\SERVER\Shared\ + \\SERVER\Shared\ + in another cases it returns 0 +*/ + +unsigned GetRootPrefixSize(CFSTR s) throw(); + +#endif + +int FindAltStreamColon(CFSTR path) throw(); + +#endif // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) throw(); +unsigned GetRootPrefixSize(const wchar_t *s) throw(); + +#ifdef WIN_LONG_PATH + +const int kSuperPathType_UseOnlyMain = 0; +const int kSuperPathType_UseOnlySuper = 1; +const int kSuperPathType_UseMainAndSuper = 2; + +int GetUseSuperPathType(CFSTR s) throw(); +bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew); +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew); + +#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper) +#define USE_MAIN_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlySuper && __useSuperPathType2 != kSuperPathType_UseOnlySuper) + +#define USE_SUPER_PATH (__useSuperPathType != kSuperPathType_UseOnlyMain) +#define USE_SUPER_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlyMain || __useSuperPathType2 != kSuperPathType_UseOnlyMain) + +#define IF_USE_MAIN_PATH int __useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH) +#define IF_USE_MAIN_PATH_2(x1, x2) \ + int __useSuperPathType1 = GetUseSuperPathType(x1); \ + int __useSuperPathType2 = GetUseSuperPathType(x2); \ + if (USE_MAIN_PATH_2) + +#else + +#define IF_USE_MAIN_PATH +#define IF_USE_MAIN_PATH_2(x1, x2) + +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath); +bool GetFullPath(CFSTR path, FString &fullPath); + +}}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/FileSystem.cpp b/other-licenses/7zstub/src/CPP/Windows/FileSystem.cpp new file mode 100644 index 0000000000..9861062808 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileSystem.cpp @@ -0,0 +1,131 @@ +// Windows/FileSystem.cpp + +#include "StdAfx.h" + +#ifndef UNDER_CE + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "FileSystem.h" +#include "Defs.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { +namespace NSystem { + +bool MyGetVolumeInformation( + CFSTR rootPath, + UString &volumeName, + LPDWORD volumeSerialNumber, + LPDWORD maximumComponentLength, + LPDWORD fileSystemFlags, + UString &fileSystemName) +{ + BOOL res; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR v[MAX_PATH + 2]; v[0] = 0; + TCHAR f[MAX_PATH + 2]; f[0] = 0; + res = GetVolumeInformation(fs2fas(rootPath), + v, MAX_PATH, + volumeSerialNumber, maximumComponentLength, fileSystemFlags, + f, MAX_PATH); + volumeName = MultiByteToUnicodeString(v); + fileSystemName = MultiByteToUnicodeString(f); + } + else + #endif + { + WCHAR v[MAX_PATH + 2]; v[0] = 0; + WCHAR f[MAX_PATH + 2]; f[0] = 0; + res = GetVolumeInformationW(fs2us(rootPath), + v, MAX_PATH, + volumeSerialNumber, maximumComponentLength, fileSystemFlags, + f, MAX_PATH); + volumeName = v; + fileSystemName = f; + } + return BOOLToBool(res); +} + +UINT MyGetDriveType(CFSTR pathName) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + return GetDriveType(fs2fas(pathName)); + } + else + #endif + { + return GetDriveTypeW(fs2us(pathName)); + } +} + +typedef BOOL (WINAPI * GetDiskFreeSpaceExA_Pointer)( + LPCSTR lpDirectoryName, // directory name + PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller + PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk + PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk +); + +typedef BOOL (WINAPI * GetDiskFreeSpaceExW_Pointer)( + LPCWSTR lpDirectoryName, // directory name + PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller + PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk + PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk +); + +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) +{ + DWORD numSectorsPerCluster, bytesPerSector, numFreeClusters, numClusters; + bool sizeIsDetected = false; + #ifndef _UNICODE + if (!g_IsNT) + { + GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA"); + if (pGetDiskFreeSpaceEx) + { + ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; + sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2fas(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); + totalSize = totalSize2.QuadPart; + freeSize = freeSize2.QuadPart; + } + if (!::GetDiskFreeSpace(fs2fas(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) + return false; + } + else + #endif + { + GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExW"); + if (pGetDiskFreeSpaceEx) + { + ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; + sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2us(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); + totalSize = totalSize2.QuadPart; + freeSize = freeSize2.QuadPart; + } + if (!::GetDiskFreeSpaceW(fs2us(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) + return false; + } + clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster; + if (!sizeIsDetected) + { + totalSize = clusterSize * (UInt64)numClusters; + freeSize = clusterSize * (UInt64)numFreeClusters; + } + return true; +} + +}}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/FileSystem.h b/other-licenses/7zstub/src/CPP/Windows/FileSystem.h new file mode 100644 index 0000000000..b0149de421 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/FileSystem.h @@ -0,0 +1,27 @@ +// Windows/FileSystem.h + +#ifndef __WINDOWS_FILE_SYSTEM_H +#define __WINDOWS_FILE_SYSTEM_H + +#include "../Common/MyString.h" +#include "../Common/MyTypes.h" + +namespace NWindows { +namespace NFile { +namespace NSystem { + +bool MyGetVolumeInformation( + CFSTR rootPath , + UString &volumeName, + LPDWORD volumeSerialNumber, + LPDWORD maximumComponentLength, + LPDWORD fileSystemFlags, + UString &fileSystemName); + +UINT MyGetDriveType(CFSTR pathName); + +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); + +}}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Handle.h b/other-licenses/7zstub/src/CPP/Windows/Handle.h new file mode 100644 index 0000000000..755eeb8c5f --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Handle.h @@ -0,0 +1,37 @@ +// Windows/Handle.h + +#ifndef __WINDOWS_HANDLE_H +#define __WINDOWS_HANDLE_H + +namespace NWindows { + +class CHandle +{ +protected: + HANDLE _handle; +public: + operator HANDLE() { return _handle; } + CHandle(): _handle(NULL) {} + ~CHandle() { Close(); } + bool IsCreated() const { return (_handle != NULL); } + bool Close() + { + if (_handle == NULL) + return true; + if (!::CloseHandle(_handle)) + return false; + _handle = NULL; + return true; + } + void Attach(HANDLE handle) { _handle = handle; } + HANDLE Detach() + { + HANDLE handle = _handle; + _handle = NULL; + return handle; + } +}; + +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/MemoryLock.cpp b/other-licenses/7zstub/src/CPP/Windows/MemoryLock.cpp new file mode 100644 index 0000000000..3cd82e50e8 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/MemoryLock.cpp @@ -0,0 +1,97 @@ +// Windows/MemoryLock.cpp + +#include "StdAfx.h" + +#include "MemoryLock.h" + +namespace NWindows { +namespace NSecurity { + +#ifndef UNDER_CE + +#ifdef _UNICODE +#define MY_FUNC_SELECT(f) :: f +#else +#define MY_FUNC_SELECT(f) my_ ## f +extern "C" { +typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); +typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); +typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges, + PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength); +} +#define GET_PROC_ADDR(fff, name) Func_ ## fff my_ ## fff = (Func_ ## fff)GetProcAddress(hModule, name) +#endif + +bool EnablePrivilege(LPCTSTR privilegeName, bool enable) +{ + bool res = false; + + #ifndef _UNICODE + + HMODULE hModule = ::LoadLibrary(TEXT("Advapi32.dll")); + if (hModule == NULL) + return false; + + GET_PROC_ADDR(OpenProcessToken, "OpenProcessToken"); + GET_PROC_ADDR(LookupPrivilegeValue, "LookupPrivilegeValueA"); + GET_PROC_ADDR(AdjustTokenPrivileges, "AdjustTokenPrivileges"); + + if (my_OpenProcessToken && + my_AdjustTokenPrivileges && + my_LookupPrivilegeValue) + + #endif + + { + HANDLE token; + if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) + { + TOKEN_PRIVILEGES tp; + if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid))) + { + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0); + if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL)) + res = (GetLastError() == ERROR_SUCCESS); + } + ::CloseHandle(token); + } + } + + #ifndef _UNICODE + + ::FreeLibrary(hModule); + + #endif + + return res; +} + + + +typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); + +/* + We suppose that Window 10 works incorrectly with "Large Pages" at: + - Windows 10 1703 (15063) + - Windows 10 1709 (16299) +*/ + +unsigned Get_LargePages_RiskLevel() +{ + OSVERSIONINFOEXW vi; + HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); + if (!ntdll) + return 0; + Func_RtlGetVersion func = (Func_RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion"); + if (!func) + return 0; + func(&vi); + return (vi.dwPlatformId == VER_PLATFORM_WIN32_NT + && vi.dwMajorVersion + vi.dwMinorVersion == 10 + && vi.dwBuildNumber <= 16299) ? 1 : 0; +} + +#endif + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/MemoryLock.h b/other-licenses/7zstub/src/CPP/Windows/MemoryLock.h new file mode 100644 index 0000000000..d82910feb9 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/MemoryLock.h @@ -0,0 +1,40 @@ +// Windows/MemoryLock.h + +#ifndef __WINDOWS_MEMORY_LOCK_H +#define __WINDOWS_MEMORY_LOCK_H + +#include "../Common/MyWindows.h" + +namespace NWindows { +namespace NSecurity { + +#ifndef UNDER_CE + +bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true); + +inline bool EnablePrivilege_LockMemory(bool enable = true) +{ + return EnablePrivilege(SE_LOCK_MEMORY_NAME, enable); +} + +inline void EnablePrivilege_SymLink() +{ + /* Probably we do not to set any Privilege for junction points. + But we need them for Symbolic links */ + NSecurity::EnablePrivilege(SE_RESTORE_NAME); + + /* Probably we need only SE_RESTORE_NAME, but there is also + SE_CREATE_SYMBOLIC_LINK_NAME. So we set it also. Do we need it? */ + + NSecurity::EnablePrivilege(TEXT("SeCreateSymbolicLinkPrivilege")); // SE_CREATE_SYMBOLIC_LINK_NAME + + // Do we need to set SE_BACKUP_NAME ? +} + +unsigned Get_LargePages_RiskLevel(); + +#endif + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/NtCheck.h b/other-licenses/7zstub/src/CPP/Windows/NtCheck.h new file mode 100644 index 0000000000..401e239e06 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/NtCheck.h @@ -0,0 +1,46 @@ +// Windows/NtCheck.h + +#ifndef __WINDOWS_NT_CHECK_H +#define __WINDOWS_NT_CHECK_H + +#ifdef _WIN32 + +#include "../Common/MyWindows.h" + +#if !defined(_WIN64) && !defined(UNDER_CE) +static inline bool IsItWindowsNT() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT); +} +#endif + +#ifndef _UNICODE + #if defined(_WIN64) || defined(UNDER_CE) + bool g_IsNT = true; + #define SET_IS_NT + #else + bool g_IsNT = false; + #define SET_IS_NT g_IsNT = IsItWindowsNT(); + #endif + #define NT_CHECK_ACTION + // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION } +#else + #if !defined(_WIN64) && !defined(UNDER_CE) + #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION } + #else + #define NT_CHECK_ACTION + #endif + #define SET_IS_NT +#endif + +#define NT_CHECK NT_CHECK_ACTION SET_IS_NT + +#else + +#define NT_CHECK + +#endif + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/PropVariant.cpp b/other-licenses/7zstub/src/CPP/Windows/PropVariant.cpp new file mode 100644 index 0000000000..6d9fb48ed4 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/PropVariant.cpp @@ -0,0 +1,347 @@ +// Windows/PropVariant.cpp + +#include "StdAfx.h" + +#include "../Common/Defs.h" + +#include "PropVariant.h" + +namespace NWindows { +namespace NCOM { + +BSTR AllocBstrFromAscii(const char *s) throw() +{ + if (!s) + return NULL; + UINT len = (UINT)strlen(s); + BSTR p = ::SysAllocStringLen(NULL, len); + if (p) + { + for (UINT i = 0; i <= len; i++) + p[i] = (Byte)s[i]; + } + return p; +} + +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw() +{ + p->bstrVal = ::SysAllocStringLen(NULL, numChars); + if (!p->bstrVal) + { + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } + p->vt = VT_BSTR; + return S_OK; +} + +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw() +{ + p->bstrVal = AllocBstrFromAscii(s); + if (p->bstrVal) + { + p->vt = VT_BSTR; + return S_OK; + } + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; +} + +CPropVariant::CPropVariant(const PROPVARIANT &varSrc) +{ + vt = VT_EMPTY; + InternalCopy(&varSrc); +} + +CPropVariant::CPropVariant(const CPropVariant &varSrc) +{ + vt = VT_EMPTY; + InternalCopy(&varSrc); +} + +CPropVariant::CPropVariant(BSTR bstrSrc) +{ + vt = VT_EMPTY; + *this = bstrSrc; +} + +CPropVariant::CPropVariant(LPCOLESTR lpszSrc) +{ + vt = VT_EMPTY; + *this = lpszSrc; +} + +CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc) +{ + InternalCopy(&varSrc); + return *this; +} + +CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc) +{ + InternalCopy(&varSrc); + return *this; +} + +CPropVariant& CPropVariant::operator=(BSTR bstrSrc) +{ + *this = (LPCOLESTR)bstrSrc; + return *this; +} + +static const char * const kMemException = "out of memory"; + +CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocString(lpszSrc); + if (!bstrVal && lpszSrc) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return *this; +} + +CPropVariant& CPropVariant::operator=(const UString &s) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(s, s.Len()); + if (!bstrVal) + throw kMemException; + return *this; +} + +CPropVariant& CPropVariant::operator=(const UString2 &s) +{ + /* + if (s.IsEmpty()) + *this = L""; + else + */ + { + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len()); + if (!bstrVal) + throw kMemException; + /* SysAllocStringLen probably appends a null-terminating character for NULL string. + But it doesn't specified in MSDN. + But we suppose that it works + + if (!s.GetRawPtr()) + { + *bstrVal = 0; + } + */ + + /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL) + pointers to this function causes an unexpected termination of the application. + Is it safe? Maybe we must chamnge the code for that case ? */ + } + return *this; +} + +CPropVariant& CPropVariant::operator=(const char *s) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = AllocBstrFromAscii(s); + if (!bstrVal) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return *this; +} + +CPropVariant& CPropVariant::operator=(bool bSrc) throw() +{ + if (vt != VT_BOOL) + { + InternalClear(); + vt = VT_BOOL; + } + boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; + return *this; +} + +BSTR CPropVariant::AllocBstr(unsigned numChars) +{ + if (vt != VT_EMPTY) + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(NULL, numChars); + if (!bstrVal) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return bstrVal; +} + +#define SET_PROP_FUNC(type, id, dest) \ + CPropVariant& CPropVariant::operator=(type value) throw() \ + { if (vt != id) { InternalClear(); vt = id; } \ + dest = value; return *this; } + +SET_PROP_FUNC(Byte, VT_UI1, bVal) +// SET_PROP_FUNC(Int16, VT_I2, iVal) +SET_PROP_FUNC(Int32, VT_I4, lVal) +SET_PROP_FUNC(UInt32, VT_UI4, ulVal) +SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) +SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) +SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) + +HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() +{ + switch (prop->vt) + { + case VT_EMPTY: + case VT_UI1: + case VT_I1: + case VT_I2: + case VT_UI2: + case VT_BOOL: + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_FILETIME: + case VT_UI8: + case VT_R8: + case VT_CY: + case VT_DATE: + prop->vt = VT_EMPTY; + prop->wReserved1 = 0; + prop->wReserved2 = 0; + prop->wReserved3 = 0; + prop->uhVal.QuadPart = 0; + return S_OK; + } + return ::VariantClear((VARIANTARG *)prop); + // return ::PropVariantClear(prop); + // PropVariantClear can clear VT_BLOB. +} + +HRESULT CPropVariant::Clear() throw() +{ + if (vt == VT_EMPTY) + return S_OK; + return PropVariant_Clear(this); +} + +HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() +{ + ::VariantClear((tagVARIANT *)this); + switch (pSrc->vt) + { + case VT_UI1: + case VT_I1: + case VT_I2: + case VT_UI2: + case VT_BOOL: + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_FILETIME: + case VT_UI8: + case VT_R8: + case VT_CY: + case VT_DATE: + memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); + return S_OK; + } + return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast(pSrc)); +} + + +HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() +{ + HRESULT hr = Clear(); + if (FAILED(hr)) + return hr; + memcpy(this, pSrc, sizeof(PROPVARIANT)); + pSrc->vt = VT_EMPTY; + return S_OK; +} + +HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw() +{ + if (pDest->vt != VT_EMPTY) + { + HRESULT hr = PropVariant_Clear(pDest); + if (FAILED(hr)) + return hr; + } + memcpy(pDest, this, sizeof(PROPVARIANT)); + vt = VT_EMPTY; + return S_OK; +} + +HRESULT CPropVariant::InternalClear() throw() +{ + if (vt == VT_EMPTY) + return S_OK; + HRESULT hr = Clear(); + if (FAILED(hr)) + { + vt = VT_ERROR; + scode = hr; + } + return hr; +} + +void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) +{ + HRESULT hr = Copy(pSrc); + if (FAILED(hr)) + { + if (hr == E_OUTOFMEMORY) + throw kMemException; + vt = VT_ERROR; + scode = hr; + } +} + +int CPropVariant::Compare(const CPropVariant &a) throw() +{ + if (vt != a.vt) + return MyCompare(vt, a.vt); + switch (vt) + { + case VT_EMPTY: return 0; + // case VT_I1: return MyCompare(cVal, a.cVal); + case VT_UI1: return MyCompare(bVal, a.bVal); + case VT_I2: return MyCompare(iVal, a.iVal); + case VT_UI2: return MyCompare(uiVal, a.uiVal); + case VT_I4: return MyCompare(lVal, a.lVal); + case VT_UI4: return MyCompare(ulVal, a.ulVal); + // case VT_UINT: return MyCompare(uintVal, a.uintVal); + case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); + case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); + case VT_BOOL: return -MyCompare(boolVal, a.boolVal); + case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); + case VT_BSTR: return 0; // Not implemented + default: return 0; + } +} + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/PropVariant.h b/other-licenses/7zstub/src/CPP/Windows/PropVariant.h new file mode 100644 index 0000000000..f2eaba2fd0 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/PropVariant.h @@ -0,0 +1,114 @@ +// Windows/PropVariant.h + +#ifndef __WINDOWS_PROP_VARIANT_H +#define __WINDOWS_PROP_VARIANT_H + +#include "../Common/MyTypes.h" +#include "../Common/MyWindows.h" +#include "../Common/MyString.h" + +namespace NWindows { +namespace NCOM { + +BSTR AllocBstrFromAscii(const char *s) throw(); + +HRESULT PropVariant_Clear(PROPVARIANT *p) throw(); + +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw(); +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw(); + +inline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw() +{ + p->vt = VT_UI4; + p->ulVal = v; +} + +inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_UI8; + p->uhVal.QuadPart = v; +} + +inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_FILETIME; + p->filetime.dwLowDateTime = (DWORD)v; + p->filetime.dwHighDateTime = (DWORD)(v >> 32); +} + +inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() +{ + p->vt = VT_BOOL; + p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE); +} + + +class CPropVariant : public tagPROPVARIANT +{ +public: + CPropVariant() + { + vt = VT_EMPTY; + wReserved1 = 0; + // wReserved2 = 0; + // wReserved3 = 0; + // uhVal.QuadPart = 0; + bstrVal = 0; + } + ~CPropVariant() throw() { Clear(); } + CPropVariant(const PROPVARIANT &varSrc); + CPropVariant(const CPropVariant &varSrc); + CPropVariant(BSTR bstrSrc); + CPropVariant(LPCOLESTR lpszSrc); + CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); } + CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } + +private: + CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; } + CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; } + +public: + CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } + CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; } + CPropVariant(Int64 value) { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; } + CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } + + CPropVariant& operator=(const CPropVariant &varSrc); + CPropVariant& operator=(const PROPVARIANT &varSrc); + CPropVariant& operator=(BSTR bstrSrc); + CPropVariant& operator=(LPCOLESTR lpszSrc); + CPropVariant& operator=(const UString &s); + CPropVariant& operator=(const UString2 &s); + CPropVariant& operator=(const char *s); + CPropVariant& operator=(const AString &s) + { return (*this)=(const char *)s; } + + CPropVariant& operator=(bool bSrc) throw(); + CPropVariant& operator=(Byte value) throw(); + +private: + CPropVariant& operator=(Int16 value) throw(); + +public: + CPropVariant& operator=(Int32 value) throw(); + CPropVariant& operator=(UInt32 value) throw(); + CPropVariant& operator=(UInt64 value) throw(); + CPropVariant& operator=(Int64 value) throw(); + CPropVariant& operator=(const FILETIME &value) throw(); + + BSTR AllocBstr(unsigned numChars); + + HRESULT Clear() throw(); + HRESULT Copy(const PROPVARIANT *pSrc) throw(); + HRESULT Attach(PROPVARIANT *pSrc) throw(); + HRESULT Detach(PROPVARIANT *pDest) throw(); + + HRESULT InternalClear() throw(); + void InternalCopy(const PROPVARIANT *pSrc); + + int Compare(const CPropVariant &a) throw(); +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/PropVariantConv.cpp b/other-licenses/7zstub/src/CPP/Windows/PropVariantConv.cpp new file mode 100644 index 0000000000..c5ac212602 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/PropVariantConv.cpp @@ -0,0 +1,138 @@ +// PropVariantConvert.cpp + +#include "StdAfx.h" + +#include "../Common/IntToString.h" + +#include "Defs.h" +#include "PropVariantConv.h" + +#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } + +bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() +{ + *s = 0; + FILETIME ft; + if (!FileTimeToLocalFileTime(&utc, &ft)) + return false; + + SYSTEMTIME st; + if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) + return false; + + { + unsigned val = st.wYear; + if (val >= 10000) + { + *s++ = (char)('0' + val / 10000); + val %= 10000; + } + s[3] = (char)('0' + val % 10); val /= 10; + s[2] = (char)('0' + val % 10); val /= 10; + s[1] = (char)('0' + val % 10); + s[0] = (char)('0' + val / 10); + s += 4; + } + UINT_TO_STR_2('-', st.wMonth); + UINT_TO_STR_2('-', st.wDay); + + if (level > kTimestampPrintLevel_DAY) + { + UINT_TO_STR_2(' ', st.wHour); + UINT_TO_STR_2(':', st.wMinute); + + if (level >= kTimestampPrintLevel_SEC) + { + UINT_TO_STR_2(':', st.wSecond); + + if (level > kTimestampPrintLevel_SEC) + { + *s++ = '.'; + /* + { + unsigned val = st.wMilliseconds; + s[2] = (char)('0' + val % 10); val /= 10; + s[1] = (char)('0' + val % 10); + s[0] = (char)('0' + val / 10); + s += 3; + } + *s++ = ' '; + */ + + { + unsigned numDigits = 7; + UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000); + for (unsigned i = numDigits; i != 0;) + { + i--; + s[i] = (char)('0' + val % 10); val /= 10; + } + if (numDigits > (unsigned)level) + numDigits = (unsigned)level; + s += numDigits; + } + } + } + } + + *s = 0; + return true; +} + + +bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw() +{ + char s[32]; + bool res = ConvertUtcFileTimeToString(ft, s, level); + for (unsigned i = 0;; i++) + { + unsigned char c = s[i]; + dest[i] = c; + if (c == 0) + break; + } + return res; +} + + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw() +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2); + } +} + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw() +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2); + } +} diff --git a/other-licenses/7zstub/src/CPP/Windows/PropVariantConv.h b/other-licenses/7zstub/src/CPP/Windows/PropVariantConv.h new file mode 100644 index 0000000000..3e2456926e --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/PropVariantConv.h @@ -0,0 +1,37 @@ +// Windows/PropVariantConv.h + +#ifndef __PROP_VARIANT_CONV_H +#define __PROP_VARIANT_CONV_H + +#include "../Common/MyTypes.h" + +// provide at least 32 bytes for buffer including zero-end + +#define kTimestampPrintLevel_DAY -3 +// #define kTimestampPrintLevel_HOUR -2 +#define kTimestampPrintLevel_MIN -1 +#define kTimestampPrintLevel_SEC 0 +#define kTimestampPrintLevel_NTFS 7 + +bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw(); +bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); + +// provide at least 32 bytes for buffer including zero-end +// don't send VT_BSTR to these functions +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw(); +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw(); + +inline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value) +{ + switch (prop.vt) + { + case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true; + case VT_UI4: value = prop.ulVal; return true; + case VT_UI2: value = prop.uiVal; return true; + case VT_UI1: value = prop.bVal; return true; + case VT_EMPTY: return false; + default: throw 151199; + } +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Registry.cpp b/other-licenses/7zstub/src/CPP/Windows/Registry.cpp new file mode 100644 index 0000000000..0146621402 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Registry.cpp @@ -0,0 +1,390 @@ +// Windows/Registry.cpp + +#include "StdAfx.h" + +#include + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif +#include "Registry.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NRegistry { + +#define MYASSERT(expr) // _ASSERTE(expr) + +LONG CKey::Create(HKEY parentKey, LPCTSTR keyName, + LPTSTR keyClass, DWORD options, REGSAM accessMask, + LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) throw() +{ + MYASSERT(parentKey != NULL); + DWORD dispositionReal; + HKEY key = NULL; + LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass, + options, accessMask, securityAttributes, &key, &dispositionReal); + if (disposition != NULL) + *disposition = dispositionReal; + if (res == ERROR_SUCCESS) + { + res = Close(); + _object = key; + } + return res; +} + +LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) throw() +{ + MYASSERT(parentKey != NULL); + HKEY key = NULL; + LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key); + if (res == ERROR_SUCCESS) + { + res = Close(); + MYASSERT(res == ERROR_SUCCESS); + _object = key; + } + return res; +} + +LONG CKey::Close() throw() +{ + LONG res = ERROR_SUCCESS; + if (_object != NULL) + { + res = RegCloseKey(_object); + _object = NULL; + } + return res; +} + +// win95, win98: deletes sunkey and all its subkeys +// winNT to be deleted must not have subkeys +LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() +{ + MYASSERT(_object != NULL); + return RegDeleteKey(_object, subKeyName); +} + +LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw() +{ + CKey key; + LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); + if (res != ERROR_SUCCESS) + return res; + FILETIME fileTime; + const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL + DWORD size = kBufSize; + TCHAR buffer[kBufSize]; + while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) + { + res = key.RecurseDeleteKey(buffer); + if (res != ERROR_SUCCESS) + return res; + size = kBufSize; + } + key.Close(); + return DeleteSubKey(subKeyName); +} + + +///////////////////////// +// Value Functions + +static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); } +static inline bool UINT32ToBool(UInt32 value) { return (value != 0); } + + +LONG CKey::DeleteValue(LPCTSTR name) throw() +{ + MYASSERT(_object != NULL); + return ::RegDeleteValue(_object, name); +} + +#ifndef _UNICODE +LONG CKey::DeleteValue(LPCWSTR name) +{ + MYASSERT(_object != NULL); + if (g_IsNT) + return ::RegDeleteValueW(_object, name); + return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name)); +} +#endif + +LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw() +{ + MYASSERT(_object != NULL); + return RegSetValueEx(_object, name, 0, REG_DWORD, + (BYTE * const)&value, sizeof(UInt32)); +} + +LONG CKey::SetValue(LPCTSTR name, bool value) throw() +{ + return SetValue(name, BoolToUINT32(value)); +} + +LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() +{ + MYASSERT(value != NULL); + MYASSERT(_object != NULL); + return RegSetValueEx(_object, name, 0, REG_SZ, + (const BYTE * )value, (lstrlen(value) + 1) * sizeof(TCHAR)); +} + +/* +LONG CKey::SetValue(LPCTSTR name, const CSysString &value) +{ + MYASSERT(value != NULL); + MYASSERT(_object != NULL); + return RegSetValueEx(_object, name, NULL, REG_SZ, + (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); +} +*/ + +#ifndef _UNICODE + +LONG CKey::SetValue(LPCWSTR name, LPCWSTR value) +{ + MYASSERT(value != NULL); + MYASSERT(_object != NULL); + if (g_IsNT) + return RegSetValueExW(_object, name, 0, REG_SZ, + (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); + return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), + value == 0 ? 0 : (LPCSTR)GetSystemString(value)); +} + +#endif + + +LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) throw() +{ + MYASSERT(value != NULL); + MYASSERT(_object != NULL); + return RegSetValueEx(_object, name, 0, REG_BINARY, + (const BYTE *)value, size); +} + +LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) +{ + MYASSERT(value != NULL); + CKey key; + LONG res = key.Create(parentKey, keyName); + if (res == ERROR_SUCCESS) + res = key.SetValue(valueName, value); + return res; +} + +LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw() +{ + MYASSERT(value != NULL); + CKey key; + LONG res = key.Create(_object, keyName); + if (res == ERROR_SUCCESS) + res = key.SetValue(valueName, value); + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw() +{ + DWORD type = 0; + DWORD count = sizeof(DWORD); + LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, + (LPBYTE)&value, &count); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD)); + MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32))); + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, bool &value) throw() +{ + UInt32 uintValue = BoolToUINT32(value); + LONG res = QueryValue(name, uintValue); + value = UINT32ToBool(uintValue); + return res; +} + +LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw() +{ + UInt32 newVal; + LONG res = QueryValue(name, newVal); + if (res == ERROR_SUCCESS) + value = newVal; + return res; +} + +LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw() +{ + bool newVal; + LONG res = QueryValue(name, newVal); + if (res == ERROR_SUCCESS) + value = newVal; + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw() +{ + DWORD type = 0; + LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, CSysString &value) +{ + value.Empty(); + DWORD type = 0; + UInt32 curSize = 0; + LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&curSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + UInt32 curSize2 = curSize; + res = QueryValue(name, value.GetBuf(curSize), curSize2); + if (curSize > curSize2) + curSize = curSize2; + value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR)); + return res; +} + + +#ifndef _UNICODE + +LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) +{ + DWORD type = 0; + LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); + return res; +} + +LONG CKey::QueryValue(LPCWSTR name, UString &value) +{ + value.Empty(); + DWORD type = 0; + UInt32 curSize = 0; + + LONG res; + + if (g_IsNT) + { + res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + UInt32 curSize2 = curSize; + res = QueryValue(name, value.GetBuf(curSize), curSize2); + if (curSize > curSize2) + curSize = curSize2; + value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t)); + } + else + { + AString vTemp; + res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); + value = GetUnicodeString(vTemp); + } + + return res; +} + +#endif + + +LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw() +{ + DWORD type = 0; + LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, (LPBYTE)value, (DWORD *)&count); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY)); + return res; +} + + +LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) +{ + DWORD type = 0; + dataSize = 0; + LONG res = RegQueryValueEx(_object, (LPTSTR)name, NULL, &type, NULL, (DWORD *)&dataSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + value.Alloc(dataSize); + return QueryValue(name, (BYTE *)value, dataSize); +} + +LONG CKey::EnumKeys(CSysStringVector &keyNames) +{ + keyNames.Clear(); + CSysString keyName; + for (DWORD index = 0; ; index++) + { + const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL + FILETIME lastWriteTime; + UInt32 nameSize = kBufSize; + LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize), + (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); + keyName.ReleaseBuf_CalcLen(kBufSize); + if (result == ERROR_NO_MORE_ITEMS) + break; + if (result != ERROR_SUCCESS) + return result; + keyNames.Add(keyName); + } + return ERROR_SUCCESS; +} + +LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) +{ + size_t numChars = 0; + + unsigned i; + + for (i = 0; i < strings.Size(); i++) + numChars += strings[i].Len() + 1; + + CObjArray buffer(numChars); + size_t pos = 0; + + for (i = 0; i < strings.Size(); i++) + { + const UString &s = strings[i]; + size_t size = s.Len() + 1; + wmemcpy(buffer + pos, s, size); + pos += size; + } + return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t)); +} + +LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) +{ + strings.Clear(); + CByteBuffer buffer; + UInt32 dataSize = 0; + LONG res = QueryValue(valueName, buffer, dataSize); + if (res != ERROR_SUCCESS) + return res; + if (dataSize > buffer.Size()) + return E_FAIL; + if (dataSize % sizeof(wchar_t) != 0) + return E_FAIL; + + const wchar_t *data = (const wchar_t *)(const Byte *)buffer; + size_t numChars = dataSize / sizeof(wchar_t); + size_t prev = 0; + UString s; + + for (size_t i = 0; i < numChars; i++) + { + if (data[i] == 0) + { + s = data + prev; + strings.Add(s); + prev = i + 1; + } + } + + return res; +} + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Registry.h b/other-licenses/7zstub/src/CPP/Windows/Registry.h new file mode 100644 index 0000000000..0a312304b0 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Registry.h @@ -0,0 +1,84 @@ +// Windows/Registry.h + +#ifndef __WINDOWS_REGISTRY_H +#define __WINDOWS_REGISTRY_H + +#include "../Common/MyBuffer.h" +#include "../Common/MyString.h" + +namespace NWindows { +namespace NRegistry { + +LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); + +class CKey +{ + HKEY _object; +public: + CKey(): _object(NULL) {} + ~CKey() { Close(); } + + operator HKEY() const { return _object; } + void Attach(HKEY key) { _object = key; } + HKEY Detach() + { + HKEY key = _object; + _object = NULL; + return key; + } + + LONG Create(HKEY parentKey, LPCTSTR keyName, + LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, + REGSAM accessMask = KEY_ALL_ACCESS, + LPSECURITY_ATTRIBUTES securityAttributes = NULL, + LPDWORD disposition = NULL) throw(); + LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS) throw(); + + LONG Close() throw(); + + LONG DeleteSubKey(LPCTSTR subKeyName) throw(); + LONG RecurseDeleteKey(LPCTSTR subKeyName) throw(); + + LONG DeleteValue(LPCTSTR name) throw(); + #ifndef _UNICODE + LONG DeleteValue(LPCWSTR name); + #endif + + LONG SetValue(LPCTSTR valueName, UInt32 value) throw(); + LONG SetValue(LPCTSTR valueName, bool value) throw(); + LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw(); + // LONG SetValue(LPCTSTR valueName, const CSysString &value); + #ifndef _UNICODE + LONG SetValue(LPCWSTR name, LPCWSTR value); + // LONG SetValue(LPCWSTR name, const UString &value); + #endif + + LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw(); + + LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings); + LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings); + + LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw(); + + LONG QueryValue(LPCTSTR name, UInt32 &value) throw(); + LONG QueryValue(LPCTSTR name, bool &value) throw(); + LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize) throw(); + LONG QueryValue(LPCTSTR name, CSysString &value); + + LONG GetValue_IfOk(LPCTSTR name, UInt32 &value) throw(); + LONG GetValue_IfOk(LPCTSTR name, bool &value) throw(); + + #ifndef _UNICODE + LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize); + LONG QueryValue(LPCWSTR name, UString &value); + #endif + + LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize) throw(); + LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); + + LONG EnumKeys(CSysStringVector &keyNames); +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/ResourceString.cpp b/other-licenses/7zstub/src/CPP/Windows/ResourceString.cpp new file mode 100644 index 0000000000..c28e60e07c --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/ResourceString.cpp @@ -0,0 +1,103 @@ +// Windows/ResourceString.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "ResourceString.h" + +extern HINSTANCE g_hInstance; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef _UNICODE + +static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID) +{ + CSysString s; + int size = 128; + int len; + do + { + size <<= 1; + len = ::LoadString(hInstance, resourceID, s.GetBuf(size - 1), size); + } + while (size - len <= 1); + s.ReleaseBuf_CalcLen(len); + return s; +} + +#endif + +static const int kStartSize = 256; + +static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s) +{ + int size = kStartSize; + int len; + do + { + size <<= 1; + len = ::LoadStringW(hInstance, resourceID, s.GetBuf(size - 1), size); + } + while (size - len <= 1); + s.ReleaseBuf_CalcLen(len); +} + +// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it. + +UString MyLoadString(UINT resourceID) +{ + #ifndef _UNICODE + if (!g_IsNT) + return GetUnicodeString(MyLoadStringA(g_hInstance, resourceID)); + else + #endif + { + { + wchar_t s[kStartSize]; + s[0] = 0; + int len = ::LoadStringW(g_hInstance, resourceID, s, kStartSize); + if (kStartSize - len > 1) + return s; + } + UString dest; + MyLoadString2(g_hInstance, resourceID, dest); + return dest; + } +} + +void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest) +{ + dest.Empty(); + #ifndef _UNICODE + if (!g_IsNT) + MultiByteToUnicodeString2(dest, MyLoadStringA(hInstance, resourceID)); + else + #endif + { + { + wchar_t s[kStartSize]; + s[0] = 0; + int len = ::LoadStringW(hInstance, resourceID, s, kStartSize); + if (kStartSize - len > 1) + { + dest = s; + return; + } + } + MyLoadString2(hInstance, resourceID, dest); + } +} + +void MyLoadString(UINT resourceID, UString &dest) +{ + MyLoadString(g_hInstance, resourceID, dest); +} + +} diff --git a/other-licenses/7zstub/src/CPP/Windows/ResourceString.h b/other-licenses/7zstub/src/CPP/Windows/ResourceString.h new file mode 100644 index 0000000000..cbaef4bfb3 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/ResourceString.h @@ -0,0 +1,16 @@ +// Windows/ResourceString.h + +#ifndef __WINDOWS_RESOURCE_STRING_H +#define __WINDOWS_RESOURCE_STRING_H + +#include "../Common/MyString.h" + +namespace NWindows { + +UString MyLoadString(UINT resourceID); +void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest); +void MyLoadString(UINT resourceID, UString &dest); + +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/SecurityUtils.cpp b/other-licenses/7zstub/src/CPP/Windows/SecurityUtils.cpp new file mode 100644 index 0000000000..8646cc9841 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/SecurityUtils.cpp @@ -0,0 +1,181 @@ +// Windows/SecurityUtils.cpp + +#include "StdAfx.h" + +#include "../Common/MyString.h" + +#include "SecurityUtils.h" + +namespace NWindows { +namespace NSecurity { + +/* +bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, + CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse) +{ + DWORD accountNameSize = 0, domainNameSize = 0; + + if (!::LookupAccountSid(systemName, sid, + accountName.GetBuf(0), &accountNameSize, + domainName.GetBuf(0), &domainNameSize, sidNameUse)) + { + if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return false; + } + DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize; + bool result = BOOLToBool(::LookupAccountSid(systemName, sid, + accountName.GetBuf(accountNameSize), &accountNameSize2, + domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse)); + accountName.ReleaseBuf_CalcLen(accountNameSize); + domainName.ReleaseBuf_CalcLen(domainNameSize); + return result; +} +*/ + +static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest) +{ + int len = (int)wcslen(src); + dest->Length = (USHORT)(len * sizeof(WCHAR)); + dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR)); + dest->Buffer = src; +} + +/* +static void MyLookupSids(CPolicy &policy, PSID ps) +{ + LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL; + LSA_TRANSLATED_NAME *names = NULL; + NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names); + int res = LsaNtStatusToWinError(nts); + LsaFreeMemory(referencedDomains); + LsaFreeMemory(names); +} +*/ + +#ifndef _UNICODE +typedef BOOL (WINAPI * LookupAccountNameWP)( + LPCWSTR lpSystemName, + LPCWSTR lpAccountName, + PSID Sid, + LPDWORD cbSid, + LPWSTR ReferencedDomainName, + LPDWORD cchReferencedDomainName, + PSID_NAME_USE peUse + ); +#endif + +static PSID GetSid(LPWSTR accountName) +{ + #ifndef _UNICODE + HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll")); + if (hModule == NULL) + return NULL; + LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW"); + if (lookupAccountNameW == NULL) + return NULL; + #endif + + DWORD sidLen = 0, domainLen = 0; + SID_NAME_USE sidNameUse; + if (! + #ifdef _UNICODE + ::LookupAccountNameW + #else + lookupAccountNameW + #endif + (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse)) + { + if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen); + LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR)); + BOOL res = + #ifdef _UNICODE + ::LookupAccountNameW + #else + lookupAccountNameW + #endif + (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse); + ::HeapFree(GetProcessHeap(), 0, domainName); + if (res) + return pSid; + } + } + return NULL; +} + +#define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege" + +bool AddLockMemoryPrivilege() +{ + CPolicy policy; + LSA_OBJECT_ATTRIBUTES attr; + attr.Length = sizeof(attr); + attr.RootDirectory = NULL; + attr.ObjectName = NULL; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + if (policy.Open(NULL, &attr, + // GENERIC_WRITE) + POLICY_ALL_ACCESS) + // STANDARD_RIGHTS_REQUIRED, + // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES) + != 0) + return false; + LSA_UNICODE_STRING userRights; + wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME; + SetLsaString(s, &userRights); + WCHAR userName[256 + 2]; + DWORD size = 256; + if (!GetUserNameW(userName, &size)) + return false; + PSID psid = GetSid(userName); + if (psid == NULL) + return false; + bool res = false; + + /* + PLSA_UNICODE_STRING userRightsArray; + ULONG countOfRights; + NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights); + if (status != 0) + return false; + bool finded = false; + for (ULONG i = 0; i < countOfRights; i++) + { + LSA_UNICODE_STRING &ur = userRightsArray[i]; + if (ur.Length != s.Length() * sizeof(WCHAR)) + continue; + if (wcsncmp(ur.Buffer, s, s.Length()) != 0) + continue; + finded = true; + res = true; + break; + } + if (!finded) + */ + { + /* + LSA_ENUMERATION_INFORMATION *enums; + ULONG countReturned; + NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned); + if (status == 0) + { + for (ULONG i = 0; i < countReturned; i++) + MyLookupSids(policy, enums[i].Sid); + if (enums) + ::LsaFreeMemory(enums); + res = true; + } + */ + NTSTATUS status = policy.AddAccountRights(psid, &userRights); + if (status == 0) + res = true; + // ULONG res = LsaNtStatusToWinError(status); + } + HeapFree(GetProcessHeap(), 0, psid); + return res; +} + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/SecurityUtils.h b/other-licenses/7zstub/src/CPP/Windows/SecurityUtils.h new file mode 100644 index 0000000000..16b6606e6c --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/SecurityUtils.h @@ -0,0 +1,167 @@ +// Windows/SecurityUtils.h + +#ifndef __WINDOWS_SECURITY_UTILS_H +#define __WINDOWS_SECURITY_UTILS_H + +#include + +#include "Defs.h" + +namespace NWindows { +namespace NSecurity { + +class CAccessToken +{ + HANDLE _handle; +public: + CAccessToken(): _handle(NULL) {}; + ~CAccessToken() { Close(); } + bool Close() + { + if (_handle == NULL) + return true; + bool res = BOOLToBool(::CloseHandle(_handle)); + if (res) + _handle = NULL; + return res; + } + + bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess) + { + Close(); + return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle)); + } + + /* + bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf) + { + Close(); + return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle)); + } + */ + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState, + DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength) + { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges), + newState, bufferLength, previousState, returnLength)); } + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); } + + bool AdjustPrivileges(PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(false, newState); } + +}; + +#ifndef _UNICODE +typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName, + PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle); +typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle); +typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle, + PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights ); +#define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) +#endif + +struct CPolicy +{ +protected: + LSA_HANDLE _handle; + #ifndef _UNICODE + HMODULE hModule; + #endif +public: + operator LSA_HANDLE() const { return _handle; } + CPolicy(): _handle(NULL) + { + #ifndef _UNICODE + hModule = GetModuleHandle(TEXT("Advapi32.dll")); + #endif + }; + ~CPolicy() { Close(); } + + NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes, + ACCESS_MASK desiredAccess) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy"); + if (lsaOpenPolicy == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + Close(); + return + #ifdef _UNICODE + ::LsaOpenPolicy + #else + lsaOpenPolicy + #endif + (systemName, objectAttributes, desiredAccess, &_handle); + } + + NTSTATUS Close() + { + if (_handle == NULL) + return 0; + + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose"); + if (lsaClose == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + NTSTATUS res = + #ifdef _UNICODE + ::LsaClose + #else + lsaClose + #endif + (_handle); + _handle = NULL; + return res; + } + + NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights, + PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned) + { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); } + + NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights) + { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); } + + NTSTATUS LookupSids(ULONG count, PSID* sids, + PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names) + { return LsaLookupSids(_handle, count, sids, referencedDomains, names); } + + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights"); + if (lsaAddAccountRights == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + return + #ifdef _UNICODE + ::LsaAddAccountRights + #else + lsaAddAccountRights + #endif + (_handle, accountSid, userRights, countOfRights); + } + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights) + { return AddAccountRights(accountSid, userRights, 1); } + + NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); } +}; + +bool AddLockMemoryPrivilege(); + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Shell.cpp b/other-licenses/7zstub/src/CPP/Windows/Shell.cpp new file mode 100644 index 0000000000..fde29ac7f0 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Shell.cpp @@ -0,0 +1,340 @@ +// Windows/Shell.cpp + +#include "StdAfx.h" + +#include "../Common/MyCom.h" +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "COM.h" +#include "Shell.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NShell { + +#ifndef UNDER_CE + +// SHGetMalloc is unsupported in Windows Mobile? + +void CItemIDList::Free() +{ + if (m_Object == NULL) + return; + CMyComPtr shellMalloc; + if (::SHGetMalloc(&shellMalloc) != NOERROR) + throw 41099; + shellMalloc->Free(m_Object); + m_Object = NULL; +} + +/* +CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL) + { *this = itemIDList; } +CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL) + { *this = itemIDList; } + +CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object) +{ + Free(); + if (object != 0) + { + UINT32 size = GetSize(object); + m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); + if (m_Object != NULL) + MoveMemory(m_Object, object, size); + } + return *this; +} + +CItemIDList& CItemIDList::operator=(const CItemIDList &object) +{ + Free(); + if (object.m_Object != NULL) + { + UINT32 size = GetSize(object.m_Object); + m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); + if (m_Object != NULL) + MoveMemory(m_Object, object.m_Object, size); + } + return *this; +} +*/ + +///////////////////////////// +// CDrop + +void CDrop::Attach(HDROP object) +{ + Free(); + m_Object = object; + m_Assigned = true; +} + +void CDrop::Free() +{ + if (m_MustBeFinished && m_Assigned) + Finish(); + m_Assigned = false; +} + +UINT CDrop::QueryCountOfFiles() +{ + return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0); +} + +UString CDrop::QueryFileName(UINT fileIndex) +{ + UString fileName; + #ifndef _UNICODE + if (!g_IsNT) + { + AString fileNameA; + UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0); + const unsigned len = bufferSize + 2; + QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1); + fileNameA.ReleaseBuf_CalcLen(len); + fileName = GetUnicodeString(fileNameA); + } + else + #endif + { + UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0); + const unsigned len = bufferSize + 2; + QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1); + fileName.ReleaseBuf_CalcLen(len); + } + return fileName; +} + +void CDrop::QueryFileNames(UStringVector &fileNames) +{ + UINT numFiles = QueryCountOfFiles(); + fileNames.ClearAndReserve(numFiles); + for (UINT i = 0; i < numFiles; i++) + fileNames.AddInReserved(QueryFileName(i)); +} + + +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path) +{ + const unsigned len = MAX_PATH * 2; + bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len))); + path.ReleaseBuf_CalcLen(len); + return result; +} + +#endif + +#ifdef UNDER_CE + +bool BrowseForFolder(LPBROWSEINFO, CSysString) +{ + return false; +} + +bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &) +{ + return false; +} + +bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, + LPCTSTR /* initialFolder */, CSysString & /* resultPath */) +{ + /* + // SHBrowseForFolder doesn't work before CE 6.0 ? + if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0) + MessageBoxW(0, L"no", L"", 0); + else + MessageBoxW(0, L"yes", L"", 0); + */ + /* + UString s = "all files"; + s += " (*.*)"; + return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true); + */ + return false; +} + +#else + +bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath) +{ + NWindows::NCOM::CComInitializer comInitializer; + LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo); + if (itemIDList == NULL) + return false; + CItemIDList itemIDListHolder; + itemIDListHolder.Attach(itemIDList); + return GetPathFromIDList(itemIDList, resultPath); +} + + +int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) +{ + #ifndef UNDER_CE + switch (uMsg) + { + case BFFM_INITIALIZED: + { + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data); + break; + } + /* + case BFFM_SELCHANGED: + { + TCHAR dir[MAX_PATH]; + if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir)) + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir); + else + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT("")); + break; + } + */ + default: + break; + } + #endif + return 0; +} + + +bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, + LPCTSTR initialFolder, CSysString &resultPath) +{ + CSysString displayName; + BROWSEINFO browseInfo; + browseInfo.hwndOwner = owner; + browseInfo.pidlRoot = NULL; + + // there are Unicode/Astring problems in some WinCE SDK ? + /* + #ifdef UNDER_CE + browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH); + browseInfo.lpszTitle = (LPCSTR)title; + #else + */ + browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); + browseInfo.lpszTitle = title; + // #endif + browseInfo.ulFlags = ulFlags; + browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL; + browseInfo.lParam = (LPARAM)initialFolder; + return BrowseForFolder(&browseInfo, resultPath); +} + +bool BrowseForFolder(HWND owner, LPCTSTR title, + LPCTSTR initialFolder, CSysString &resultPath) +{ + return BrowseForFolder(owner, title, + #ifndef UNDER_CE + BIF_NEWDIALOGSTYLE | + #endif + BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath); + // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) +} + +#ifndef _UNICODE + +typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath); + +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) +{ + path.Empty(); + SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP) + ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW"); + if (shGetPathFromIDListW == 0) + return false; + const unsigned len = MAX_PATH * 2; + bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len))); + path.ReleaseBuf_CalcLen(len); + return result; +} + +typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi); + +bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) +{ + NWindows::NCOM::CComInitializer comInitializer; + SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP) + ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW"); + if (shBrowseForFolderW == 0) + return false; + LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo); + if (itemIDList == NULL) + return false; + CItemIDList itemIDListHolder; + itemIDListHolder.Attach(itemIDList); + return GetPathFromIDList(itemIDList, resultPath); +} + + +int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) +{ + switch (uMsg) + { + case BFFM_INITIALIZED: + { + SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data); + break; + } + /* + case BFFM_SELCHANGED: + { + wchar_t dir[MAX_PATH * 2]; + + if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir)) + SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir); + else + SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L""); + break; + } + */ + default: + break; + } + return 0; +} + + +static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags, + LPCWSTR initialFolder, UString &resultPath) +{ + UString displayName; + BROWSEINFOW browseInfo; + browseInfo.hwndOwner = owner; + browseInfo.pidlRoot = NULL; + browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); + browseInfo.lpszTitle = title; + browseInfo.ulFlags = ulFlags; + browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL; + browseInfo.lParam = (LPARAM)initialFolder; + return BrowseForFolder(&browseInfo, resultPath); +} + +bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) +{ + if (g_IsNT) + return BrowseForFolder(owner, title, + BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS + // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. + , initialFolder, resultPath); + // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) + CSysString s; + bool res = BrowseForFolder(owner, GetSystemString(title), + BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS + // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. + , GetSystemString(initialFolder), s); + resultPath = GetUnicodeString(s); + return res; +} + +#endif + +#endif + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Shell.h b/other-licenses/7zstub/src/CPP/Windows/Shell.h new file mode 100644 index 0000000000..9068040980 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Shell.h @@ -0,0 +1,94 @@ +// Windows/Shell.h + +#ifndef __WINDOWS_SHELL_H +#define __WINDOWS_SHELL_H + +#include +#include + +#include "../Common/MyString.h" + +#include "Defs.h" + +namespace NWindows{ +namespace NShell{ + +///////////////////////// +// CItemIDList +#ifndef UNDER_CE + +class CItemIDList +{ + LPITEMIDLIST m_Object; +public: + CItemIDList(): m_Object(NULL) {} + // CItemIDList(LPCITEMIDLIST itemIDList); + // CItemIDList(const CItemIDList& itemIDList); + ~CItemIDList() { Free(); } + void Free(); + void Attach(LPITEMIDLIST object) + { + Free(); + m_Object = object; + } + LPITEMIDLIST Detach() + { + LPITEMIDLIST object = m_Object; + m_Object = NULL; + return object; + } + operator LPITEMIDLIST() { return m_Object;} + operator LPCITEMIDLIST() const { return m_Object;} + LPITEMIDLIST* operator&() { return &m_Object; } + LPITEMIDLIST operator->() { return m_Object; } + + // CItemIDList& operator=(LPCITEMIDLIST object); + // CItemIDList& operator=(const CItemIDList &object); +}; + +///////////////////////////// +// CDrop + +class CDrop +{ + HDROP m_Object; + bool m_MustBeFinished; + bool m_Assigned; + void Free(); +public: + CDrop(bool mustBeFinished) : m_MustBeFinished(mustBeFinished), m_Assigned(false) {} + ~CDrop() { Free(); } + + void Attach(HDROP object); + operator HDROP() { return m_Object;} + bool QueryPoint(LPPOINT point) + { return BOOLToBool(::DragQueryPoint(m_Object, point)); } + void Finish() { ::DragFinish(m_Object); } + UINT QueryFile(UINT fileIndex, LPTSTR fileName, UINT fileNameSize) + { return ::DragQueryFile(m_Object, fileIndex, fileName, fileNameSize); } + #ifndef _UNICODE + UINT QueryFile(UINT fileIndex, LPWSTR fileName, UINT fileNameSize) + { return ::DragQueryFileW(m_Object, fileIndex, fileName, fileNameSize); } + #endif + UINT QueryCountOfFiles(); + UString QueryFileName(UINT fileIndex); + void QueryFileNames(UStringVector &fileNames); +}; + +#endif + +///////////////////////////// +// Functions + +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path); +bool BrowseForFolder(LPBROWSEINFO lpbi, CSysString &resultPath); +bool BrowseForFolder(HWND owner, LPCTSTR title, LPCTSTR initialFolder, CSysString &resultPath); + +#ifndef _UNICODE +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path); +bool BrowseForFolder(LPBROWSEINFO lpbi, UString &resultPath); +bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath); +#endif +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/StdAfx.h b/other-licenses/7zstub/src/CPP/Windows/StdAfx.h new file mode 100644 index 0000000000..47a4895278 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/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/Windows/Synchronization.cpp b/other-licenses/7zstub/src/CPP/Windows/Synchronization.cpp new file mode 100644 index 0000000000..01f1ad90f6 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Synchronization.cpp @@ -0,0 +1,10 @@ +// Windows/Synchronization.cpp + +#include "StdAfx.h" + +#include "Synchronization.h" + +namespace NWindows { +namespace NSynchronization { + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/Synchronization.h b/other-licenses/7zstub/src/CPP/Windows/Synchronization.h new file mode 100644 index 0000000000..786da00c6f --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Synchronization.h @@ -0,0 +1,164 @@ +// Windows/Synchronization.h + +#ifndef __WINDOWS_SYNCHRONIZATION_H +#define __WINDOWS_SYNCHRONIZATION_H + +#include "../../C/Threads.h" + +#include "Defs.h" + +#ifdef _WIN32 +#include "Handle.h" +#endif + +namespace NWindows { +namespace NSynchronization { + +class CBaseEvent +{ +protected: + ::CEvent _object; +public: + bool IsCreated() { return Event_IsCreated(&_object) != 0; } + operator HANDLE() { return _object; } + CBaseEvent() { Event_Construct(&_object); } + ~CBaseEvent() { Close(); } + WRes Close() { return Event_Close(&_object); } + #ifdef _WIN32 + WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) + { + _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); + if (name == NULL && _object != 0) + return 0; + return ::GetLastError(); + } + WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) + { + _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); + if (_object != 0) + return 0; + return ::GetLastError(); + } + #endif + + WRes Set() { return Event_Set(&_object); } + // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } + WRes Reset() { return Event_Reset(&_object); } + WRes Lock() { return Event_Wait(&_object); } +}; + +class CManualResetEvent: public CBaseEvent +{ +public: + WRes Create(bool initiallyOwn = false) + { + return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); + } + WRes CreateIfNotCreated() + { + if (IsCreated()) + return 0; + return ManualResetEvent_CreateNotSignaled(&_object); + } + #ifdef _WIN32 + WRes CreateWithName(bool initiallyOwn, LPCTSTR name) + { + return CBaseEvent::Create(true, initiallyOwn, name); + } + #endif +}; + +class CAutoResetEvent: public CBaseEvent +{ +public: + WRes Create() + { + return AutoResetEvent_CreateNotSignaled(&_object); + } + WRes CreateIfNotCreated() + { + if (IsCreated()) + return 0; + return AutoResetEvent_CreateNotSignaled(&_object); + } +}; + +#ifdef _WIN32 +class CObject: public CHandle +{ +public: + WRes Lock(DWORD timeoutInterval = INFINITE) + { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } +}; +class CMutex: public CObject +{ +public: + WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) + { + _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name); + if (name == NULL && _handle != 0) + return 0; + return ::GetLastError(); + } + #ifndef UNDER_CE + WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) + { + _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); + if (_handle != 0) + return 0; + return ::GetLastError(); + } + #endif + WRes Release() + { + return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); + } +}; +class CMutexLock +{ + CMutex *_object; +public: + CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } + ~CMutexLock() { _object->Release(); } +}; +#endif + +class CSemaphore +{ + ::CSemaphore _object; +public: + CSemaphore() { Semaphore_Construct(&_object); } + ~CSemaphore() { Close(); } + WRes Close() { return Semaphore_Close(&_object); } + operator HANDLE() { return _object; } + WRes Create(UInt32 initiallyCount, UInt32 maxCount) + { + return Semaphore_Create(&_object, initiallyCount, maxCount); + } + WRes Release() { return Semaphore_Release1(&_object); } + WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } + WRes Lock() { return Semaphore_Wait(&_object); } +}; + +class CCriticalSection +{ + ::CCriticalSection _object; +public: + CCriticalSection() { CriticalSection_Init(&_object); } + ~CCriticalSection() { CriticalSection_Delete(&_object); } + void Enter() { CriticalSection_Enter(&_object); } + void Leave() { CriticalSection_Leave(&_object); } +}; + +class CCriticalSectionLock +{ + CCriticalSection *_object; + void Unlock() { _object->Leave(); } +public: + CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } + ~CCriticalSectionLock() { Unlock(); } +}; + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/System.cpp b/other-licenses/7zstub/src/CPP/Windows/System.cpp new file mode 100644 index 0000000000..c6f8275889 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/System.cpp @@ -0,0 +1,142 @@ +// Windows/System.cpp + +#include "StdAfx.h" + +#include "../Common/MyWindows.h" + +#include "../Common/Defs.h" + +#include "System.h" + +namespace NWindows { +namespace NSystem { + +UInt32 CountAffinity(DWORD_PTR mask) +{ + UInt32 num = 0; + for (unsigned i = 0; i < sizeof(mask) * 8; i++) + num += (UInt32)((mask >> i) & 1); + return num; +} + +#ifdef _WIN32 + +BOOL CProcessAffinity::Get() +{ + #ifndef UNDER_CE + return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask); + #else + return FALSE; + #endif +} + + +UInt32 GetNumberOfProcessors() +{ + // We need to know how many threads we can use. + // By default the process is assigned to one group. + // So we get the number of logical processors (threads) + // assigned to current process in the current group. + // Group size can be smaller than total number logical processors, for exammple, 2x36 + + CProcessAffinity pa; + + if (pa.Get() && pa.processAffinityMask != 0) + return pa.GetNumProcessThreads(); + + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + // the number of logical processors in the current group + return (UInt32)systemInfo.dwNumberOfProcessors; +} + +#else + +UInt32 GetNumberOfProcessors() +{ + return 1; +} + +#endif + + +#ifdef _WIN32 + +#ifndef UNDER_CE + +#if !defined(_WIN64) && defined(__GNUC__) + +typedef struct _MY_MEMORYSTATUSEX { + DWORD dwLength; + DWORD dwMemoryLoad; + DWORDLONG ullTotalPhys; + DWORDLONG ullAvailPhys; + DWORDLONG ullTotalPageFile; + DWORDLONG ullAvailPageFile; + DWORDLONG ullTotalVirtual; + DWORDLONG ullAvailVirtual; + DWORDLONG ullAvailExtendedVirtual; +} MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; + +#else + +#define MY_MEMORYSTATUSEX MEMORYSTATUSEX +#define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX + +#endif + +typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); + +#endif + +#endif + + +bool GetRamSize(UInt64 &size) +{ + size = (UInt64)(sizeof(size_t)) << 29; + + #ifdef _WIN32 + + #ifndef UNDER_CE + MY_MEMORYSTATUSEX stat; + stat.dwLength = sizeof(stat); + #endif + + #ifdef _WIN64 + + if (!::GlobalMemoryStatusEx(&stat)) + return false; + size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); + return true; + + #else + + #ifndef UNDER_CE + GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) + ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); + if (globalMemoryStatusEx && globalMemoryStatusEx(&stat)) + { + size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); + return true; + } + #endif + + { + MEMORYSTATUS stat2; + stat2.dwLength = sizeof(stat2); + ::GlobalMemoryStatus(&stat2); + size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys); + return true; + } + + #endif + + #else + + return false; + + #endif +} + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/System.h b/other-licenses/7zstub/src/CPP/Windows/System.h new file mode 100644 index 0000000000..bc28f47802 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/System.h @@ -0,0 +1,40 @@ +// Windows/System.h + +#ifndef __WINDOWS_SYSTEM_H +#define __WINDOWS_SYSTEM_H + +#include "../Common/MyTypes.h" + +namespace NWindows { +namespace NSystem { + +UInt32 CountAffinity(DWORD_PTR mask); + +struct CProcessAffinity +{ + // UInt32 numProcessThreads; + // UInt32 numSysThreads; + DWORD_PTR processAffinityMask; + DWORD_PTR systemAffinityMask; + + void InitST() + { + // numProcessThreads = 1; + // numSysThreads = 1; + processAffinityMask = 1; + systemAffinityMask = 1; + } + + UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); } + UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); } + + BOOL Get(); +}; + +UInt32 GetNumberOfProcessors(); + +bool GetRamSize(UInt64 &size); // returns false, if unknown ram size + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Thread.h b/other-licenses/7zstub/src/CPP/Windows/Thread.h new file mode 100644 index 0000000000..1b5863ce4c --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Thread.h @@ -0,0 +1,38 @@ +// Windows/Thread.h + +#ifndef __WINDOWS_THREAD_H +#define __WINDOWS_THREAD_H + +#include "../../C/Threads.h" + +#include "Defs.h" + +namespace NWindows { + +class CThread +{ + ::CThread thread; +public: + CThread() { Thread_Construct(&thread); } + ~CThread() { Close(); } + bool IsCreated() { return Thread_WasCreated(&thread) != 0; } + WRes Close() { return Thread_Close(&thread); } + WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) + { return Thread_Create(&thread, startAddress, parameter); } + WRes Wait() { return Thread_Wait(&thread); } + + #ifdef _WIN32 + operator HANDLE() { return thread; } + void Attach(HANDLE handle) { thread = handle; } + HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; } + DWORD Resume() { return ::ResumeThread(thread); } + DWORD Suspend() { return ::SuspendThread(thread); } + bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); } + int GetPriority() { return ::GetThreadPriority(thread); } + bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); } + #endif +}; + +} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/TimeUtils.cpp b/other-licenses/7zstub/src/CPP/Windows/TimeUtils.cpp new file mode 100644 index 0000000000..3fc02bc868 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/TimeUtils.cpp @@ -0,0 +1,213 @@ +// Windows/TimeUtils.cpp + +#include "StdAfx.h" + +#include "Defs.h" +#include "TimeUtils.h" + +namespace NWindows { +namespace NTime { + +static const UInt32 kNumTimeQuantumsInSecond = 10000000; +static const UInt32 kFileTimeStartYear = 1601; +static const UInt32 kDosTimeStartYear = 1980; +static const UInt32 kUnixTimeStartYear = 1970; +static const UInt64 kUnixTimeOffset = + (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); +static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); + #else + ft.dwLowDateTime = 0; + ft.dwHighDateTime = 0; + UInt64 res; + if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F, + (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res)) + return false; + res *= kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (UInt32)res; + ft.dwHighDateTime = (UInt32)(res >> 32); + return true; + #endif +} + +static const UInt32 kHighDosTime = 0xFF9FBF7D; +static const UInt32 kLowDosTime = 0x210000; + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + +bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + + WORD datePart, timePart; + if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart)) + { + dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; + return false; + } + dosTime = (((UInt32)datePart) << 16) + timePart; + + #else + + unsigned year, mon, day, hour, min, sec; + UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned temp; + UInt32 v; + v64 += (kNumTimeQuantumsInSecond * 2 - 1); + v64 /= kNumTimeQuantumsInSecond; + sec = (unsigned)(v64 % 60); + v64 /= 60; + min = (unsigned)(v64 % 60); + v64 /= 60; + hour = (unsigned)(v64 % 24); + v64 /= 24; + + v = (UInt32)v64; + + year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400); + v %= PERIOD_400; + + temp = (unsigned)(v / PERIOD_100); + if (temp == 4) + temp = 3; + year += temp * 100; + v -= temp * PERIOD_100; + + temp = v / PERIOD_4; + if (temp == 25) + temp = 24; + year += temp * 4; + v -= temp * PERIOD_4; + + temp = v / 365; + if (temp == 4) + temp = 3; + year += temp; + v -= temp * 365; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 1; mon <= 12; mon++) + { + unsigned s = ms[mon - 1]; + if (v < s) + break; + v -= s; + } + day = (unsigned)v + 1; + + dosTime = kLowDosTime; + if (year < kDosTimeStartYear) + return false; + year -= kDosTimeStartYear; + dosTime = kHighDosTime; + if (year >= 128) + return false; + dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1); + #endif + return true; +} + +UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw() +{ + return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; +} + +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() +{ + UInt64 v = UnixTimeToFileTime64(unixTime); + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw() +{ + return (UInt64)(kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; +} + +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() +{ + if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) + { + ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; + return false; + } + Int64 v = (Int64)kUnixTimeOffset + unixTime; + if (v < 0) + { + ft.dwLowDateTime = ft.dwHighDateTime = 0; + return false; + } + UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v2; + ft.dwHighDateTime = (DWORD)(v2 >> 32); + return true; +} + +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; +} + +bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + winTime /= kNumTimeQuantumsInSecond; + if (winTime < kUnixTimeOffset) + { + unixTime = 0; + return false; + } + winTime -= kUnixTimeOffset; + if (winTime > 0xFFFFFFFF) + { + unixTime = 0xFFFFFFFF; + return false; + } + unixTime = (UInt32)winTime; + return true; +} + +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw() +{ + resSeconds = 0; + if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || + day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) + return false; + UInt32 numYears = year - kFileTimeStartYear; + UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + month--; + for (unsigned i = 0; i < month; i++) + numDays += ms[i]; + numDays += day - 1; + resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; + return true; +} + +void GetCurUtcFileTime(FILETIME &ft) throw() +{ + // Both variants provide same low resolution on WinXP: about 15 ms. + // But GetSystemTimeAsFileTime is much faster. + + #ifdef UNDER_CE + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + #else + GetSystemTimeAsFileTime(&ft); + #endif +} + +}} diff --git a/other-licenses/7zstub/src/CPP/Windows/TimeUtils.h b/other-licenses/7zstub/src/CPP/Windows/TimeUtils.h new file mode 100644 index 0000000000..b0092f8702 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/TimeUtils.h @@ -0,0 +1,32 @@ +// Windows/TimeUtils.h + +#ifndef __WINDOWS_TIME_UTILS_H +#define __WINDOWS_TIME_UTILS_H + +#include "../Common/MyTypes.h" +#include "../Common/MyWindows.h" + +namespace NWindows { +namespace NTime { + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw(); +bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); + +// UInt32 Unix Time : for dates 1970-2106 +UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw(); +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw(); + +// Int64 Unix Time : negative values for dates before 1970 +UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw(); +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw(); + +bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw(); + +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); +void GetCurUtcFileTime(FILETIME &ft) throw(); + +}} + +#endif diff --git a/other-licenses/7zstub/src/CPP/Windows/Window.cpp b/other-licenses/7zstub/src/CPP/Windows/Window.cpp new file mode 100644 index 0000000000..0c7422240c --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Window.cpp @@ -0,0 +1,179 @@ +// Windows/Window.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif +#include "Window.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef _UNICODE +ATOM MyRegisterClass(CONST WNDCLASSW *wndClass) +{ + if (g_IsNT) + return RegisterClassW(wndClass); + WNDCLASSA wndClassA; + wndClassA.style = wndClass->style; + wndClassA.lpfnWndProc = wndClass->lpfnWndProc; + wndClassA.cbClsExtra = wndClass->cbClsExtra; + wndClassA.cbWndExtra = wndClass->cbWndExtra; + wndClassA.hInstance = wndClass->hInstance; + wndClassA.hIcon = wndClass->hIcon; + wndClassA.hCursor = wndClass->hCursor; + wndClassA.hbrBackground = wndClass->hbrBackground; + AString menuName; + AString className; + if (IS_INTRESOURCE(wndClass->lpszMenuName)) + wndClassA.lpszMenuName = (LPCSTR)wndClass->lpszMenuName; + else + { + menuName = GetSystemString(wndClass->lpszMenuName); + wndClassA.lpszMenuName = menuName; + } + if (IS_INTRESOURCE(wndClass->lpszClassName)) + wndClassA.lpszClassName = (LPCSTR)wndClass->lpszClassName; + else + { + className = GetSystemString(wndClass->lpszClassName); + wndClassA.lpszClassName = className; + } + return RegisterClassA(&wndClassA); +} + +bool CWindow::Create(LPCWSTR className, + LPCWSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) +{ + if (g_IsNT) + { + _window = ::CreateWindowW(className, windowName, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); + return (_window != NULL); + } + return Create(GetSystemString(className), GetSystemString(windowName), + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); +} + +bool CWindow::CreateEx(DWORD exStyle, LPCWSTR className, + LPCWSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) +{ + if (g_IsNT) + { + _window = ::CreateWindowExW(exStyle, className, windowName, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); + return (_window != NULL); + } + AString classNameA; + LPCSTR classNameP; + if (IS_INTRESOURCE(className)) + classNameP = (LPCSTR)className; + else + { + classNameA = GetSystemString(className); + classNameP = classNameA; + } + AString windowNameA; + LPCSTR windowNameP; + if (IS_INTRESOURCE(windowName)) + windowNameP = (LPCSTR)windowName; + else + { + windowNameA = GetSystemString(windowName); + windowNameP = windowNameA; + } + return CreateEx(exStyle, classNameP, windowNameP, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); +} + +#endif + +#ifndef _UNICODE +bool MySetWindowText(HWND wnd, LPCWSTR s) +{ + if (g_IsNT) + return BOOLToBool(::SetWindowTextW(wnd, s)); + return BOOLToBool(::SetWindowTextA(wnd, UnicodeStringToMultiByte(s))); +} +#endif + +bool CWindow::GetText(CSysString &s) +{ + s.Empty(); + int len = GetTextLength(); + if (len == 0) + return (::GetLastError() == ERROR_SUCCESS); + TCHAR *p = s.GetBuf(len); + { + int len2 = GetText(p, len + 1); + if (len > len2) + len = len2; + } + s.ReleaseBuf_CalcLen(len); + if (len == 0) + return (::GetLastError() == ERROR_SUCCESS); + return true; +} + +#ifndef _UNICODE +bool CWindow::GetText(UString &s) +{ + if (g_IsNT) + { + s.Empty(); + int len = GetWindowTextLengthW(_window); + if (len == 0) + return (::GetLastError() == ERROR_SUCCESS); + wchar_t *p = s.GetBuf(len); + { + int len2 = GetWindowTextW(_window, p, len + 1); + if (len > len2) + len = len2; + } + s.ReleaseBuf_CalcLen(len); + if (len == 0) + return (::GetLastError() == ERROR_SUCCESS); + return true; + } + CSysString sysString; + bool result = GetText(sysString); + MultiByteToUnicodeString2(s, sysString); + return result; +} +#endif + + +/* +bool CWindow::ModifyStyleBase(int styleOffset, + DWORD remove, DWORD add, UINT flags) +{ + DWORD style = GetWindowLong(styleOffset); + DWORD newStyle = (style & ~remove) | add; + if (style == newStyle) + return false; // it is not good + + SetWindowLong(styleOffset, newStyle); + if (flags != 0) + { + ::SetWindowPos(_window, NULL, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | flags); + } + return TRUE; +} +*/ + +} diff --git a/other-licenses/7zstub/src/CPP/Windows/Window.h b/other-licenses/7zstub/src/CPP/Windows/Window.h new file mode 100644 index 0000000000..4c80a5b4f6 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/Windows/Window.h @@ -0,0 +1,284 @@ +// Windows/Window.h + +#ifndef __WINDOWS_WINDOW_H +#define __WINDOWS_WINDOW_H + +#include "../Common/MyWindows.h" +#include "../Common/MyString.h" + +#include "Defs.h" + +#ifndef UNDER_CE + +#define MY__WM_CHANGEUISTATE 0x0127 +#define MY__WM_UPDATEUISTATE 0x0128 +#define MY__WM_QUERYUISTATE 0x0129 + +// LOWORD(wParam) values in WM_*UISTATE +#define MY__UIS_SET 1 +#define MY__UIS_CLEAR 2 +#define MY__UIS_INITIALIZE 3 + +// HIWORD(wParam) values in WM_*UISTATE +#define MY__UISF_HIDEFOCUS 0x1 +#define MY__UISF_HIDEACCEL 0x2 +#define MY__UISF_ACTIVE 0x4 + +#endif + +namespace NWindows { + +inline ATOM MyRegisterClass(CONST WNDCLASS *wndClass) + { return ::RegisterClass(wndClass); } + +#ifndef _UNICODE +ATOM MyRegisterClass(CONST WNDCLASSW *wndClass); +#endif + +#ifdef _UNICODE +inline bool MySetWindowText(HWND wnd, LPCWSTR s) { return BOOLToBool(::SetWindowText(wnd, s)); } +#else +bool MySetWindowText(HWND wnd, LPCWSTR s); +#endif + + +#ifdef UNDER_CE +#define GWLP_USERDATA GWL_USERDATA +#define GWLP_WNDPROC GWL_WNDPROC +#define BTNS_BUTTON TBSTYLE_BUTTON +#define WC_COMBOBOXW L"ComboBox" +#define DWLP_MSGRESULT DWL_MSGRESULT +#endif + +class CWindow +{ +private: + // bool ModifyStyleBase(int styleOffset, DWORD remove, DWORD add, UINT flags); +protected: + HWND _window; +public: + CWindow(HWND newWindow = NULL): _window(newWindow){}; + CWindow& operator=(HWND newWindow) + { + _window = newWindow; + return *this; + } + operator HWND() const { return _window; } + void Attach(HWND newWindow) { _window = newWindow; } + HWND Detach() + { + HWND window = _window; + _window = NULL; + return window; + } + + bool Foreground() { return BOOLToBool(::SetForegroundWindow(_window)); } + + HWND GetParent() const { return ::GetParent(_window); } + bool GetWindowRect(LPRECT rect) const { return BOOLToBool(::GetWindowRect(_window,rect)); } + #ifndef UNDER_CE + bool IsZoomed() const { return BOOLToBool(::IsZoomed(_window)); } + #endif + bool ClientToScreen(LPPOINT point) const { return BOOLToBool(::ClientToScreen(_window, point)); } + bool ScreenToClient(LPPOINT point) const { return BOOLToBool(::ScreenToClient(_window, point)); } + + bool CreateEx(DWORD exStyle, LPCTSTR className, + LPCTSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) + { + _window = ::CreateWindowEx(exStyle, className, windowName, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); + return (_window != NULL); + } + + bool Create(LPCTSTR className, + LPCTSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) + { + _window = ::CreateWindow(className, windowName, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); + return (_window != NULL); + } + + #ifndef _UNICODE + bool Create(LPCWSTR className, + LPCWSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam); + bool CreateEx(DWORD exStyle, LPCWSTR className, + LPCWSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam); + #endif + + + bool Destroy() + { + if (_window == NULL) + return true; + bool result = BOOLToBool(::DestroyWindow(_window)); + if (result) + _window = NULL; + return result; + } + bool IsWindow() { return BOOLToBool(::IsWindow(_window)); } + bool Move(int x, int y, int width, int height, bool repaint = true) + { return BOOLToBool(::MoveWindow(_window, x, y, width, height, BoolToBOOL(repaint))); } + + bool ChangeSubWindowSizeX(HWND hwnd, int xSize) + { + RECT rect; + ::GetWindowRect(hwnd, &rect); + POINT p1; + p1.x = rect.left; + p1.y = rect.top; + ScreenToClient(&p1); + return BOOLToBool(::MoveWindow(hwnd, p1.x, p1.y, xSize, rect.bottom - rect.top, TRUE)); + } + + void ScreenToClient(RECT *rect) + { + POINT p1, p2; + p1.x = rect->left; + p1.y = rect->top; + p2.x = rect->right; + p2.y = rect->bottom; + ScreenToClient(&p1); + ScreenToClient(&p2); + + rect->left = p1.x; + rect->top = p1.y; + rect->right = p2.x; + rect->bottom = p2.y; + } + + bool GetClientRect(LPRECT rect) { return BOOLToBool(::GetClientRect(_window, rect)); } + bool Show(int cmdShow) { return BOOLToBool(::ShowWindow(_window, cmdShow)); } + bool Show_Bool(bool show) { return Show(show ? SW_SHOW: SW_HIDE); } + + #ifndef UNDER_CE + bool SetPlacement(CONST WINDOWPLACEMENT *placement) { return BOOLToBool(::SetWindowPlacement(_window, placement)); } + bool GetPlacement(WINDOWPLACEMENT *placement) { return BOOLToBool(::GetWindowPlacement(_window, placement)); } + #endif + bool Update() { return BOOLToBool(::UpdateWindow(_window)); } + bool InvalidateRect(LPCRECT rect, bool backgroundErase = true) + { return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); } + void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, BoolToBOOL(redraw), 0); } + + LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); } + LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); } + // bool MyIsMaximized() const { return ((GetStyle() & WS_MAXIMIZE) != 0); } + + LONG_PTR SetLong(int index, LONG newLongPtr) { return ::SetWindowLong(_window, index, newLongPtr); } + LONG_PTR GetLong(int index) const { return ::GetWindowLong(_window, index); } + LONG_PTR SetUserDataLong(LONG newLongPtr) { return SetLong(GWLP_USERDATA, newLongPtr); } + LONG_PTR GetUserDataLong() const { return GetLong(GWLP_USERDATA); } + + + #ifdef UNDER_CE + + LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) { return SetLong(index, newLongPtr); } + LONG_PTR GetLongPtr(int index) const { return GetLong(index); } + + LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetUserDataLong(newLongPtr); } + LONG_PTR GetUserDataLongPtr() const { return GetUserDataLong(); } + + #else + + LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) + { return ::SetWindowLongPtr(_window, index, + #ifndef _WIN64 + (LONG) + #endif + newLongPtr); } + #ifndef _UNICODE + LONG_PTR SetLongPtrW(int index, LONG_PTR newLongPtr) + { return ::SetWindowLongPtrW(_window, index, + #ifndef _WIN64 + (LONG) + #endif + newLongPtr); } + #endif + + LONG_PTR GetLongPtr(int index) const { return ::GetWindowLongPtr(_window, index); } + LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetLongPtr(GWLP_USERDATA, newLongPtr); } + LONG_PTR GetUserDataLongPtr() const { return GetLongPtr(GWLP_USERDATA); } + + #endif + + /* + bool ModifyStyle(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0) + { return ModifyStyleBase(GWL_STYLE, remove, add, flags); } + bool ModifyStyleEx(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0) + { return ModifyStyleBase(GWL_EXSTYLE, remove, add, flags); } + */ + + HWND SetFocus() { return ::SetFocus(_window); } + + LRESULT SendMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::SendMessage(_window, message, wParam, lParam); } + #ifndef _UNICODE + LRESULT SendMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::SendMessageW(_window, message, wParam, lParam); } + #endif + + bool PostMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)); } + #ifndef _UNICODE + bool PostMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return BOOLToBool(::PostMessageW(_window, message, wParam, lParam)); } + #endif + + bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); } + #ifndef _UNICODE + bool SetText(LPCWSTR s) { return MySetWindowText(_window, s); } + #endif + + int GetTextLength() const + { return GetWindowTextLength(_window); } + UINT GetText(LPTSTR string, int maxCount) const + { return GetWindowText(_window, string, maxCount); } + bool GetText(CSysString &s); + #ifndef _UNICODE + /* + UINT GetText(LPWSTR string, int maxCount) const + { return GetWindowTextW(_window, string, maxCount); } + */ + bool GetText(UString &s); + #endif + + bool Enable(bool enable) + { return BOOLToBool(::EnableWindow(_window, BoolToBOOL(enable))); } + + bool IsEnabled() + { return BOOLToBool(::IsWindowEnabled(_window)); } + + #ifndef UNDER_CE + HMENU GetSystemMenu(bool revert) + { return ::GetSystemMenu(_window, BoolToBOOL(revert)); } + #endif + + UINT_PTR SetTimer(UINT_PTR idEvent, UINT elapse, TIMERPROC timerFunc = 0) + { return ::SetTimer(_window, idEvent, elapse, timerFunc); } + bool KillTimer(UINT_PTR idEvent) + {return BOOLToBool(::KillTimer(_window, idEvent)); } + + HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMsg(WM_SETICON, sizeType, (LPARAM)icon); } +}; + +#define RECT_SIZE_X(r) ((r).right - (r).left) +#define RECT_SIZE_Y(r) ((r).bottom - (r).top) + +inline bool IsKeyDown(int virtKey) { return (::GetKeyState(virtKey) & 0x8000) != 0; } + +} + +#endif diff --git a/other-licenses/7zstub/src/CS/7zip/Common/CRC.cs b/other-licenses/7zstub/src/CS/7zip/Common/CRC.cs new file mode 100644 index 0000000000..62bb8478ba --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Common/CRC.cs @@ -0,0 +1,55 @@ +// Common/CRC.cs + +namespace SevenZip +{ + class CRC + { + public static readonly uint[] Table; + + static CRC() + { + Table = new uint[256]; + const uint kPoly = 0xEDB88320; + for (uint i = 0; i < 256; i++) + { + uint r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >> 1) ^ kPoly; + else + r >>= 1; + Table[i] = r; + } + } + + uint _value = 0xFFFFFFFF; + + public void Init() { _value = 0xFFFFFFFF; } + + public void UpdateByte(byte b) + { + _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); + } + + public void Update(byte[] data, uint offset, uint size) + { + for (uint i = 0; i < size; i++) + _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); + } + + public uint GetDigest() { return _value ^ 0xFFFFFFFF; } + + static uint CalculateDigest(byte[] data, uint offset, uint size) + { + CRC crc = new CRC(); + // crc.Init(); + crc.Update(data, offset, size); + return crc.GetDigest(); + } + + static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) + { + return (CalculateDigest(data, offset, size) == digest); + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Common/CommandLineParser.cs b/other-licenses/7zstub/src/CS/7zip/Common/CommandLineParser.cs new file mode 100644 index 0000000000..b46f6f2095 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Common/CommandLineParser.cs @@ -0,0 +1,274 @@ +// CommandLineParser.cs + +using System; +using System.Collections; + +namespace SevenZip.CommandLineParser +{ + public enum SwitchType + { + Simple, + PostMinus, + LimitedPostString, + UnLimitedPostString, + PostChar + } + + public class SwitchForm + { + public string IDString; + public SwitchType Type; + public bool Multi; + public int MinLen; + public int MaxLen; + public string PostCharSet; + + public SwitchForm(string idString, SwitchType type, bool multi, + int minLen, int maxLen, string postCharSet) + { + IDString = idString; + Type = type; + Multi = multi; + MinLen = minLen; + MaxLen = maxLen; + PostCharSet = postCharSet; + } + public SwitchForm(string idString, SwitchType type, bool multi, int minLen): + this(idString, type, multi, minLen, 0, "") + { + } + public SwitchForm(string idString, SwitchType type, bool multi): + this(idString, type, multi, 0) + { + } + } + + public class SwitchResult + { + public bool ThereIs; + public bool WithMinus; + public ArrayList PostStrings = new ArrayList(); + public int PostCharIndex; + public SwitchResult() + { + ThereIs = false; + } + } + + public class Parser + { + public ArrayList NonSwitchStrings = new ArrayList(); + SwitchResult[] _switches; + + public Parser(int numSwitches) + { + _switches = new SwitchResult[numSwitches]; + for (int i = 0; i < numSwitches; i++) + _switches[i] = new SwitchResult(); + } + + bool ParseString(string srcString, SwitchForm[] switchForms) + { + int len = srcString.Length; + if (len == 0) + return false; + int pos = 0; + if (!IsItSwitchChar(srcString[pos])) + return false; + while (pos < len) + { + if (IsItSwitchChar(srcString[pos])) + pos++; + const int kNoLen = -1; + int matchedSwitchIndex = 0; + int maxLen = kNoLen; + for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) + { + int switchLen = switchForms[switchIndex].IDString.Length; + if (switchLen <= maxLen || pos + switchLen > len) + continue; + if (String.Compare(switchForms[switchIndex].IDString, 0, + srcString, pos, switchLen, true) == 0) + { + matchedSwitchIndex = switchIndex; + maxLen = switchLen; + } + } + if (maxLen == kNoLen) + throw new Exception("maxLen == kNoLen"); + SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; + SwitchForm switchForm = switchForms[matchedSwitchIndex]; + if ((!switchForm.Multi) && matchedSwitch.ThereIs) + throw new Exception("switch must be single"); + matchedSwitch.ThereIs = true; + pos += maxLen; + int tailSize = len - pos; + SwitchType type = switchForm.Type; + switch (type) + { + case SwitchType.PostMinus: + { + if (tailSize == 0) + matchedSwitch.WithMinus = false; + else + { + matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); + if (matchedSwitch.WithMinus) + pos++; + } + break; + } + case SwitchType.PostChar: + { + if (tailSize < switchForm.MinLen) + throw new Exception("switch is not full"); + string charSet = switchForm.PostCharSet; + const int kEmptyCharValue = -1; + if (tailSize == 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + int index = charSet.IndexOf(srcString[pos]); + if (index < 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + matchedSwitch.PostCharIndex = index; + pos++; + } + } + break; + } + case SwitchType.LimitedPostString: + case SwitchType.UnLimitedPostString: + { + int minLen = switchForm.MinLen; + if (tailSize < minLen) + throw new Exception("switch is not full"); + if (type == SwitchType.UnLimitedPostString) + { + matchedSwitch.PostStrings.Add(srcString.Substring(pos)); + return true; + } + String stringSwitch = srcString.Substring(pos, minLen); + pos += minLen; + for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) + { + char c = srcString[pos]; + if (IsItSwitchChar(c)) + break; + stringSwitch += c; + } + matchedSwitch.PostStrings.Add(stringSwitch); + break; + } + } + } + return true; + + } + + public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) + { + int numCommandStrings = commandStrings.Length; + bool stopSwitch = false; + for (int i = 0; i < numCommandStrings; i++) + { + string s = commandStrings[i]; + if (stopSwitch) + NonSwitchStrings.Add(s); + else + if (s == kStopSwitchParsing) + stopSwitch = true; + else + if (!ParseString(s, switchForms)) + NonSwitchStrings.Add(s); + } + } + + public SwitchResult this[int index] { get { return _switches[index]; } } + + public static int ParseCommand(CommandForm[] commandForms, string commandString, + out string postString) + { + for (int i = 0; i < commandForms.Length; i++) + { + string id = commandForms[i].IDString; + if (commandForms[i].PostStringMode) + { + if (commandString.IndexOf(id) == 0) + { + postString = commandString.Substring(id.Length); + return i; + } + } + else + if (commandString == id) + { + postString = ""; + return i; + } + } + postString = ""; + return -1; + } + + static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, + string commandString, ArrayList indices) + { + indices.Clear(); + int numUsedChars = 0; + for (int i = 0; i < numForms; i++) + { + CommandSubCharsSet charsSet = forms[i]; + int currentIndex = -1; + int len = charsSet.Chars.Length; + for (int j = 0; j < len; j++) + { + char c = charsSet.Chars[j]; + int newIndex = commandString.IndexOf(c); + if (newIndex >= 0) + { + if (currentIndex >= 0) + return false; + if (commandString.IndexOf(c, newIndex + 1) >= 0) + return false; + currentIndex = j; + numUsedChars++; + } + } + if (currentIndex == -1 && !charsSet.EmptyAllowed) + return false; + indices.Add(currentIndex); + } + return (numUsedChars == commandString.Length); + } + const char kSwitchID1 = '-'; + const char kSwitchID2 = '/'; + + const char kSwitchMinus = '-'; + const string kStopSwitchParsing = "--"; + + static bool IsItSwitchChar(char c) + { + return (c == kSwitchID1 || c == kSwitchID2); + } + } + + public class CommandForm + { + public string IDString = ""; + public bool PostStringMode = false; + public CommandForm(string idString, bool postStringMode) + { + IDString = idString; + PostStringMode = postStringMode; + } + } + + class CommandSubCharsSet + { + public string Chars = ""; + public bool EmptyAllowed = false; + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Common/InBuffer.cs b/other-licenses/7zstub/src/CS/7zip/Common/InBuffer.cs new file mode 100644 index 0000000000..9c47c73ae3 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Common/InBuffer.cs @@ -0,0 +1,72 @@ +// InBuffer.cs + +namespace SevenZip.Buffer +{ + public class InBuffer + { + byte[] m_Buffer; + uint m_Pos; + uint m_Limit; + uint m_BufferSize; + System.IO.Stream m_Stream; + bool m_StreamWasExhausted; + ulong m_ProcessedSize; + + public InBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void Init(System.IO.Stream stream) + { + m_Stream = stream; + m_ProcessedSize = 0; + m_Limit = 0; + m_Pos = 0; + m_StreamWasExhausted = false; + } + + public bool ReadBlock() + { + if (m_StreamWasExhausted) + return false; + m_ProcessedSize += m_Pos; + int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); + m_Pos = 0; + m_Limit = (uint)aNumProcessedBytes; + m_StreamWasExhausted = (aNumProcessedBytes == 0); + return (!m_StreamWasExhausted); + } + + + public void ReleaseStream() + { + // m_Stream.Close(); + m_Stream = null; + } + + public bool ReadByte(byte b) // check it + { + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return false; + b = m_Buffer[m_Pos++]; + return true; + } + + public byte ReadByte() + { + // return (byte)m_Stream.ReadByte(); + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return 0xFF; + return m_Buffer[m_Pos++]; + } + + public ulong GetProcessedSize() + { + return m_ProcessedSize + m_Pos; + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Common/OutBuffer.cs b/other-licenses/7zstub/src/CS/7zip/Common/OutBuffer.cs new file mode 100644 index 0000000000..c205aa6346 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Common/OutBuffer.cs @@ -0,0 +1,47 @@ +// OutBuffer.cs + +namespace SevenZip.Buffer +{ + public class OutBuffer + { + byte[] m_Buffer; + uint m_Pos; + uint m_BufferSize; + System.IO.Stream m_Stream; + ulong m_ProcessedSize; + + public OutBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void SetStream(System.IO.Stream stream) { m_Stream = stream; } + public void FlushStream() { m_Stream.Flush(); } + public void CloseStream() { m_Stream.Close(); } + public void ReleaseStream() { m_Stream = null; } + + public void Init() + { + m_ProcessedSize = 0; + m_Pos = 0; + } + + public void WriteByte(byte b) + { + m_Buffer[m_Pos++] = b; + if (m_Pos >= m_BufferSize) + FlushData(); + } + + public void FlushData() + { + if (m_Pos == 0) + return; + m_Stream.Write(m_Buffer, 0, (int)m_Pos); + m_Pos = 0; + } + + public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LZ/IMatchFinder.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LZ/IMatchFinder.cs new file mode 100644 index 0000000000..30fab86501 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LZ/IMatchFinder.cs @@ -0,0 +1,24 @@ +// IMatchFinder.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + interface IInWindowStream + { + void SetStream(System.IO.Stream inStream); + void Init(); + void ReleaseStream(); + Byte GetIndexByte(Int32 index); + UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); + UInt32 GetNumAvailableBytes(); + } + + interface IMatchFinder : IInWindowStream + { + void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter); + UInt32 GetMatches(UInt32[] distances); + void Skip(UInt32 num); + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzBinTree.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzBinTree.cs new file mode 100644 index 0000000000..7a9ca2092c --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzBinTree.cs @@ -0,0 +1,367 @@ +// LzBinTree.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + public class BinTree : InWindow, IMatchFinder + { + UInt32 _cyclicBufferPos; + UInt32 _cyclicBufferSize = 0; + UInt32 _matchMaxLen; + + UInt32[] _son; + UInt32[] _hash; + + UInt32 _cutValue = 0xFF; + UInt32 _hashMask; + UInt32 _hashSizeSum = 0; + + bool HASH_ARRAY = true; + + const UInt32 kHash2Size = 1 << 10; + const UInt32 kHash3Size = 1 << 16; + const UInt32 kBT2HashSize = 1 << 16; + const UInt32 kStartMaxLen = 1; + const UInt32 kHash3Offset = kHash2Size; + const UInt32 kEmptyHashValue = 0; + const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; + + UInt32 kNumHashDirectBytes = 0; + UInt32 kMinMatchCheck = 4; + UInt32 kFixHashSize = kHash2Size + kHash3Size; + + public void SetType(int numHashBytes) + { + HASH_ARRAY = (numHashBytes > 2); + if (HASH_ARRAY) + { + kNumHashDirectBytes = 0; + kMinMatchCheck = 4; + kFixHashSize = kHash2Size + kHash3Size; + } + else + { + kNumHashDirectBytes = 2; + kMinMatchCheck = 2 + 1; + kFixHashSize = 0; + } + } + + public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } + public new void ReleaseStream() { base.ReleaseStream(); } + + public new void Init() + { + base.Init(); + for (UInt32 i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + } + + public new void MovePos() + { + if (++_cyclicBufferPos >= _cyclicBufferSize) + _cyclicBufferPos = 0; + base.MovePos(); + if (_pos == kMaxValForNormalize) + Normalize(); + } + + public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } + + public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { return base.GetMatchLen(index, distance, limit); } + + public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } + + public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) + { + if (historySize > kMaxValForNormalize - 256) + throw new Exception(); + _cutValue = 16 + (matchMaxLen >> 1); + + UInt32 windowReservSize = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + + base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); + + _matchMaxLen = matchMaxLen; + + UInt32 cyclicBufferSize = historySize + 1; + if (_cyclicBufferSize != cyclicBufferSize) + _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; + + UInt32 hs = kBT2HashSize; + + if (HASH_ARRAY) + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + _hashMask = hs; + hs++; + hs += kFixHashSize; + } + if (hs != _hashSizeSum) + _hash = new UInt32[_hashSizeSum = hs]; + } + + public UInt32 GetMatches(UInt32[] distances) + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + return 0; + } + } + + UInt32 offset = 0; + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; + UInt32 hashValue, hash2Value = 0, hash3Value = 0; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + hash2Value = temp & (kHash2Size - 1); + temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); + hash3Value = temp & (kHash3Size - 1); + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + if (HASH_ARRAY) + { + UInt32 curMatch2 = _hash[hash2Value]; + UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; + _hash[hash2Value] = _pos; + _hash[kHash3Offset + hash3Value] = _pos; + if (curMatch2 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + if (curMatch3 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + if (offset != 0 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + } + + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + if (kNumHashDirectBytes != 0) + { + if (curMatch > matchMinPos) + { + if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != + _bufferBase[cur + kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + } + + UInt32 count = _cutValue; + + while(true) + { + if(curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while(++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + return offset; + } + + public void Skip(UInt32 num) + { + do + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + continue; + } + } + + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + + UInt32 hashValue; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + UInt32 hash2Value = temp & (kHash2Size - 1); + _hash[hash2Value] = _pos; + temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); + UInt32 hash3Value = temp & (kHash3Size - 1); + _hash[kHash3Offset + hash3Value] = _pos; + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + UInt32 count = _cutValue; + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while (++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + } + while (--num != 0); + } + + void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) + { + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + } + + void Normalize() + { + UInt32 subValue = _pos - _cyclicBufferSize; + NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); + NormalizeLinks(_hash, _hashSizeSum, subValue); + ReduceOffsets((Int32)subValue); + } + + public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzInWindow.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzInWindow.cs new file mode 100644 index 0000000000..f1974cef50 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzInWindow.cs @@ -0,0 +1,132 @@ +// LzInWindow.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + public class InWindow + { + public Byte[] _bufferBase = null; // pointer to buffer with data + System.IO.Stream _stream; + UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done + bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream + + UInt32 _pointerToLastSafePosition; + + public UInt32 _bufferOffset; + + public UInt32 _blockSize; // Size of Allocated memory block + public UInt32 _pos; // offset (from _buffer) of curent byte + UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream + + public void MoveBlock() + { + UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + + UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; + + // check negative offset ???? + for (UInt32 i = 0; i < numBytes; i++) + _bufferBase[i] = _bufferBase[offset + i]; + _bufferOffset -= offset; + } + + public virtual void ReadBlock() + { + if (_streamEndWasReached) + return; + while (true) + { + int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); + if (size == 0) + return; + int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); + if (numReadBytes == 0) + { + _posLimit = _streamPos; + UInt32 pointerToPostion = _bufferOffset + _posLimit; + if (pointerToPostion > _pointerToLastSafePosition) + _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); + + _streamEndWasReached = true; + return; + } + _streamPos += (UInt32)numReadBytes; + if (_streamPos >= _pos + _keepSizeAfter) + _posLimit = _streamPos - _keepSizeAfter; + } + } + + void Free() { _bufferBase = null; } + + public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) + { + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == null || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + _bufferBase = new Byte[_blockSize]; + } + _pointerToLastSafePosition = _blockSize - keepSizeAfter; + } + + public void SetStream(System.IO.Stream stream) { _stream = stream; } + public void ReleaseStream() { _stream = null; } + + public void Init() + { + _bufferOffset = 0; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + ReadBlock(); + } + + public void MovePos() + { + _pos++; + if (_pos > _posLimit) + { + UInt32 pointerToPostion = _bufferOffset + _pos; + if (pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + ReadBlock(); + } + } + + public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } + + // index + limit have not to exceed _keepSizeAfter; + public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { + if (_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (UInt32)(_pos + index); + distance++; + // Byte *pby = _buffer + (size_t)_pos + index; + UInt32 pby = _bufferOffset + _pos + (UInt32)index; + + UInt32 i; + for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); + return i; + } + + public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } + + public void ReduceOffsets(Int32 subValue) + { + _bufferOffset += (UInt32)subValue; + _posLimit -= (UInt32)subValue; + _pos -= (UInt32)subValue; + _streamPos -= (UInt32)subValue; + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzOutWindow.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzOutWindow.cs new file mode 100644 index 0000000000..84914f0d94 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LZ/LzOutWindow.cs @@ -0,0 +1,110 @@ +// LzOutWindow.cs + +namespace SevenZip.Compression.LZ +{ + public class OutWindow + { + byte[] _buffer = null; + uint _pos; + uint _windowSize = 0; + uint _streamPos; + System.IO.Stream _stream; + + public uint TrainSize = 0; + + public void Create(uint windowSize) + { + if (_windowSize != windowSize) + { + // System.GC.Collect(); + _buffer = new byte[windowSize]; + } + _windowSize = windowSize; + _pos = 0; + _streamPos = 0; + } + + public void Init(System.IO.Stream stream, bool solid) + { + ReleaseStream(); + _stream = stream; + if (!solid) + { + _streamPos = 0; + _pos = 0; + TrainSize = 0; + } + } + + public bool Train(System.IO.Stream stream) + { + long len = stream.Length; + uint size = (len < _windowSize) ? (uint)len : _windowSize; + TrainSize = size; + stream.Position = len - size; + _streamPos = _pos = 0; + while (size > 0) + { + uint curSize = _windowSize - _pos; + if (size < curSize) + curSize = size; + int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); + if (numReadBytes == 0) + return false; + size -= (uint)numReadBytes; + _pos += (uint)numReadBytes; + _streamPos += (uint)numReadBytes; + if (_pos == _windowSize) + _streamPos = _pos = 0; + } + return true; + } + + public void ReleaseStream() + { + Flush(); + _stream = null; + } + + public void Flush() + { + uint size = _pos - _streamPos; + if (size == 0) + return; + _stream.Write(_buffer, (int)_streamPos, (int)size); + if (_pos >= _windowSize) + _pos = 0; + _streamPos = _pos; + } + + public void CopyBlock(uint distance, uint len) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + for (; len > 0; len--) + { + if (pos >= _windowSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos >= _windowSize) + Flush(); + } + } + + public void PutByte(byte b) + { + _buffer[_pos++] = b; + if (_pos >= _windowSize) + Flush(); + } + + public byte GetByte(uint distance) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + return _buffer[pos]; + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaBase.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaBase.cs new file mode 100644 index 0000000000..8447a2a0ff --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaBase.cs @@ -0,0 +1,76 @@ +// LzmaBase.cs + +namespace SevenZip.Compression.LZMA +{ + internal abstract class Base + { + public const uint kNumRepDistances = 4; + public const uint kNumStates = 12; + + // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; + // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; + // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; + // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + + public struct State + { + public uint Index; + public void Init() { Index = 0; } + public void UpdateChar() + { + if (Index < 4) Index = 0; + else if (Index < 10) Index -= 3; + else Index -= 6; + } + public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } + public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } + public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } + public bool IsCharState() { return Index < 7; } + } + + public const int kNumPosSlotBits = 6; + public const int kDicLogSizeMin = 0; + // public const int kDicLogSizeMax = 30; + // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; + + public const int kNumLenToPosStatesBits = 2; // it's for speed optimization + public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; + + public const uint kMatchMinLen = 2; + + public static uint GetLenToPosState(uint len) + { + len -= kMatchMinLen; + if (len < kNumLenToPosStates) + return len; + return (uint)(kNumLenToPosStates - 1); + } + + public const int kNumAlignBits = 4; + public const uint kAlignTableSize = 1 << kNumAlignBits; + public const uint kAlignMask = (kAlignTableSize - 1); + + public const uint kStartPosModelIndex = 4; + public const uint kEndPosModelIndex = 14; + public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + + public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); + + public const uint kNumLitPosStatesBitsEncodingMax = 4; + public const uint kNumLitContextBitsMax = 8; + + public const int kNumPosStatesBitsMax = 4; + public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + public const int kNumPosStatesBitsEncodingMax = 4; + public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + + public const int kNumLowLenBits = 3; + public const int kNumMidLenBits = 3; + public const int kNumHighLenBits = 8; + public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; + public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; + public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + + (1 << kNumHighLenBits); + public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaDecoder.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaDecoder.cs new file mode 100644 index 0000000000..00bfe63802 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaDecoder.cs @@ -0,0 +1,398 @@ +// LzmaDecoder.cs + +using System; + +namespace SevenZip.Compression.LZMA +{ + using RangeCoder; + + public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream + { + class LenDecoder + { + BitDecoder m_Choice = new BitDecoder(); + BitDecoder m_Choice2 = new BitDecoder(); + BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); + uint m_NumPosStates = 0; + + public void Create(uint numPosStates) + { + for (uint posState = m_NumPosStates; posState < numPosStates; posState++) + { + m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); + m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); + } + m_NumPosStates = numPosStates; + } + + public void Init() + { + m_Choice.Init(); + for (uint posState = 0; posState < m_NumPosStates; posState++) + { + m_LowCoder[posState].Init(); + m_MidCoder[posState].Init(); + } + m_Choice2.Init(); + m_HighCoder.Init(); + } + + public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) + { + if (m_Choice.Decode(rangeDecoder) == 0) + return m_LowCoder[posState].Decode(rangeDecoder); + else + { + uint symbol = Base.kNumLowLenSymbols; + if (m_Choice2.Decode(rangeDecoder) == 0) + symbol += m_MidCoder[posState].Decode(rangeDecoder); + else + { + symbol += Base.kNumMidLenSymbols; + symbol += m_HighCoder.Decode(rangeDecoder); + } + return symbol; + } + } + } + + class LiteralDecoder + { + struct Decoder2 + { + BitDecoder[] m_Decoders; + public void Create() { m_Decoders = new BitDecoder[0x300]; } + public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) + { + uint symbol = 1; + do + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + while (symbol < 0x100); + return (byte)symbol; + } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) + { + uint symbol = 1; + do + { + uint matchBit = (uint)(matchByte >> 7) & 1; + matchByte <<= 1; + uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + { + while (symbol < 0x100) + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + break; + } + } + while (symbol < 0x100); + return (byte)symbol; + } + } + + Decoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && + m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint)1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Decoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + uint GetState(uint pos, byte prevByte) + { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) + { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) + { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } + }; + + LZ.OutWindow m_OutWindow = new LZ.OutWindow(); + RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); + + BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; + BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + + BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); + + LenDecoder m_LenDecoder = new LenDecoder(); + LenDecoder m_RepLenDecoder = new LenDecoder(); + + LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); + + uint m_DictionarySize; + uint m_DictionarySizeCheck; + + uint m_PosStateMask; + + public Decoder() + { + m_DictionarySize = 0xFFFFFFFF; + for (int i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); + } + + void SetDictionarySize(uint dictionarySize) + { + if (m_DictionarySize != dictionarySize) + { + m_DictionarySize = dictionarySize; + m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); + uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); + m_OutWindow.Create(blockSize); + } + } + + void SetLiteralProperties(int lp, int lc) + { + if (lp > 8) + throw new InvalidParamException(); + if (lc > 8) + throw new InvalidParamException(); + m_LiteralDecoder.Create(lp, lc); + } + + void SetPosBitsProperties(int pb) + { + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + uint numPosStates = (uint)1 << pb; + m_LenDecoder.Create(numPosStates); + m_RepLenDecoder.Create(numPosStates); + m_PosStateMask = numPosStates - 1; + } + + bool _solid = false; + void Init(System.IO.Stream inStream, System.IO.Stream outStream) + { + m_RangeDecoder.Init(inStream); + m_OutWindow.Init(outStream, _solid); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= m_PosStateMask; j++) + { + uint index = (i << Base.kNumPosStatesBitsMax) + j; + m_IsMatchDecoders[index].Init(); + m_IsRep0LongDecoders[index].Init(); + } + m_IsRepDecoders[i].Init(); + m_IsRepG0Decoders[i].Init(); + m_IsRepG1Decoders[i].Init(); + m_IsRepG2Decoders[i].Init(); + } + + m_LiteralDecoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + // m_PosSpecDecoder.Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + m_PosDecoders[i].Init(); + + m_LenDecoder.Init(); + m_RepLenDecoder.Init(); + m_PosAlignDecoder.Init(); + } + + public void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + Init(inStream, outStream); + + Base.State state = new Base.State(); + state.Init(); + uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + + UInt64 nowPos64 = 0; + UInt64 outSize64 = (UInt64)outSize; + if (nowPos64 < outSize64) + { + if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) + throw new DataErrorException(); + state.UpdateChar(); + byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); + m_OutWindow.PutByte(b); + nowPos64++; + } + while (nowPos64 < outSize64) + { + // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); + // while(nowPos64 < next) + { + uint posState = (uint)nowPos64 & m_PosStateMask; + if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) + { + byte b; + byte prevByte = m_OutWindow.GetByte(0); + if (!state.IsCharState()) + b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, + (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); + else + b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); + m_OutWindow.PutByte(b); + state.UpdateChar(); + nowPos64++; + } + else + { + uint len; + if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) + { + if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) + { + state.UpdateShortRep(); + m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); + nowPos64++; + continue; + } + } + else + { + UInt32 distance; + if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + distance = rep1; + } + else + { + if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; + state.UpdateRep(); + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); + state.UpdateMatch(); + uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); + if (posSlot >= Base.kStartPosModelIndex) + { + int numDirectBits = (int)((posSlot >> 1) - 1); + rep0 = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < Base.kEndPosModelIndex) + rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, + rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); + else + { + rep0 += (m_RangeDecoder.DecodeDirectBits( + numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); + rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); + } + } + else + rep0 = posSlot; + } + if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) + { + if (rep0 == 0xFFFFFFFF) + break; + throw new DataErrorException(); + } + m_OutWindow.CopyBlock(rep0, len); + nowPos64 += len; + } + } + } + m_OutWindow.Flush(); + m_OutWindow.ReleaseStream(); + m_RangeDecoder.ReleaseStream(); + } + + public void SetDecoderProperties(byte[] properties) + { + if (properties.Length < 5) + throw new InvalidParamException(); + int lc = properties[0] % 9; + int remainder = properties[0] / 9; + int lp = remainder % 5; + int pb = remainder / 5; + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + UInt32 dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); + SetDictionarySize(dictionarySize); + SetLiteralProperties(lp, lc); + SetPosBitsProperties(pb); + } + + public bool Train(System.IO.Stream stream) + { + _solid = true; + return m_OutWindow.Train(stream); + } + + /* + public override bool CanRead { get { return true; }} + public override bool CanWrite { get { return true; }} + public override bool CanSeek { get { return true; }} + public override long Length { get { return 0; }} + public override long Position + { + get { return 0; } + set { } + } + public override void Flush() { } + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + public override void Write(byte[] buffer, int offset, int count) + { + } + public override long Seek(long offset, System.IO.SeekOrigin origin) + { + return 0; + } + public override void SetLength(long value) {} + */ + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaEncoder.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaEncoder.cs new file mode 100644 index 0000000000..6dc2708bdf --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LZMA/LzmaEncoder.cs @@ -0,0 +1,1480 @@ +// LzmaEncoder.cs + +using System; + +namespace SevenZip.Compression.LZMA +{ + using RangeCoder; + + public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + { + enum EMatchFinderType + { + BT2, + BT4, + }; + + const UInt32 kIfinityPrice = 0xFFFFFFF; + + static Byte[] g_FastPos = new Byte[1 << 11]; + + static Encoder() + { + const Byte kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) + { + UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); + for (UInt32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } + + static UInt32 GetPosSlot(UInt32 pos) + { + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return (UInt32)(g_FastPos[pos >> 10] + 20); + return (UInt32)(g_FastPos[pos >> 20] + 40); + } + + static UInt32 GetPosSlot2(UInt32 pos) + { + if (pos < (1 << 17)) + return (UInt32)(g_FastPos[pos >> 6] + 12); + if (pos < (1 << 27)) + return (UInt32)(g_FastPos[pos >> 16] + 32); + return (UInt32)(g_FastPos[pos >> 26] + 52); + } + + Base.State _state = new Base.State(); + Byte _previousByte; + UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; + + void BaseInit() + { + _state.Init(); + _previousByte = 0; + for (UInt32 i = 0; i < Base.kNumRepDistances; i++) + _repDistances[i] = 0; + } + + const int kDefaultDictionaryLogSize = 22; + const UInt32 kNumFastBytesDefault = 0x20; + + class LiteralEncoder + { + public struct Encoder2 + { + BitEncoder[] m_Encoders; + + public void Create() { m_Encoders = new BitEncoder[0x300]; } + + public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } + + public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) + { + uint context = 1; + for (int i = 7; i >= 0; i--) + { + uint bit = (uint)((symbol >> i) & 1); + m_Encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) + { + uint context = 1; + bool same = true; + for (int i = 7; i >= 0; i--) + { + uint bit = (uint)((symbol >> i) & 1); + uint state = context; + if (same) + { + uint matchBit = (uint)((matchByte >> i) & 1); + state += ((1 + matchBit) << 8); + same = (matchBit == bit); + } + m_Encoders[state].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public uint GetPrice(bool matchMode, byte matchByte, byte symbol) + { + uint price = 0; + uint context = 1; + int i = 7; + if (matchMode) + { + for (; i >= 0; i--) + { + uint matchBit = (uint)(matchByte >> i) & 1; + uint bit = (uint)(symbol >> i) & 1; + price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + i--; + break; + } + } + } + for (; i >= 0; i--) + { + uint bit = (uint)(symbol >> i) & 1; + price += m_Encoders[context].GetPrice(bit); + context = (context << 1) | bit; + } + return price; + } + } + + Encoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint)1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Encoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) + { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } + } + + class LenEncoder + { + RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); + RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); + RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); + + public LenEncoder() + { + for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) + { + _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); + _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); + } + } + + public void Init(UInt32 numPosStates) + { + _choice.Init(); + _choice2.Init(); + for (UInt32 posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); + } + + public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + if (symbol < Base.kNumLowLenSymbols) + { + _choice.Encode(rangeEncoder, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + symbol -= Base.kNumLowLenSymbols; + _choice.Encode(rangeEncoder, 1); + if (symbol < Base.kNumMidLenSymbols) + { + _choice2.Encode(rangeEncoder, 0); + _midCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + _choice2.Encode(rangeEncoder, 1); + _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); + } + } + } + + public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) + { + UInt32 a0 = _choice.GetPrice0(); + UInt32 a1 = _choice.GetPrice1(); + UInt32 b0 = a1 + _choice2.GetPrice0(); + UInt32 b1 = a1 + _choice2.GetPrice1(); + UInt32 i = 0; + for (i = 0; i < Base.kNumLowLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); + } + for (; i < numSymbols; i++) + prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); + } + }; + + const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; + + class LenPriceTableEncoder : LenEncoder + { + UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; + UInt32 _tableSize; + UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; + + public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } + + public UInt32 GetPrice(UInt32 symbol, UInt32 posState) + { + return _prices[posState * Base.kNumLenSymbols + symbol]; + } + + void UpdateTable(UInt32 posState) + { + SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); + _counters[posState] = _tableSize; + } + + public void UpdateTables(UInt32 numPosStates) + { + for (UInt32 posState = 0; posState < numPosStates; posState++) + UpdateTable(posState); + } + + public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + base.Encode(rangeEncoder, symbol, posState); + if (--_counters[posState] == 0) + UpdateTable(posState); + } + } + + const UInt32 kNumOpts = 1 << 12; + class Optimal + { + public Base.State State; + + public bool Prev1IsChar; + public bool Prev2; + + public UInt32 PosPrev2; + public UInt32 BackPrev2; + + public UInt32 Price; + public UInt32 PosPrev; + public UInt32 BackPrev; + + public UInt32 Backs0; + public UInt32 Backs1; + public UInt32 Backs2; + public UInt32 Backs3; + + public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } + public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } + public bool IsShortRep() { return (BackPrev == 0); } + }; + Optimal[] _optimum = new Optimal[kNumOpts]; + LZ.IMatchFinder _matchFinder = null; + RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); + + RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; + + RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); + + LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); + LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); + + LiteralEncoder _literalEncoder = new LiteralEncoder(); + + UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; + + UInt32 _numFastBytes = kNumFastBytesDefault; + UInt32 _longestMatchLength; + UInt32 _numDistancePairs; + + UInt32 _additionalOffset; + + UInt32 _optimumEndIndex; + UInt32 _optimumCurrentIndex; + + bool _longestMatchWasFound; + + UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; + UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; + UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; + UInt32 _alignPriceCount; + + UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); + + int _posStateBits = 2; + UInt32 _posStateMask = (4 - 1); + int _numLiteralPosStateBits = 0; + int _numLiteralContextBits = 3; + + UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); + UInt32 _dictionarySizePrev = 0xFFFFFFFF; + UInt32 _numFastBytesPrev = 0xFFFFFFFF; + + Int64 nowPos64; + bool _finished; + System.IO.Stream _inStream; + + EMatchFinderType _matchFinderType = EMatchFinderType.BT4; + bool _writeEndMark = false; + + bool _needReleaseMFStream; + + void Create() + { + if (_matchFinder == null) + { + LZ.BinTree bt = new LZ.BinTree(); + int numHashBytes = 4; + if (_matchFinderType == EMatchFinderType.BT2) + numHashBytes = 2; + bt.SetType(numHashBytes); + _matchFinder = bt; + } + _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); + + if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) + return; + _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); + _dictionarySizePrev = _dictionarySize; + _numFastBytesPrev = _numFastBytes; + } + + public Encoder() + { + for (int i = 0; i < kNumOpts; i++) + _optimum[i] = new Optimal(); + for (int i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); + } + + void SetWriteEndMarkerMode(bool writeEndMarker) + { + _writeEndMark = writeEndMarker; + } + + void Init() + { + BaseInit(); + _rangeEncoder.Init(); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= _posStateMask; j++) + { + uint complexState = (i << Base.kNumPosStatesBitsMax) + j; + _isMatch[complexState].Init(); + _isRep0Long[complexState].Init(); + } + _isRep[i].Init(); + _isRepG0[i].Init(); + _isRepG1[i].Init(); + _isRepG2[i].Init(); + } + _literalEncoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i].Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + _posEncoders[i].Init(); + + _lenEncoder.Init((UInt32)1 << _posStateBits); + _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); + + _posAlignEncoder.Init(); + + _longestMatchWasFound = false; + _optimumEndIndex = 0; + _optimumCurrentIndex = 0; + _additionalOffset = 0; + } + + void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) + { + lenRes = 0; + numDistancePairs = _matchFinder.GetMatches(_matchDistances); + if (numDistancePairs > 0) + { + lenRes = _matchDistances[numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], + Base.kMatchMaxLen - lenRes); + } + _additionalOffset++; + } + + + void MovePos(UInt32 num) + { + if (num > 0) + { + _matchFinder.Skip(num); + _additionalOffset += num; + } + } + + UInt32 GetRepLen1Price(Base.State state, UInt32 posState) + { + return _isRepG0[state.Index].GetPrice0() + + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); + } + + UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) + { + UInt32 price; + if (repIndex == 0) + { + price = _isRepG0[state.Index].GetPrice0(); + price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + } + else + { + price = _isRepG0[state.Index].GetPrice1(); + if (repIndex == 1) + price += _isRepG1[state.Index].GetPrice0(); + else + { + price += _isRepG1[state.Index].GetPrice1(); + price += _isRepG2[state.Index].GetPrice(repIndex - 2); + } + } + return price; + } + + UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) + { + UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + return price + GetPureRepPrice(repIndex, state, posState); + } + + UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) + { + UInt32 price; + UInt32 lenToPosState = Base.GetLenToPosState(len); + if (pos < Base.kNumFullDistances) + price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; + else + price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + + _alignPrices[pos & Base.kAlignMask]; + return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + } + + UInt32 Backward(out UInt32 backRes, UInt32 cur) + { + _optimumEndIndex = cur; + UInt32 posMem = _optimum[cur].PosPrev; + UInt32 backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while (cur > 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; + } + + UInt32[] reps = new UInt32[Base.kNumRepDistances]; + UInt32[] repLens = new UInt32[Base.kNumRepDistances]; + + + UInt32 GetOptimum(UInt32 position, out UInt32 backRes) + { + if (_optimumEndIndex != _optimumCurrentIndex) + { + UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; + backRes = _optimum[_optimumCurrentIndex].BackPrev; + _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + return lenRes; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + ReadMatchDistances(out lenMain, out numDistancePairs); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = 0xFFFFFFFF; + return 1; + } + if (numAvailableBytes > Base.kMatchMaxLen) + numAvailableBytes = Base.kMatchMaxLen; + + UInt32 repMaxIndex = 0; + UInt32 i; + for (i = 0; i < Base.kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); + if (repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + UInt32 lenRes = repLens[repMaxIndex]; + MovePos(lenRes - 1); + return lenRes; + } + + if (lenMain >= _numFastBytes) + { + backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + + Byte currentByte = _matchFinder.GetIndexByte(0 - 1); + Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); + + if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = (UInt32)0xFFFFFFFF; + return 1; + } + + _optimum[0].State = _state; + + UInt32 posState = (position & _posStateMask); + + _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); + _optimum[1].MakeAsChar(); + + UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); + + if (matchByte == currentByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if (shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + + UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if(lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + return 1; + } + + _optimum[1].PosPrev = 0; + + _optimum[0].Backs0 = reps[0]; + _optimum[0].Backs1 = reps[1]; + _optimum[0].Backs2 = reps[2]; + _optimum[0].Backs3 = reps[3]; + + UInt32 len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); + + for (i = 0; i < Base.kNumRepDistances; i++) + { + UInt32 repLen = repLens[i]; + if (repLen < 2) + continue; + UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + Optimal optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + while (--repLen >= 2); + } + + UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > _matchDistances[offs]) + offs += 2; + for (; ; len++) + { + UInt32 distance = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + Optimal optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == _matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + UInt32 cur = 0; + + while (true) + { + cur++; + if (cur == lenEnd) + return Backward(out backRes, cur); + UInt32 newLen; + ReadMatchDistances(out newLen, out numDistancePairs); + if (newLen >= _numFastBytes) + { + _numDistancePairs = numDistancePairs; + _longestMatchLength = newLen; + _longestMatchWasFound = true; + return Backward(out backRes, cur); + } + position++; + UInt32 posPrev = _optimum[cur].PosPrev; + Base.State state; + if (_optimum[cur].Prev1IsChar) + { + posPrev--; + if (_optimum[cur].Prev2) + { + state = _optimum[_optimum[cur].PosPrev2].State; + if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + else + state = _optimum[posPrev].State; + state.UpdateChar(); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (_optimum[cur].IsShortRep()) + state.UpdateShortRep(); + else + state.UpdateChar(); + } + else + { + UInt32 pos; + if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + { + posPrev = _optimum[cur].PosPrev2; + pos = _optimum[cur].BackPrev2; + state.UpdateRep(); + } + else + { + pos = _optimum[cur].BackPrev; + if (pos < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + Optimal opt = _optimum[posPrev]; + if (pos < Base.kNumRepDistances) + { + if (pos == 0) + { + reps[0] = opt.Backs0; + reps[1] = opt.Backs1; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 1) + { + reps[0] = opt.Backs1; + reps[1] = opt.Backs0; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 2) + { + reps[0] = opt.Backs2; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs3; + } + else + { + reps[0] = opt.Backs3; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + else + { + reps[0] = (pos - Base.kNumRepDistances); + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + _optimum[cur].State = state; + _optimum[cur].Backs0 = reps[0]; + _optimum[cur].Backs1 = reps[1]; + _optimum[cur].Backs2 = reps[2]; + _optimum[cur].Backs3 = reps[3]; + UInt32 curPrice = _optimum[cur].Price; + + currentByte = _matchFinder.GetIndexByte(0 - 1); + matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); + + posState = (position & _posStateMask); + + UInt32 curAnd1Price = curPrice + + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). + GetPrice(!state.IsCharState(), matchByte, currentByte); + + Optimal nextOptimum = _optimum[cur + 1]; + + bool nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); + + if (matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if (shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + + UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; + numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); + numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) + { + // try Literal + rep0 + UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateChar(); + UInt32 posStateNext = (position + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAnd1Price + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + { + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + UInt32 startLen = 2; // speed optimization + + for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) + { + UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); + if (lenTest < 2) + continue; + UInt32 lenTestTemp = lenTest; + do + { + while (lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } + while(--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateRep(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = + repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, + _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), + _matchFinder.GetIndexByte((Int32)lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = lenTest + 1 + lenTest2; + while(lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; + _matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); + while (lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + UInt32 offs = 0; + while (startLen > _matchDistances[offs]) + offs += 2; + + for (UInt32 lenTest = startLen; ; lenTest++) + { + UInt32 curBack = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (lenTest == _matchDistances[offs]) + { + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateMatch(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). + GetPrice(true, + _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), + _matchFinder.GetIndexByte((Int32)lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + UInt32 offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + Base.kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + } + } + + bool ChangePair(UInt32 smallDist, UInt32 bigDist) + { + const int kDif = 7; + return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); + } + + void WriteEndMarker(UInt32 posState) + { + if (!_writeEndMark) + return; + + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + UInt32 len = Base.kMatchMinLen; + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + int footerBits = 30; + UInt32 posReduced = (((UInt32)1) << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + } + + void Flush(UInt32 nowPos) + { + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + _rangeEncoder.FlushStream(); + } + + public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) + { + inSize = 0; + outSize = 0; + finished = true; + + if (_inStream != null) + { + _matchFinder.SetStream(_inStream); + _matchFinder.Init(); + _needReleaseMFStream = true; + _inStream = null; + if (_trainSize > 0) + _matchFinder.Skip(_trainSize); + } + + if (_finished) + return; + _finished = true; + + + Int64 progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + UInt32 len, numDistancePairs; // it's not used + ReadMatchDistances(out len, out numDistancePairs); + UInt32 posState = (UInt32)(nowPos64) & _posStateMask; + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); + _state.UpdateChar(); + Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); + _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + while (true) + { + UInt32 pos; + UInt32 len = GetOptimum((UInt32)nowPos64, out pos); + + UInt32 posState = ((UInt32)nowPos64) & _posStateMask; + UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; + if (len == 1 && pos == 0xFFFFFFFF) + { + _isMatch[complexState].Encode(_rangeEncoder, 0); + Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); + LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); + if (!_state.IsCharState()) + { + Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); + subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); + } + else + subCoder.Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _state.UpdateChar(); + } + else + { + _isMatch[complexState].Encode(_rangeEncoder, 1); + if (pos < Base.kNumRepDistances) + { + _isRep[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 0) + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 0); + if (len == 1) + _isRep0Long[complexState].Encode(_rangeEncoder, 0); + else + _isRep0Long[complexState].Encode(_rangeEncoder, 1); + } + else + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 1) + _isRepG1[_state.Index].Encode(_rangeEncoder, 0); + else + { + _isRepG1[_state.Index].Encode(_rangeEncoder, 1); + _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); + } + } + if (len == 1) + _state.UpdateShortRep(); + else + { + _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + _state.UpdateRep(); + } + UInt32 distance = _repDistances[pos]; + if (pos != 0) + { + for (UInt32 i = pos; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + } + else + { + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + pos -= Base.kNumRepDistances; + UInt32 posSlot = GetPosSlot(pos); + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + + if (posSlot >= Base.kStartPosModelIndex) + { + int footerBits = (int)((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - baseVal; + + if (posSlot < Base.kEndPosModelIndex) + RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, + baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + _alignPriceCount++; + } + } + UInt32 distance = pos; + for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + _matchPriceCount++; + } + _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); + } + _additionalOffset -= len; + nowPos64 += len; + if (_additionalOffset == 0) + { + // if (!_fastMode) + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= Base.kAlignTableSize) + FillAlignPrices(); + inSize = nowPos64; + outSize = _rangeEncoder.GetProcessedSizeAdd(); + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + + if (nowPos64 - progressPosValuePrev >= (1 << 12)) + { + _finished = false; + finished = false; + return; + } + } + } + } + + void ReleaseMFStream() + { + if (_matchFinder != null && _needReleaseMFStream) + { + _matchFinder.ReleaseStream(); + _needReleaseMFStream = false; + } + } + + void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } + void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } + + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize) + { + _inStream = inStream; + _finished = false; + Create(); + SetOutStream(outStream); + Init(); + + // if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); + + nowPos64 = 0; + } + + + public void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + _needReleaseMFStream = false; + try + { + SetStreams(inStream, outStream, inSize, outSize); + while (true) + { + Int64 processedInSize; + Int64 processedOutSize; + bool finished; + CodeOneBlock(out processedInSize, out processedOutSize, out finished); + if (finished) + return; + if (progress != null) + { + progress.SetProgress(processedInSize, processedOutSize); + } + } + } + finally + { + ReleaseStreams(); + } + } + + const int kPropSize = 5; + Byte[] properties = new Byte[kPropSize]; + + public void WriteCoderProperties(System.IO.Stream outStream) + { + properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); + for (int i = 0; i < 4; i++) + properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF); + outStream.Write(properties, 0, kPropSize); + } + + UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; + UInt32 _matchPriceCount; + + void FillDistancesPrices() + { + for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot(i); + int footerBits = (int)((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, + baseVal - posSlot - 1, footerBits, i - baseVal); + } + + for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; + + UInt32 st = (lenToPosState << Base.kNumPosSlotBits); + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); + for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); + + UInt32 st2 = lenToPosState * Base.kNumFullDistances; + UInt32 i; + for (i = 0; i < Base.kStartPosModelIndex; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + i]; + for (; i < Base.kNumFullDistances; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; + } + + void FillAlignPrices() + { + for (UInt32 i = 0; i < Base.kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; + } + + + static string[] kMatchFinderIDs = + { + "BT2", + "BT4", + }; + + static int FindMatchFinder(string s) + { + for (int m = 0; m < kMatchFinderIDs.Length; m++) + if (s == kMatchFinderIDs[m]) + return m; + return -1; + } + + public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) + { + for (UInt32 i = 0; i < properties.Length; i++) + { + object prop = properties[i]; + switch (propIDs[i]) + { + case CoderPropID.NumFastBytes: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 numFastBytes = (Int32)prop; + if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) + throw new InvalidParamException(); + _numFastBytes = (UInt32)numFastBytes; + break; + } + case CoderPropID.Algorithm: + { + /* + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 maximize = (Int32)prop; + _fastMode = (maximize == 0); + _maxMode = (maximize >= 2); + */ + break; + } + case CoderPropID.MatchFinder: + { + if (!(prop is String)) + throw new InvalidParamException(); + EMatchFinderType matchFinderIndexPrev = _matchFinderType; + int m = FindMatchFinder(((string)prop).ToUpper()); + if (m < 0) + throw new InvalidParamException(); + _matchFinderType = (EMatchFinderType)m; + if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) + { + _dictionarySizePrev = 0xFFFFFFFF; + _matchFinder = null; + } + break; + } + case CoderPropID.DictionarySize: + { + const int kDicLogSizeMaxCompress = 30; + if (!(prop is Int32)) + throw new InvalidParamException(); ; + Int32 dictionarySize = (Int32)prop; + if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || + dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) + throw new InvalidParamException(); + _dictionarySize = (UInt32)dictionarySize; + int dicLogSize; + for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) + if (dictionarySize <= ((UInt32)(1) << dicLogSize)) + break; + _distTableSize = (UInt32)dicLogSize * 2; + break; + } + case CoderPropID.PosStateBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _posStateBits = (int)v; + _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; + break; + } + case CoderPropID.LitPosBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _numLiteralPosStateBits = (int)v; + break; + } + case CoderPropID.LitContextBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) + throw new InvalidParamException(); ; + _numLiteralContextBits = (int)v; + break; + } + case CoderPropID.EndMarker: + { + if (!(prop is Boolean)) + throw new InvalidParamException(); + SetWriteEndMarkerMode((Boolean)prop); + break; + } + default: + throw new InvalidParamException(); + } + } + } + + uint _trainSize = 0; + public void SetTrainSize(uint trainSize) + { + _trainSize = trainSize; + } + + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs new file mode 100644 index 0000000000..8aa446267a --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs @@ -0,0 +1,364 @@ +using System; +using System.IO; +namespace SevenZip +{ + using CommandLineParser; + + public class CDoubleStream: Stream + { + public System.IO.Stream s1; + public System.IO.Stream s2; + public int fileIndex; + public long skipSize; + + public override bool CanRead { get { return true; }} + public override bool CanWrite { get { return false; }} + public override bool CanSeek { get { return false; }} + public override long Length { get { return s1.Length + s2.Length - skipSize; } } + public override long Position + { + get { return 0; } + set { } + } + public override void Flush() { } + public override int Read(byte[] buffer, int offset, int count) + { + int numTotal = 0; + while (count > 0) + { + if (fileIndex == 0) + { + int num = s1.Read(buffer, offset, count); + offset += num; + count -= num; + numTotal += num; + if (num == 0) + fileIndex++; + } + if (fileIndex == 1) + { + numTotal += s2.Read(buffer, offset, count); + return numTotal; + } + } + return numTotal; + } + public override void Write(byte[] buffer, int offset, int count) + { + throw (new Exception("can't Write")); + } + public override long Seek(long offset, System.IO.SeekOrigin origin) + { + throw (new Exception("can't Seek")); + } + public override void SetLength(long value) + { + throw (new Exception("can't SetLength")); + } + } + + class LzmaAlone + { + enum Key + { + Help1 = 0, + Help2, + Mode, + Dictionary, + FastBytes, + LitContext, + LitPos, + PosBits, + MatchFinder, + EOS, + StdIn, + StdOut, + Train + }; + + static void PrintHelp() + { + System.Console.WriteLine("\nUsage: LZMA [...] inputFile outputFile\n" + + " e: encode file\n" + + " d: decode file\n" + + " b: Benchmark\n" + + "\n" + + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + + " -eos: write End Of Stream marker\n" + // + " -si: read data from stdin\n" + // + " -so: write data to stdout\n" + ); + } + + static bool GetNumber(string s, out Int32 v) + { + v = 0; + for (int i = 0; i < s.Length; i++) + { + char c = s[i]; + if (c < '0' || c > '9') + return false; + v *= 10; + v += (Int32)(c - '0'); + } + return true; + } + + static int IncorrectCommand() + { + throw (new Exception("Command line error")); + // System.Console.WriteLine("\nCommand line error\n"); + // return 1; + } + static int Main2(string[] args) + { + System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); + + if (args.Length == 0) + { + PrintHelp(); + return 0; + } + + SwitchForm[] kSwitchForms = new SwitchForm[13]; + int sw = 0; + kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); + + + Parser parser = new Parser(sw); + try + { + parser.ParseStrings(kSwitchForms, args); + } + catch + { + return IncorrectCommand(); + } + + if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) + { + PrintHelp(); + return 0; + } + + System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; + + int paramIndex = 0; + if (paramIndex >= nonSwitchStrings.Count) + return IncorrectCommand(); + string command = (string)nonSwitchStrings[paramIndex++]; + command = command.ToLower(); + + bool dictionaryIsDefined = false; + Int32 dictionary = 1 << 21; + if (parser[(int)Key.Dictionary].ThereIs) + { + Int32 dicLog; + if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) + IncorrectCommand(); + dictionary = (Int32)1 << dicLog; + dictionaryIsDefined = true; + } + string mf = "bt4"; + if (parser[(int)Key.MatchFinder].ThereIs) + mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; + mf = mf.ToLower(); + + if (command == "b") + { + const Int32 kNumDefaultItereations = 10; + Int32 numIterations = kNumDefaultItereations; + if (paramIndex < nonSwitchStrings.Count) + if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) + numIterations = kNumDefaultItereations; + return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); + } + + string train = ""; + if (parser[(int)Key.Train].ThereIs) + train = (string)parser[(int)Key.Train].PostStrings[0]; + + bool encodeMode = false; + if (command == "e") + encodeMode = true; + else if (command == "d") + encodeMode = false; + else + IncorrectCommand(); + + bool stdInMode = parser[(int)Key.StdIn].ThereIs; + bool stdOutMode = parser[(int)Key.StdOut].ThereIs; + + Stream inStream = null; + if (stdInMode) + { + throw (new Exception("Not implemeted")); + } + else + { + if (paramIndex >= nonSwitchStrings.Count) + IncorrectCommand(); + string inputName = (string)nonSwitchStrings[paramIndex++]; + inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); + } + + FileStream outStream = null; + if (stdOutMode) + { + throw (new Exception("Not implemeted")); + } + else + { + if (paramIndex >= nonSwitchStrings.Count) + IncorrectCommand(); + string outputName = (string)nonSwitchStrings[paramIndex++]; + outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); + } + + FileStream trainStream = null; + if (train.Length != 0) + trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); + + if (encodeMode) + { + if (!dictionaryIsDefined) + dictionary = 1 << 23; + + Int32 posStateBits = 2; + Int32 litContextBits = 3; // for normal files + // UInt32 litContextBits = 0; // for 32-bit data + Int32 litPosBits = 0; + // UInt32 litPosBits = 2; // for 32-bit data + Int32 algorithm = 2; + Int32 numFastBytes = 128; + + bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; + + if (parser[(int)Key.Mode].ThereIs) + if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) + IncorrectCommand(); + + if (parser[(int)Key.FastBytes].ThereIs) + if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) + IncorrectCommand(); + if (parser[(int)Key.LitContext].ThereIs) + if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) + IncorrectCommand(); + if (parser[(int)Key.LitPos].ThereIs) + if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) + IncorrectCommand(); + if (parser[(int)Key.PosBits].ThereIs) + if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) + IncorrectCommand(); + + CoderPropID[] propIDs = + { + CoderPropID.DictionarySize, + CoderPropID.PosStateBits, + CoderPropID.LitContextBits, + CoderPropID.LitPosBits, + CoderPropID.Algorithm, + CoderPropID.NumFastBytes, + CoderPropID.MatchFinder, + CoderPropID.EndMarker + }; + object[] properties = + { + (Int32)(dictionary), + (Int32)(posStateBits), + (Int32)(litContextBits), + (Int32)(litPosBits), + (Int32)(algorithm), + (Int32)(numFastBytes), + mf, + eos + }; + + Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); + encoder.SetCoderProperties(propIDs, properties); + encoder.WriteCoderProperties(outStream); + Int64 fileSize; + if (eos || stdInMode) + fileSize = -1; + else + fileSize = inStream.Length; + for (int i = 0; i < 8; i++) + outStream.WriteByte((Byte)(fileSize >> (8 * i))); + if (trainStream != null) + { + CDoubleStream doubleStream = new CDoubleStream(); + doubleStream.s1 = trainStream; + doubleStream.s2 = inStream; + doubleStream.fileIndex = 0; + inStream = doubleStream; + long trainFileSize = trainStream.Length; + doubleStream.skipSize = 0; + if (trainFileSize > dictionary) + doubleStream.skipSize = trainFileSize - dictionary; + trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); + encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); + } + encoder.Code(inStream, outStream, -1, -1, null); + } + else if (command == "d") + { + byte[] properties = new byte[5]; + if (inStream.Read(properties, 0, 5) != 5) + throw (new Exception("input .lzma is too short")); + Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); + decoder.SetDecoderProperties(properties); + if (trainStream != null) + { + if (!decoder.Train(trainStream)) + throw (new Exception("can't train")); + } + long outSize = 0; + for (int i = 0; i < 8; i++) + { + int v = inStream.ReadByte(); + if (v < 0) + throw (new Exception("Can't Read 1")); + outSize |= ((long)(byte)v) << (8 * i); + } + long compressedSize = inStream.Length - inStream.Position; + decoder.Code(inStream, outStream, compressedSize, outSize, null); + } + else + throw (new Exception("Command Error")); + return 0; + } + + [STAThread] + static int Main(string[] args) + { + try + { + return Main2(args); + } + catch (Exception e) + { + Console.WriteLine("{0} Caught exception #1.", e); + // throw e; + return 1; + } + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj new file mode 100644 index 0000000000..ceb7073504 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj @@ -0,0 +1,90 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973} + Exe + LzmaAlone + Lzma# + 4 + + + true + full + false + .\bin\Debug\ + DEBUG;TRACE + + + false + true + .\bin\Release\ + TRACE + AnyCPU + + + + + + + + + Common\CommandLineParser.cs + + + Common\CRC.cs + + + ICoder.cs + + + LZ\IMatchFinder.cs + + + LZ\LzBinTree.cs + + + LZ\LzInWindow.cs + + + LZ\LzOutWindow.cs + + + LZMA\LzmaBase.cs + + + LZMA\LzmaDecoder.cs + + + LZMA\LzmaEncoder.cs + + + RangeCoder\RangeCoder.cs + + + RangeCoder\RangeCoderBit.cs + + + RangeCoder\RangeCoderBitTree.cs + + + Code + + + Code + + + + True + Settings.settings + + + SettingsSingleFileGenerator + Settings.cs + + + + + \ No newline at end of file diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln new file mode 100644 index 0000000000..a96ee3e433 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C# Express 2005 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaBench.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaBench.cs new file mode 100644 index 0000000000..6a1ffe2460 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/LzmaBench.cs @@ -0,0 +1,340 @@ +// LzmaBench.cs + +using System; +using System.IO; + +namespace SevenZip +{ + /// + /// LZMA Benchmark + /// + internal abstract class LzmaBench + { + const UInt32 kAdditionalSize = (6 << 20); + const UInt32 kCompressedAdditionalSize = (1 << 10); + const UInt32 kMaxLzmaPropSize = 10; + + class CRandomGenerator + { + UInt32 A1; + UInt32 A2; + public CRandomGenerator() { Init(); } + public void Init() { A1 = 362436069; A2 = 521288629; } + public UInt32 GetRnd() + { + return + ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); + } + }; + + class CBitRandomGenerator + { + CRandomGenerator RG = new CRandomGenerator(); + UInt32 Value; + int NumBits; + public void Init() + { + Value = 0; + NumBits = 0; + } + public UInt32 GetRnd(int numBits) + { + UInt32 result; + if (NumBits > numBits) + { + result = Value & (((UInt32)1 << numBits) - 1); + Value >>= numBits; + NumBits -= numBits; + return result; + } + numBits -= NumBits; + result = (Value << numBits); + Value = RG.GetRnd(); + result |= Value & (((UInt32)1 << numBits) - 1); + Value >>= numBits; + NumBits = 32 - numBits; + return result; + } + }; + + class CBenchRandomGenerator + { + CBitRandomGenerator RG = new CBitRandomGenerator(); + UInt32 Pos; + UInt32 Rep0; + + public UInt32 BufferSize; + public Byte[] Buffer = null; + + public CBenchRandomGenerator() { } + + public void Set(UInt32 bufferSize) + { + Buffer = new Byte[bufferSize]; + Pos = 0; + BufferSize = bufferSize; + } + UInt32 GetRndBit() { return RG.GetRnd(1); } + UInt32 GetLogRandBits(int numBits) + { + UInt32 len = RG.GetRnd(numBits); + return RG.GetRnd((int)len); + } + UInt32 GetOffset() + { + if (GetRndBit() == 0) + return GetLogRandBits(4); + return (GetLogRandBits(4) << 10) | RG.GetRnd(10); + } + UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } + UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } + public void Generate() + { + RG.Init(); + Rep0 = 1; + while (Pos < BufferSize) + { + if (GetRndBit() == 0 || Pos < 1) + Buffer[Pos++] = (Byte)RG.GetRnd(8); + else + { + UInt32 len; + if (RG.GetRnd(3) == 0) + len = 1 + GetLen1(); + else + { + do + Rep0 = GetOffset(); + while (Rep0 >= Pos); + Rep0++; + len = 2 + GetLen2(); + } + for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) + Buffer[Pos] = Buffer[Pos - Rep0]; + } + } + } + }; + + class CrcOutStream : System.IO.Stream + { + public CRC CRC = new CRC(); + public void Init() { CRC.Init(); } + public UInt32 GetDigest() { return CRC.GetDigest(); } + + public override bool CanRead { get { return false; } } + public override bool CanSeek { get { return false; } } + public override bool CanWrite { get { return true; } } + public override Int64 Length { get { return 0; } } + public override Int64 Position { get { return 0; } set { } } + public override void Flush() { } + public override long Seek(long offset, SeekOrigin origin) { return 0; } + public override void SetLength(long value) { } + public override int Read(byte[] buffer, int offset, int count) { return 0; } + + public override void WriteByte(byte b) + { + CRC.UpdateByte(b); + } + public override void Write(byte[] buffer, int offset, int count) + { + CRC.Update(buffer, (uint)offset, (uint)count); + } + }; + + class CProgressInfo : ICodeProgress + { + public Int64 ApprovedStart; + public Int64 InSize; + public System.DateTime Time; + public void Init() { InSize = 0; } + public void SetProgress(Int64 inSize, Int64 outSize) + { + if (inSize >= ApprovedStart && InSize == 0) + { + Time = DateTime.UtcNow; + InSize = inSize; + } + } + } + const int kSubBits = 8; + + static UInt32 GetLogSize(UInt32 size) + { + for (int i = kSubBits; i < 32; i++) + for (UInt32 j = 0; j < (1 << kSubBits); j++) + if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) + return (UInt32)(i << kSubBits) + j; + return (32 << kSubBits); + } + + static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) + { + UInt64 freq = TimeSpan.TicksPerSecond; + UInt64 elTime = elapsedTime; + while (freq > 1000000) + { + freq >>= 1; + elTime >>= 1; + } + if (elTime == 0) + elTime = 1; + return value * freq / elTime; + } + + static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) + { + UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); + UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); + UInt64 numCommands = (UInt64)(size) * numCommandsForOne; + return MyMultDiv64(numCommands, elapsedTime); + } + + static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) + { + UInt64 numCommands = inSize * 220 + outSize * 20; + return MyMultDiv64(numCommands, elapsedTime); + } + + static UInt64 GetTotalRating( + UInt32 dictionarySize, + UInt64 elapsedTimeEn, UInt64 sizeEn, + UInt64 elapsedTimeDe, + UInt64 inSizeDe, UInt64 outSizeDe) + { + return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; + } + + static void PrintValue(UInt64 v) + { + string s = v.ToString(); + for (int i = 0; i + s.Length < 6; i++) + System.Console.Write(" "); + System.Console.Write(s); + } + + static void PrintRating(UInt64 rating) + { + PrintValue(rating / 1000000); + System.Console.Write(" MIPS"); + } + + static void PrintResults( + UInt32 dictionarySize, + UInt64 elapsedTime, + UInt64 size, + bool decompressMode, UInt64 secondSize) + { + UInt64 speed = MyMultDiv64(size, elapsedTime); + PrintValue(speed / 1024); + System.Console.Write(" KB/s "); + UInt64 rating; + if (decompressMode) + rating = GetDecompressRating(elapsedTime, size, secondSize); + else + rating = GetCompressRating(dictionarySize, elapsedTime, size); + PrintRating(rating); + } + + static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) + { + if (numIterations <= 0) + return 0; + if (dictionarySize < (1 << 18)) + { + System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); + return 1; + } + System.Console.Write("\n Compressing Decompressing\n\n"); + + Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); + Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); + + + CoderPropID[] propIDs = + { + CoderPropID.DictionarySize, + }; + object[] properties = + { + (Int32)(dictionarySize), + }; + + UInt32 kBufferSize = dictionarySize + kAdditionalSize; + UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; + + encoder.SetCoderProperties(propIDs, properties); + System.IO.MemoryStream propStream = new System.IO.MemoryStream(); + encoder.WriteCoderProperties(propStream); + byte[] propArray = propStream.ToArray(); + + CBenchRandomGenerator rg = new CBenchRandomGenerator(); + + rg.Set(kBufferSize); + rg.Generate(); + CRC crc = new CRC(); + crc.Init(); + crc.Update(rg.Buffer, 0, rg.BufferSize); + + CProgressInfo progressInfo = new CProgressInfo(); + progressInfo.ApprovedStart = dictionarySize; + + UInt64 totalBenchSize = 0; + UInt64 totalEncodeTime = 0; + UInt64 totalDecodeTime = 0; + UInt64 totalCompressedSize = 0; + + MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); + MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); + CrcOutStream crcOutStream = new CrcOutStream(); + for (Int32 i = 0; i < numIterations; i++) + { + progressInfo.Init(); + inStream.Seek(0, SeekOrigin.Begin); + compressedStream.Seek(0, SeekOrigin.Begin); + encoder.Code(inStream, compressedStream, -1, -1, progressInfo); + TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; + UInt64 encodeTime = (UInt64)sp2.Ticks; + + long compressedSize = compressedStream.Position; + if (progressInfo.InSize == 0) + throw (new Exception("Internal ERROR 1282")); + + UInt64 decodeTime = 0; + for (int j = 0; j < 2; j++) + { + compressedStream.Seek(0, SeekOrigin.Begin); + crcOutStream.Init(); + + decoder.SetDecoderProperties(propArray); + UInt64 outSize = kBufferSize; + System.DateTime startTime = DateTime.UtcNow; + decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); + TimeSpan sp = (DateTime.UtcNow - startTime); + decodeTime = (ulong)sp.Ticks; + if (crcOutStream.GetDigest() != crc.GetDigest()) + throw (new Exception("CRC Error")); + } + UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; + PrintResults(dictionarySize, encodeTime, benchSize, false, 0); + System.Console.Write(" "); + PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); + System.Console.WriteLine(); + + totalBenchSize += benchSize; + totalEncodeTime += encodeTime; + totalDecodeTime += decodeTime; + totalCompressedSize += (ulong)compressedSize; + } + System.Console.WriteLine("---------------------------------------------------"); + PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); + System.Console.Write(" "); + PrintResults(dictionarySize, totalDecodeTime, + kBufferSize * (UInt64)numIterations, true, totalCompressedSize); + System.Console.WriteLine(" Average"); + return 0; + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..a394aee877 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Using directives + +using System.Reflection; +using System.Runtime.CompilerServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("LZMA#")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Igor Pavlov")] +[assembly: AssemblyProduct("LZMA# SDK")] +[assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("4.12.*")] diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs new file mode 100644 index 0000000000..efe4ee9af8 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.40607.42 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace LzmaAlone.Properties +{ + using System; + using System.IO; + using System.Resources; + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the Strongly Typed Resource Builder + // class via a tool like ResGen or Visual Studio.NET. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + class Resources + { + + private static System.Resources.ResourceManager _resMgr; + + private static System.Globalization.CultureInfo _resCulture; + + /*FamANDAssem*/ + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public static System.Resources.ResourceManager ResourceManager + { + get + { + if ((_resMgr == null)) + { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); + _resMgr = temp; + } + return _resMgr; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public static System.Globalization.CultureInfo Culture + { + get + { + return _resCulture; + } + set + { + _resCulture = value; + } + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs new file mode 100644 index 0000000000..1281fd2e09 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.40607.42 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace LzmaAlone.Properties +{ + public partial class Settings : System.Configuration.ApplicationSettingsBase + { + private static Settings m_Value; + + private static object m_SyncObject = new object(); + + public static Settings Value + { + get + { + if ((Settings.m_Value == null)) + { + System.Threading.Monitor.Enter(Settings.m_SyncObject); + if ((Settings.m_Value == null)) + { + try + { + Settings.m_Value = new Settings(); + } + finally + { + System.Threading.Monitor.Exit(Settings.m_SyncObject); + } + } + } + return Settings.m_Value; + } + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoder.cs b/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoder.cs new file mode 100644 index 0000000000..4ced2477e4 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoder.cs @@ -0,0 +1,234 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + class Encoder + { + public const uint kTopValue = (1 << 24); + + System.IO.Stream Stream; + + public UInt64 Low; + public uint Range; + uint _cacheSize; + byte _cache; + + long StartPosition; + + public void SetStream(System.IO.Stream stream) + { + Stream = stream; + } + + public void ReleaseStream() + { + Stream = null; + } + + public void Init() + { + StartPosition = Stream.Position; + + Low = 0; + Range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + } + + public void FlushData() + { + for (int i = 0; i < 5; i++) + ShiftLow(); + } + + public void FlushStream() + { + Stream.Flush(); + } + + public void CloseStream() + { + Stream.Close(); + } + + public void Encode(uint start, uint size, uint total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + public void ShiftLow() + { + if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) + { + byte temp = _cache; + do + { + Stream.WriteByte((byte)(temp + (Low >> 32))); + temp = 0xFF; + } + while (--_cacheSize != 0); + _cache = (byte)(((uint)Low) >> 24); + } + _cacheSize++; + Low = ((uint)Low) << 8; + } + + public void EncodeDirectBits(uint v, int numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((v >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + public void EncodeBit(uint size0, int numTotalBits, uint symbol) + { + uint newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + public long GetProcessedSizeAdd() + { + return _cacheSize + + Stream.Position - StartPosition + 4; + // (long)Stream.GetProcessedSize(); + } + } + + class Decoder + { + public const uint kTopValue = (1 << 24); + public uint Range; + public uint Code; + // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); + public System.IO.Stream Stream; + + public void Init(System.IO.Stream stream) + { + // Stream.Init(stream); + Stream = stream; + + Code = 0; + Range = 0xFFFFFFFF; + for (int i = 0; i < 5; i++) + Code = (Code << 8) | (byte)Stream.ReadByte(); + } + + public void ReleaseStream() + { + // Stream.ReleaseStream(); + Stream = null; + } + + public void CloseStream() + { + Stream.Close(); + } + + public void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + } + + public void Normalize2() + { + if (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + } + + public uint GetThreshold(uint total) + { + return Code / (Range /= total); + } + + public void Decode(uint start, uint size, uint total) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + public uint DecodeDirectBits(int numTotalBits) + { + uint range = Range; + uint code = Code; + uint result = 0; + for (int i = numTotalBits; i > 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + uint t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | (byte)Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + public uint DecodeBit(uint size0, int numTotalBits) + { + uint newBound = (Range >> numTotalBits) * size0; + uint symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs b/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs new file mode 100644 index 0000000000..000a5a0787 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs @@ -0,0 +1,117 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + struct BitEncoder + { + public const int kNumBitModelTotalBits = 11; + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + const int kNumMoveBits = 5; + const int kNumMoveReducingBits = 2; + public const int kNumBitPriceShiftBits = 6; + + uint Prob; + + public void Init() { Prob = kBitModelTotal >> 1; } + + public void UpdateModel(uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + else + Prob -= (Prob) >> kNumMoveBits; + } + + public void Encode(Encoder encoder, uint symbol) + { + // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); + // UpdateModel(symbol); + uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; + if (symbol == 0) + { + encoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + } + else + { + encoder.Low += newBound; + encoder.Range -= newBound; + Prob -= (Prob) >> kNumMoveBits; + } + if (encoder.Range < Encoder.kTopValue) + { + encoder.Range <<= 8; + encoder.ShiftLow(); + } + } + + private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; + + static BitEncoder() + { + const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for (int i = kNumBits - 1; i >= 0; i--) + { + UInt32 start = (UInt32)1 << (kNumBits - i - 1); + UInt32 end = (UInt32)1 << (kNumBits - i); + for (UInt32 j = start; j < end; j++) + ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); + } + } + + public uint GetPrice(uint symbol) + { + return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } + public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } + public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } + } + + struct BitDecoder + { + public const int kNumBitModelTotalBits = 11; + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + const int kNumMoveBits = 5; + + uint Prob; + + public void UpdateModel(int numMoveBits, uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> numMoveBits; + else + Prob -= (Prob) >> numMoveBits; + } + + public void Init() { Prob = kBitModelTotal >> 1; } + + public uint Decode(RangeCoder.Decoder rangeDecoder) + { + uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; + if (rangeDecoder.Code < newBound) + { + rangeDecoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 0; + } + else + { + rangeDecoder.Range -= newBound; + rangeDecoder.Code -= newBound; + Prob -= (Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 1; + } + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs b/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs new file mode 100644 index 0000000000..3309c14a50 --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs @@ -0,0 +1,157 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + struct BitTreeEncoder + { + BitEncoder[] Models; + int NumBitLevels; + + public BitTreeEncoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitEncoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public void Encode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; ) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + } + } + + public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (UInt32 i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + + public UInt32 GetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; ) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + price += Models[m].GetPrice(bit); + m = (m << 1) + bit; + } + return price; + } + + public UInt32 ReverseGetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, + int NumBitLevels, UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[startIndex + m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, + Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) + { + UInt32 m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[startIndex + m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + } + + struct BitTreeDecoder + { + BitDecoder[] Models; + int NumBitLevels; + + public BitTreeDecoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitDecoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public uint Decode(RangeCoder.Decoder rangeDecoder) + { + uint m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) + m = (m << 1) + Models[m].Decode(rangeDecoder); + return m - ((uint)1 << NumBitLevels); + } + + public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + + public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, + RangeCoder.Decoder rangeDecoder, int NumBitLevels) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[startIndex + m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + } +} diff --git a/other-licenses/7zstub/src/CS/7zip/ICoder.cs b/other-licenses/7zstub/src/CS/7zip/ICoder.cs new file mode 100644 index 0000000000..875cb2739e --- /dev/null +++ b/other-licenses/7zstub/src/CS/7zip/ICoder.cs @@ -0,0 +1,157 @@ +// ICoder.h + +using System; + +namespace SevenZip +{ + /// + /// The exception that is thrown when an error in input stream occurs during decoding. + /// + class DataErrorException : ApplicationException + { + public DataErrorException(): base("Data Error") { } + } + + /// + /// The exception that is thrown when the value of an argument is outside the allowable range. + /// + class InvalidParamException : ApplicationException + { + public InvalidParamException(): base("Invalid Parameter") { } + } + + public interface ICodeProgress + { + /// + /// Callback progress. + /// + /// + /// input size. -1 if unknown. + /// + /// + /// output size. -1 if unknown. + /// + void SetProgress(Int64 inSize, Int64 outSize); + }; + + public interface ICoder + { + /// + /// Codes streams. + /// + /// + /// input Stream. + /// + /// + /// output Stream. + /// + /// + /// input Size. -1 if unknown. + /// + /// + /// output Size. -1 if unknown. + /// + /// + /// callback progress reference. + /// + /// + /// if input stream is not valid + /// + void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress); + }; + + /* + public interface ICoder2 + { + void Code(ISequentialInStream []inStreams, + const UInt64 []inSizes, + ISequentialOutStream []outStreams, + UInt64 []outSizes, + ICodeProgress progress); + }; + */ + + /// + /// Provides the fields that represent properties idenitifiers for compressing. + /// + public enum CoderPropID + { + /// + /// Specifies default property. + /// + DefaultProp = 0, + /// + /// Specifies size of dictionary. + /// + DictionarySize, + /// + /// Specifies size of memory for PPM*. + /// + UsedMemorySize, + /// + /// Specifies order for PPM methods. + /// + Order, + /// + /// Specifies Block Size. + /// + BlockSize, + /// + /// Specifies number of postion state bits for LZMA (0 <= x <= 4). + /// + PosStateBits, + /// + /// Specifies number of literal context bits for LZMA (0 <= x <= 8). + /// + LitContextBits, + /// + /// Specifies number of literal position bits for LZMA (0 <= x <= 4). + /// + LitPosBits, + /// + /// Specifies number of fast bytes for LZ*. + /// + NumFastBytes, + /// + /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". + /// + MatchFinder, + /// + /// Specifies the number of match finder cyckes. + /// + MatchFinderCycles, + /// + /// Specifies number of passes. + /// + NumPasses, + /// + /// Specifies number of algorithm. + /// + Algorithm, + /// + /// Specifies the number of threads. + /// + NumThreads, + /// + /// Specifies mode with end marker. + /// + EndMarker + }; + + + public interface ISetCoderProperties + { + void SetCoderProperties(CoderPropID[] propIDs, object[] properties); + }; + + public interface IWriteCoderProperties + { + void WriteCoderProperties(System.IO.Stream outStream); + } + + public interface ISetDecoderProperties + { + void SetDecoderProperties(byte[] properties); + } +} diff --git a/other-licenses/7zstub/src/DOC/7zC.txt b/other-licenses/7zstub/src/DOC/7zC.txt new file mode 100644 index 0000000000..49276787f8 --- /dev/null +++ b/other-licenses/7zstub/src/DOC/7zC.txt @@ -0,0 +1,187 @@ +7z ANSI-C Decoder 9.35 +---------------------- + +7z ANSI-C provides 7z/LZMA decoding. +7z ANSI-C version is simplified version ported from C++ code. + +LZMA is default and general compression method of 7z format +in 7-Zip compression program (www.7-zip.org). LZMA provides high +compression ratio and very fast decompression. + + +LICENSE +------- + +7z ANSI-C Decoder is part of the LZMA SDK. +LZMA SDK is written and placed in the public domain by Igor Pavlov. + +Files +--------------------- + +7zDecode.* - Low level 7z decoding +7zExtract.* - High level 7z decoding +7zHeader.* - .7z format constants +7zIn.* - .7z archive opening +7zItem.* - .7z structures +7zMain.c - Test application + + +How To Use +---------- + +You can create .7z archive with 7z.exe, 7za.exe or 7zr.exe: + + 7z.exe a archive.7z *.htm -r -mx -m0fb=255 + +If you have big number of files in archive, and you need fast extracting, +you can use partly-solid archives: + + 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K + +In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only +512KB for extracting one file from such archive. + + +Limitations of current version of 7z ANSI-C Decoder +--------------------------------------------------- + + - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. + - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. + - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. + +These limitations will be fixed in future versions. + + +Using 7z ANSI-C Decoder Test application: +----------------------------------------- + +Usage: 7zDec + +: + e: Extract files from archive + l: List contents of archive + t: Test integrity of archive + +Example: + + 7zDec l archive.7z + +lists contents of archive.7z + + 7zDec e archive.7z + +extracts files from archive.7z to current folder. + + +How to use .7z Decoder +---------------------- + +Memory allocation +~~~~~~~~~~~~~~~~~ + +7z Decoder uses two memory pools: +1) Temporary pool +2) Main pool +Such scheme can allow you to avoid fragmentation of allocated blocks. + + +Steps for using 7z decoder +-------------------------- + +Use code at 7zMain.c as example. + +1) Declare variables: + inStream /* implements ILookInStream interface */ + CSzArEx db; /* 7z archive database structure */ + ISzAlloc allocImp; /* memory functions for main pool */ + ISzAlloc allocTempImp; /* memory functions for temporary pool */ + +2) call CrcGenerateTable(); function to initialize CRC structures. + +3) call SzArEx_Init(&db); function to initialize db structures. + +4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive + +This function opens archive "inStream" and reads headers to "db". +All items in "db" will be allocated with "allocMain" functions. +SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. + +5) List items or Extract items + + Listing code: + ~~~~~~~~~~~~~ + + Use SzArEx_GetFileNameUtf16 function. Look example code in C\Util\7z\7zMain.c file. + + + Extracting code: + ~~~~~~~~~~~~~~~~ + + SZ_RESULT SzAr_Extract( + CArchiveDatabaseEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + + If you need to decompress more than one file, you can send these values from previous call: + blockIndex, + outBuffer, + outBufferSize, + You can consider "outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + After decompressing you must free "outBuffer": + allocImp.Free(outBuffer); + +6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". + + + + +Memory requirements for .7z decoding +------------------------------------ + +Memory usage for Archive opening: + - Temporary pool: + - Memory for uncompressed .7z headers + - some other temporary blocks + - Main pool: + - Memory for database: + Estimated size of one file structures in solid archive: + - Size (4 or 8 Bytes) + - CRC32 (4 bytes) + - LastWriteTime (8 bytes) + - Some file information (4 bytes) + - File Name (variable length) + pointer + allocation structures + +Memory usage for archive Decompressing: + - Temporary pool: + - Memory for LZMA decompressing structures + - Main pool: + - Memory for decompressed solid block + - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these + temprorary buffers can be about 15% of solid block size. + + +7z Decoder doesn't allocate memory for compressed blocks. +Instead of this, you must allocate buffer with desired +size before calling 7z Decoder. Use 7zMain.c as example. + + +Defines +------- + +_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. + + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/other-licenses/7zstub/src/DOC/7zFormat.txt b/other-licenses/7zstub/src/DOC/7zFormat.txt new file mode 100644 index 0000000000..6b8678fbb4 --- /dev/null +++ b/other-licenses/7zstub/src/DOC/7zFormat.txt @@ -0,0 +1,469 @@ +7z Format description (4.59) +---------------------------- + +This file contains description of 7z archive format. +7z archive can contain files compressed with any method. +See "Methods.txt" for description for defined compressing methods. + + +Format structure Overview +------------------------- + +Some fields can be optional. + +Archive structure +~~~~~~~~~~~~~~~~~ +SignatureHeader +[PackedStreams] +[PackedStreamsForHeaders] +[ + Header + or + { + Packed Header + HeaderInfo + } +] + + + +Header structure +~~~~~~~~~~~~~~~~ +{ + ArchiveProperties + AdditionalStreams + { + PackInfo + { + PackPos + NumPackStreams + Sizes[NumPackStreams] + CRCs[NumPackStreams] + } + CodersInfo + { + NumFolders + Folders[NumFolders] + { + NumCoders + CodersInfo[NumCoders] + { + ID + NumInStreams; + NumOutStreams; + PropertiesSize + Properties[PropertiesSize] + } + NumBindPairs + BindPairsInfo[NumBindPairs] + { + InIndex; + OutIndex; + } + PackedIndices + } + UnPackSize[Folders][Folders.NumOutstreams] + CRCs[NumFolders] + } + SubStreamsInfo + { + NumUnPackStreamsInFolders[NumFolders]; + UnPackSizes[] + CRCs[] + } + } + MainStreamsInfo + { + (Same as in AdditionalStreams) + } + FilesInfo + { + NumFiles + Properties[] + { + ID + Size + Data + } + } +} + +HeaderInfo structure +~~~~~~~~~~~~~~~~~~~~ +{ + (Same as in AdditionalStreams) +} + + + +Notes about Notation and encoding +--------------------------------- + +7z uses little endian encoding. + +7z archive format has optional headers that are marked as +[] +Header +[] + +REAL_UINT64 means real UINT64. + +UINT64 means real UINT64 encoded with the following scheme: + + Size of encoding sequence depends from first byte: + First_Byte Extra_Bytes Value + (binary) + 0xxxxxxx : ( xxxxxxx ) + 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y + 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y + ... + 1111110x BYTE y[6] : ( x << (8 * 6)) + y + 11111110 BYTE y[7] : y + 11111111 BYTE y[8] : y + + + +Property IDs +------------ + +0x00 = kEnd + +0x01 = kHeader + +0x02 = kArchiveProperties + +0x03 = kAdditionalStreamsInfo +0x04 = kMainStreamsInfo +0x05 = kFilesInfo + +0x06 = kPackInfo +0x07 = kUnPackInfo +0x08 = kSubStreamsInfo + +0x09 = kSize +0x0A = kCRC + +0x0B = kFolder + +0x0C = kCodersUnPackSize +0x0D = kNumUnPackStream + +0x0E = kEmptyStream +0x0F = kEmptyFile +0x10 = kAnti + +0x11 = kName +0x12 = kCTime +0x13 = kATime +0x14 = kMTime +0x15 = kWinAttributes +0x16 = kComment + +0x17 = kEncodedHeader + +0x18 = kStartPos +0x19 = kDummy + + +7z format headers +----------------- + +SignatureHeader +~~~~~~~~~~~~~~~ + BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + + ArchiveVersion + { + BYTE Major; // now = 0 + BYTE Minor; // now = 2 + }; + + UINT32 StartHeaderCRC; + + StartHeader + { + REAL_UINT64 NextHeaderOffset + REAL_UINT64 NextHeaderSize + UINT32 NextHeaderCRC + } + + +........................... + + +ArchiveProperties +~~~~~~~~~~~~~~~~~ +BYTE NID::kArchiveProperties (0x02) +for (;;) +{ + BYTE PropertyType; + if (aType == 0) + break; + UINT64 PropertySize; + BYTE PropertyData[PropertySize]; +} + + +Digests (NumStreams) +~~~~~~~~~~~~~~~~~~~~~ + BYTE AllAreDefined + if (AllAreDefined == 0) + { + for(NumStreams) + BIT Defined + } + UINT32 CRCs[NumDefined] + + +PackInfo +~~~~~~~~~~~~ + BYTE NID::kPackInfo (0x06) + UINT64 PackPos + UINT64 NumPackStreams + + [] + BYTE NID::kSize (0x09) + UINT64 PackSizes[NumPackStreams] + [] + + [] + BYTE NID::kCRC (0x0A) + PackStreamDigests[NumPackStreams] + [] + + BYTE NID::kEnd + + +Folder +~~~~~~ + UINT64 NumCoders; + for (NumCoders) + { + BYTE + { + 0:3 CodecIdSize + 4: Is Complex Coder + 5: There Are Attributes + 6: Reserved + 7: There are more alternative methods. (Not used anymore, must be 0). + } + BYTE CodecId[CodecIdSize] + if (Is Complex Coder) + { + UINT64 NumInStreams; + UINT64 NumOutStreams; + } + if (There Are Attributes) + { + UINT64 PropertiesSize + BYTE Properties[PropertiesSize] + } + } + + NumBindPairs = NumOutStreamsTotal - 1; + + for (NumBindPairs) + { + UINT64 InIndex; + UINT64 OutIndex; + } + + NumPackedStreams = NumInStreamsTotal - NumBindPairs; + if (NumPackedStreams > 1) + for(NumPackedStreams) + { + UINT64 Index; + }; + + + + +Coders Info +~~~~~~~~~~~ + + BYTE NID::kUnPackInfo (0x07) + + + BYTE NID::kFolder (0x0B) + UINT64 NumFolders + BYTE External + switch(External) + { + case 0: + Folders[NumFolders] + case 1: + UINT64 DataStreamIndex + } + + + BYTE ID::kCodersUnPackSize (0x0C) + for(Folders) + for(Folder.NumOutStreams) + UINT64 UnPackSize; + + + [] + BYTE NID::kCRC (0x0A) + UnPackDigests[NumFolders] + [] + + + + BYTE NID::kEnd + + + +SubStreams Info +~~~~~~~~~~~~~~ + BYTE NID::kSubStreamsInfo; (0x08) + + [] + BYTE NID::kNumUnPackStream; (0x0D) + UINT64 NumUnPackStreamsInFolders[NumFolders]; + [] + + + [] + BYTE NID::kSize (0x09) + UINT64 UnPackSizes[] + [] + + + [] + BYTE NID::kCRC (0x0A) + Digests[Number of streams with unknown CRC] + [] + + + BYTE NID::kEnd + + +Streams Info +~~~~~~~~~~~~ + + [] + PackInfo + [] + + + [] + CodersInfo + [] + + + [] + SubStreamsInfo + [] + + BYTE NID::kEnd + + +FilesInfo +~~~~~~~~~ + BYTE NID::kFilesInfo; (0x05) + UINT64 NumFiles + + for (;;) + { + BYTE PropertyType; + if (aType == 0) + break; + + UINT64 Size; + + switch(PropertyType) + { + kEmptyStream: (0x0E) + for(NumFiles) + BIT IsEmptyStream + + kEmptyFile: (0x0F) + for(EmptyStreams) + BIT IsEmptyFile + + kAnti: (0x10) + for(EmptyStreams) + BIT IsAntiFile + + case kCTime: (0x12) + case kATime: (0x13) + case kMTime: (0x14) + BYTE AllAreDefined + if (AllAreDefined == 0) + { + for(NumFiles) + BIT TimeDefined + } + BYTE External; + if(External != 0) + UINT64 DataIndex + [] + for(Definded Items) + UINT64 Time + [] + + kNames: (0x11) + BYTE External; + if(External != 0) + UINT64 DataIndex + [] + for(Files) + { + wchar_t Names[NameSize]; + wchar_t 0; + } + [] + + kAttributes: (0x15) + BYTE AllAreDefined + if (AllAreDefined == 0) + { + for(NumFiles) + BIT AttributesAreDefined + } + BYTE External; + if(External != 0) + UINT64 DataIndex + [] + for(Definded Attributes) + UINT32 Attributes + [] + } + } + + +Header +~~~~~~ + BYTE NID::kHeader (0x01) + + [] + ArchiveProperties + [] + + [] + BYTE NID::kAdditionalStreamsInfo; (0x03) + StreamsInfo + [] + + [] + BYTE NID::kMainStreamsInfo; (0x04) + StreamsInfo + [] + + [] + FilesInfo + [] + + BYTE NID::kEnd + + +HeaderInfo +~~~~~~~~~~ + [] + BYTE NID::kEncodedHeader; (0x17) + StreamsInfo for Encoded Header + [] + + +--- +End of document diff --git a/other-licenses/7zstub/src/DOC/Methods.txt b/other-licenses/7zstub/src/DOC/Methods.txt new file mode 100644 index 0000000000..11adcb0ba3 --- /dev/null +++ b/other-licenses/7zstub/src/DOC/Methods.txt @@ -0,0 +1,167 @@ +7-Zip method IDs for 7z and xz archives +--------------------------------------- + +Version: 17.01 +Date: 2017-05-27 + +Each compression or crypto method in 7z is associated with unique binary value (ID). +The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). + +xz and 7z formats use same ID map. + +If you want to add some new ID, you have two ways: + 1) Write request for allocating IDs to 7-Zip developers. + 2) Generate 8-bytes ID: + + 3F ZZ ZZ ZZ ZZ ZZ MM MM + + 3F - Prefix for random IDs (1 byte) + ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. + + MM MM - Method ID (2 bytes) + + You can notify 7-Zip developers about your Developer ID / Method ID. + + Note: Use new ID, if old codec can not decode data encoded with new version. + + +List of defined IDs +------------------- + +00 - Copy + +03 - Delta +04 - BCJ (x86) +05 - PPC (big-endian) +06 - IA64 +07 - ARM (little-endian) +08 - ARMT (little-endian) +09 - SPARC + +21 - LZMA2 + +02.. - Common + 03 [Swap] + - 2 Swap2 + - 4 Swap4 + +03.. - 7z + 01 - + 01 - LZMA + + 03 - [Branch Codecs] + 01 - [x86 Codecs] + 03 - BCJ + 1B - BCJ2 (4 packed streams) + 02 - + 05 - PPC (big-endian) + 03 - + 01 - Alpha + 04 - + 01 - IA64 + 05 - + 01 - ARM (little-endian) + 06 - + 05 - M68 (big-endian) + 07 - + 01 - ARMT (little-endian) + 08 - + 05 - SPARC + + 04 - + 01 - PPMD + + 7F - + 01 - experimental method. + + +04.. - Misc codecs + + 00 - Reserved + + 01 - [Zip] + 00 - Copy (not used. Use {00} instead) + 01 - Shrink + 06 - Implode + 08 - Deflate + 09 - Deflate64 + 0A - Imploding + 0C - BZip2 (not used. Use {040202} instead) + 0E - LZMA (LZMA-zip) + 5F - xz + 60 - Jpeg + 61 - WavPack + 62 - PPMd (PPMd-zip) + 63 - wzAES + + 02 - + 02 - BZip2 + + 03 - [Rar] + 01 - Rar1 + 02 - Rar2 + 03 - Rar3 + 05 - Rar5 + + 04 - [Arj] + 01 - Arj(1,2,3) + 02 - Arj4 + + 05 - [Z] + + 06 - [Lzh] + + 07 - Reserved for 7z + + 08 - [Cab] + + 09 - [NSIS] + 01 - DeflateNSIS + 02 - BZip2NSIS + + F7 - External codecs (that are not included to 7-Zip) + + 0x xx - reserved + + 10 xx - reserved (LZHAM) + 01 - LZHAM + + 11 xx - reserved (Tino Reichardt) + 01 - ZSTD + 02 - BROTLI + 04 - LZ4 + 05 - LZ5 + 06 - LIZARD + + +06.. - Crypto + + F0 - Ciphers without hashing algo + + 01 - [AES] + 0x - AES-128 + 4x - AES-192 + 8x - AES-256 + Cx - AES + + x0 - ECB + x1 - CBC + x2 - CFB + x3 - OFB + x4 - CTR + + F1 - Combine Ciphers + + 01 - [Zip] + 01 - ZipCrypto (Main Zip crypto algo) + + 03 - [RAR] + 02 - + 03 - Rar29AES (AES-128 + modified SHA-1) + + 07 - [7z] + 01 - 7zAES (AES-256 + SHA-256) + + +--- +End of document diff --git a/other-licenses/7zstub/src/DOC/installer.txt b/other-licenses/7zstub/src/DOC/installer.txt new file mode 100644 index 0000000000..70ad7dc6a6 --- /dev/null +++ b/other-licenses/7zstub/src/DOC/installer.txt @@ -0,0 +1,166 @@ +7-Zip for installers 9.38 +------------------------- + +7-Zip is a file archiver for Windows NT/2000/2003/2008/XP/Vista/7/8/10. + +7-Zip for installers is part of LZMA SDK. +LZMA SDK is written and placed in the public domain by Igor Pavlov. + +It's allowed to join 7-Zip SFX module with another software. +It's allowed to change resources of 7-Zip's SFX modules. + + +HOW to use +----------- + +7zr.exe is reduced version of 7za.exe of 7-Zip. +7zr.exe supports only format with these codecs: LZMA, LZMA2, BCJ, BCJ2, ARM, Copy. + +Example of compressing command for installation packages: + +7zr a archive.7z files + +7zSD.sfx is SFX module for installers. 7zSD.sfx uses msvcrt.dll. + +SFX modules for installers allow to create installation program. +Such module extracts archive to temp folder and then runs specified program and removes +temp files after program finishing. Self-extract archive for installers must be created +as joining 3 files: SFX_Module, Installer_Config, 7z_Archive. +Installer_Config is optional file. You can use the following command to create installer +self-extract archive: + +copy /b 7zSD.sfx + config.txt + archive.7z archive.exe + +The smallest installation package size can be achieved, if installation files was +uncompressed before including to 7z archive. + +-y switch for installer module (at runtime) specifies quiet mode for extracting. + +Installer Config file format +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Config file contains commands for Installer. File begins from string +;!@Install@!UTF-8! and ends with ;!@InstallEnd@!. File must be written +in UTF-8 encoding. File contains string pairs: + +ID_String="Value" + +ID_String Description + +Title Title for messages +BeginPrompt Begin Prompt message +Progress Value can be "yes" or "no". Default value is "yes". +RunProgram Command for executing. Default value is "setup.exe". + Substring %%T will be replaced with path to temporary + folder, where files were extracted +Directory Directory prefix for "RunProgram". Default value is ".\\" +ExecuteFile Name of file for executing +ExecuteParameters Parameters for "ExecuteFile" + + +You can omit any string pair. + +There are two ways to run program: RunProgram and ExecuteFile. +Use RunProgram, if you want to run some program from .7z archive. +Use ExecuteFile, if you want to open some document from .7z archive or +if you want to execute some command from Windows. + +If you use RunProgram and if you specify empty directory prefix: Directory="", +the system searches for the executable file in the following sequence: + +1. The directory from which the application (installer) loaded. +2. The temporary folder, where files were extracted. +3. The Windows system directory. + + +Config file Examples +~~~~~~~~~~~~~~~~~~~~ + +;!@Install@!UTF-8! +Title="7-Zip 4.00" +BeginPrompt="Do you want to install the 7-Zip 4.00?" +RunProgram="setup.exe" +;!@InstallEnd@! + + + +;!@Install@!UTF-8! +Title="7-Zip 4.00" +BeginPrompt="Do you want to install the 7-Zip 4.00?" +ExecuteFile="7zip.msi" +;!@InstallEnd@! + + + +;!@Install@!UTF-8! +Title="7-Zip 4.01 Update" +BeginPrompt="Do you want to install the 7-Zip 4.01 Update?" +ExecuteFile="msiexec.exe" +ExecuteParameters="/i 7zip.msi REINSTALL=ALL REINSTALLMODE=vomus" +;!@InstallEnd@! + + + +Small SFX modules for installers +-------------------------------- + +7zS2.sfx - small SFX module (GUI version) +7zS2con.sfx - small SFX module (Console version) + +Small SFX modules support this codecs: LZMA, LZMA2, BCJ, BCJ2, ARM, COPY + +Small SFX module is similar to common SFX module for installers. +The difference (what's new in small version): + - Smaller size (30 KB vs 100 KB) + - C source code instead of Ñ++ + - No installer Configuration file + - No extracting progress window + - It decompresses solid 7z blocks (it can be whole 7z archive) to RAM. + So user that calls SFX installer must have free RAM of size of largest + solid 7z block (size of 7z archive at simplest case). + +How to use +---------- + +copy /b 7zS2.sfx + archive.7z sfx.exe + +When you run installer sfx module (sfx.exe) +1) It creates "7zNNNNNNNN" temp folder in system temp folder. +2) It extracts .7z archive to that folder +3) It executes one file from "7zNNNNNNNN" temp folder. +4) It removes "7zNNNNNNNN" temp folder + +You can send parameters to installer, and installer will transfer them to extracted .exe file. + +Small SFX uses 3 levels of priorities to select file to execute: + + 1) Files in root folder have higher priority than files in subfolders. + 2) File extension priorities (from high to low priority order): + bat, cmd, exe, inf, msi, cab (under Windows CE), html, htm + 3) File name priorities (from high to low priority order): + setup, install, run, start + +Windows CE (ARM) version of 7zS2.sfx is included to 7-Zip for Windows Mobile package. + + +Examples +-------- + +1) To create compressed console 7-Zip: + +7zr a c.7z 7z.exe 7z.dll -mx +copy /b 7zS2con.sfx + c.7z 7zCompr.exe +7zCompr.exe b -md22 + + +2) To create compressed GUI 7-Zip: + +7zr a g.7z 7zg.exe 7z.dll -mx +copy /b 7zS2.sfx + g.7z 7zgCompr.exe +7zgCompr.exe b -md22 + + +3) To open some file: + +7zr a h.7z readme.txt -mx +copy /b 7zS2.sfx + h.7z 7zTxt.exe +7zTxt.exe diff --git a/other-licenses/7zstub/src/DOC/lzma-history.txt b/other-licenses/7zstub/src/DOC/lzma-history.txt new file mode 100644 index 0000000000..c53e3bd702 --- /dev/null +++ b/other-licenses/7zstub/src/DOC/lzma-history.txt @@ -0,0 +1,424 @@ +HISTORY of the LZMA SDK +----------------------- + +18.05 2018-04-30 +------------------------- +- The speed for LZMA/LZMA2 compressing was increased + by 8% for fastest/fast compression levels and + by 3% for normal/maximum compression levels. +- Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in + Windows 10 because of some BUG with "Large Pages" in Windows 10. + Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299). +- The BUG was fixed in Lzma2Enc.c + Lzma2Enc_Encode2() function worked incorretly, + if (inStream == NULL) and the number of block threads is more than 1. + + +18.03 beta 2018-03-04 +------------------------- +- Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm + for x64 with about 30% higher speed than main version of LZMA decoder written in C. +- The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%. +- 7-Zip now can use multi-threading for 7z/LZMA2 decoding, + if there are multiple independent data chunks in LZMA2 stream. +- 7-Zip now can use multi-threading for xz decoding, + if there are multiple blocks in xz stream. + + +18.01 2019-01-28 +------------------------- +- The BUG in 17.01 - 18.00 beta was fixed: + XzDec.c : random block unpacking and XzUnpacker_IsBlockFinished() + didn't work correctly for xz archives without checksum (CRC). + + +18.00 beta 2019-01-10 +------------------------- +- The BUG in xz encoder was fixed: + There was memory leak of 16 KB for each file compressed with + xz compression method, if additional filter was used. + + +17.01 beta 2017-08-28 +------------------------- +- Minor speed optimization for LZMA2 (xz and 7z) multi-threading compression. + 7-Zip now uses additional memory buffers for multi-block LZMA2 compression. + CPU utilization was slightly improved. +- 7-zip now creates multi-block xz archives by default. Block size can be + specified with -ms[Size]{m|g} switch. +- xz decoder now can unpack random block from multi-block xz archives. +- 7-Zip command line: @listfile now doesn't work after -- switch. + Use -i@listfile before -- switch instead. +- The BUGs were fixed: + 7-Zip 17.00 beta crashed for commands that write anti-item to 7z archive. + + +17.00 beta 2017-04-29 +------------------------- +- NewHandler.h / NewHandler.cpp: + now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900). +- C/7zTypes.h : the names of variables in interface structures were changed (vt). +- Some bugs were fixed. 7-Zip could crash in some cases. +- Some internal changes in code. + + +16.04 2016-10-04 +------------------------- +- The bug was fixed in DllSecur.c. + + +16.03 2016-09-28 +------------------------- +- SFX modules now use some protection against DLL preloading attack. +- Some bugs in 7z code were fixed. + + +16.02 2016-05-21 +------------------------- +- The BUG in 16.00 - 16.01 was fixed: + Split Handler (SplitHandler.cpp) returned incorrect + total size value (kpidSize) for split archives. + + +16.01 2016-05-19 +------------------------- +- Some internal changes to reduce the number of compiler warnings. + + +16.00 2016-05-10 +------------------------- +- Some bugs were fixed. + + +15.12 2015-11-19 +------------------------- +- The BUG in C version of 7z decoder was fixed: + 7zDec.c : SzDecodeLzma2() + 7z decoder could mistakenly report about decoding error for some 7z archives + that use LZMA2 compression method. + The probability to get that mistaken decoding error report was about + one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). +- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed: + 7zArcIn.c : SzReadHeader2() + 7z decoder worked incorrectly for 7z archives that contain + empty solid blocks, that can be placed to 7z archive, if some file is + unavailable for reading during archive creation. + + +15.09 beta 2015-10-16 +------------------------- +- The BUG in LZMA / LZMA2 encoding code was fixed. + The BUG in LzFind.c::MatchFinder_ReadBlock() function. + If input data size is larger than (4 GiB - dictionary_size), + the following code worked incorrectly: + - LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions + for compressing from memory to memory. + That BUG is not related to LZMA encoder version that works via streams. + - LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if + default value of chunk size (CLzma2EncProps::blockSize) is changed + to value larger than (4 GiB - dictionary_size). + + +9.38 beta 2015-01-03 +------------------------- +- The BUG in 9.31-9.37 was fixed: + IArchiveGetRawProps interface was disabled for 7z archives. +- The BUG in 9.26-9.36 was fixed: + Some code in CPP\7zip\Archive\7z\ worked correctly only under Windows. + + +9.36 beta 2014-12-26 +------------------------- +- The BUG in command line version was fixed: + 7-Zip created temporary archive in current folder during update archive + operation, if -w{Path} switch was not specified. + The fixed 7-Zip creates temporary archive in folder that contains updated archive. +- The BUG in 9.33-9.35 was fixed: + 7-Zip silently ignored file reading errors during 7z or gz archive creation, + and the created archive contained only part of file that was read before error. + The fixed 7-Zip stops archive creation and it reports about error. + + +9.35 beta 2014-12-07 +------------------------- +- 7zr.exe now support AES encryption. +- SFX mudules were added to LZMA SDK +- Some bugs were fixed. + + +9.21 beta 2011-04-11 +------------------------- +- New class FString for file names at file systems. +- Speed optimization in CRC code for big-endian CPUs. +- The BUG in Lzma2Dec.c was fixed: + Lzma2Decode function didn't work. + + +9.18 beta 2010-11-02 +------------------------- +- New small SFX module for installers (SfxSetup). + + +9.12 beta 2010-03-24 +------------------------- +- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work, + if more than 10 threads were used (or more than 20 threads in some modes). + + +9.11 beta 2010-03-15 +------------------------- +- PPMd compression method support + + +9.09 2009-12-12 +------------------------- +- The bug was fixed: + Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c + incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8. +- Some bugs were fixed + + +9.06 2009-08-17 +------------------------- +- Some changes in ANSI-C 7z Decoder interfaces. + + +9.04 2009-05-30 +------------------------- +- LZMA2 compression method support +- xz format support + + +4.65 2009-02-03 +------------------------- +- Some minor fixes + + +4.63 2008-12-31 +------------------------- +- Some minor fixes + + +4.61 beta 2008-11-23 +------------------------- +- The bug in ANSI-C LZMA Decoder was fixed: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. +- Some changes in ANSI-C 7z Decoder interfaces. +- LZMA SDK is placed in the public domain. + + +4.60 beta 2008-08-19 +------------------------- +- Some minor fixes. + + +4.59 beta 2008-08-13 +------------------------- +- The bug was fixed: + LZMA Encoder in fast compression mode could access memory outside of + allocated range in some rare cases. + + +4.58 beta 2008-05-05 +------------------------- +- ANSI-C LZMA Decoder was rewritten for speed optimizations. +- ANSI-C LZMA Encoder was included to LZMA SDK. +- C++ LZMA code now is just wrapper over ANSI-C code. + + +4.57 2007-12-12 +------------------------- +- Speed optimizations in Ñ++ LZMA Decoder. +- Small changes for more compatibility with some C/C++ compilers. + + +4.49 beta 2007-07-05 +------------------------- +- .7z ANSI-C Decoder: + - now it supports BCJ and BCJ2 filters + - now it supports files larger than 4 GB. + - now it supports "Last Write Time" field for files. +- C++ code for .7z archives compressing/decompressing from 7-zip + was included to LZMA SDK. + + +4.43 2006-06-04 +------------------------- +- Small changes for more compatibility with some C/C++ compilers. + + +4.42 2006-05-15 +------------------------- +- Small changes in .h files in ANSI-C version. + + +4.39 beta 2006-04-14 +------------------------- +- The bug in versions 4.33b:4.38b was fixed: + C++ version of LZMA encoder could not correctly compress + files larger than 2 GB with HC4 match finder (-mfhc4). + + +4.37 beta 2005-04-06 +------------------------- +- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. + + +4.35 beta 2005-03-02 +------------------------- +- The bug was fixed in C++ version of LZMA Decoder: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. + + +4.34 beta 2006-02-27 +------------------------- +- Compressing speed and memory requirements for compressing were increased +- LZMA now can use only these match finders: HC4, BT2, BT3, BT4 + + +4.32 2005-12-09 +------------------------- +- Java version of LZMA SDK was included + + +4.30 2005-11-20 +------------------------- +- Compression ratio was improved in -a2 mode +- Speed optimizations for compressing in -a2 mode +- -fb switch now supports values up to 273 +- The bug in 7z_C (7zIn.c) was fixed: + It used Alloc/Free functions from different memory pools. + So if program used two memory pools, it worked incorrectly. +- 7z_C: .7z format supporting was improved +- LZMA# SDK (C#.NET version) was included + + +4.27 (Updated) 2005-09-21 +------------------------- +- Some GUIDs/interfaces in C++ were changed. + IStream.h: + ISequentialInStream::Read now works as old ReadPart + ISequentialOutStream::Write now works as old WritePart + + +4.27 2005-08-07 +------------------------- +- The bug in LzmaDecodeSize.c was fixed: + if _LZMA_IN_CB and _LZMA_OUT_READ were defined, + decompressing worked incorrectly. + + +4.26 2005-08-05 +------------------------- +- Fixes in 7z_C code and LzmaTest.c: + previous versions could work incorrectly, + if malloc(0) returns 0 + + +4.23 2005-06-29 +------------------------- +- Small fixes in C++ code + + +4.22 2005-06-10 +------------------------- +- Small fixes + + +4.21 2005-06-08 +------------------------- +- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed +- New additional version of ANSI-C LZMA Decoder with zlib-like interface: + - LzmaStateDecode.h + - LzmaStateDecode.c + - LzmaStateTest.c +- ANSI-C LZMA Decoder now can decompress files larger than 4 GB + + +4.17 2005-04-18 +------------------------- +- New example for RAM->RAM compressing/decompressing: + LZMA + BCJ (filter for x86 code): + - LzmaRam.h + - LzmaRam.cpp + - LzmaRamDecode.h + - LzmaRamDecode.c + - -f86 switch for lzma.exe + + +4.16 2005-03-29 +------------------------- +- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): + If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, + decoder could access memory outside of allocated range. +- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). + Old version of LZMA Decoder now is in file LzmaDecodeSize.c. + LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c +- Small speed optimization in LZMA C++ code +- filter for SPARC's code was added +- Simplified version of .7z ANSI-C Decoder was included + + +4.06 2004-09-05 +------------------------- +- The bug in v4.05 was fixed: + LZMA-Encoder didn't release output stream in some cases. + + +4.05 2004-08-25 +------------------------- +- Source code of filters for x86, IA-64, ARM, ARM-Thumb + and PowerPC code was included to SDK +- Some internal minor changes + + +4.04 2004-07-28 +------------------------- +- More compatibility with some C++ compilers + + +4.03 2004-06-18 +------------------------- +- "Benchmark" command was added. It measures compressing + and decompressing speed and shows rating values. + Also it checks hardware errors. + + +4.02 2004-06-10 +------------------------- +- C++ LZMA Encoder/Decoder code now is more portable + and it can be compiled by GCC on Linux. + + +4.01 2004-02-15 +------------------------- +- Some detection of data corruption was enabled. + LzmaDecode.c / RangeDecoderReadByte + ..... + { + rd->ExtraBytes = 1; + return 0xFF; + } + + +4.00 2004-02-13 +------------------------- +- Original version of LZMA SDK + + + +HISTORY of the LZMA +------------------- + 2001-2008: Improvements to LZMA compressing/decompressing code, + keeping compatibility with original LZMA format + 1996-2001: Development of LZMA compression format + + Some milestones: + + 2001-08-30: LZMA compression was added to 7-Zip + 1999-01-02: First version of 7-Zip was released + + +End of document diff --git a/other-licenses/7zstub/src/DOC/lzma-sdk.txt b/other-licenses/7zstub/src/DOC/lzma-sdk.txt new file mode 100644 index 0000000000..01521e9398 --- /dev/null +++ b/other-licenses/7zstub/src/DOC/lzma-sdk.txt @@ -0,0 +1,357 @@ +LZMA SDK 18.05 +-------------- + +LZMA SDK provides the documentation, samples, header files, +libraries, and tools you need to develop applications that +use 7z / LZMA / LZMA2 / XZ compression. + +LZMA is an improved version of famous LZ77 compression algorithm. +It was improved in way of maximum increasing of compression ratio, +keeping high decompression speed and low memory requirements for +decompressing. + +LZMA2 is a LZMA based compression method. LZMA2 provides better +multithreading support for compression than LZMA and some other improvements. + +7z is a file format for data compression and file archiving. +7z is a main file format for 7-Zip compression program (www.7-zip.org). +7z format supports different compression methods: LZMA, LZMA2 and others. +7z also supports AES-256 based encryption. + +XZ is a file format for data compression that uses LZMA2 compression. +XZ format provides additional features: SHA/CRC check, filters for +improved compression ratio, splitting to blocks and streams, + + + +LICENSE +------- + +LZMA SDK is written and placed in the public domain by Igor Pavlov. + +Some code in LZMA SDK is based on public domain code from another developers: + 1) PPMd var.H (2001): Dmitry Shkarin + 2) SHA-256: Wei Dai (Crypto++ library) + +Anyone is free to copy, modify, publish, use, compile, sell, or distribute the +original LZMA SDK code, either in source code form or as a compiled binary, for +any purpose, commercial or non-commercial, and by any means. + +LZMA SDK code is compatible with open source licenses, for example, you can +include it to GNU GPL or GNU LGPL code. + + +LZMA SDK Contents +----------------- + + Source code: + + - C / C++ / C# / Java - LZMA compression and decompression + - C / C++ - LZMA2 compression and decompression + - C / C++ - XZ compression and decompression + - C - 7z decompression + - C++ - 7z compression and decompression + - C - small SFXs for installers (7z decompression) + - C++ - SFXs and SFXs for installers (7z decompression) + + Precomiled binaries: + + - console programs for lzma / 7z / xz compression and decompression + - SFX modules for installers. + + +UNIX/Linux version +------------------ +To compile C++ version of file->file LZMA encoding, go to directory +CPP/7zip/Bundles/LzmaCon +and call make to recompile it: + make -f makefile.gcc clean all + +In some UNIX/Linux versions you must compile LZMA with static libraries. +To compile with static libraries, you can use +LIB = -lm -static + +Also you can use p7zip (port of 7-Zip for POSIX systems like Unix or Linux): + + http://p7zip.sourceforge.net/ + + +Files +----- + +DOC/7zC.txt - 7z ANSI-C Decoder description +DOC/7zFormat.txt - 7z Format description +DOC/installer.txt - information about 7-Zip for installers +DOC/lzma.txt - LZMA compression description +DOC/lzma-sdk.txt - LZMA SDK description (this file) +DOC/lzma-history.txt - history of LZMA SDK +DOC/lzma-specification.txt - Specification of LZMA +DOC/Methods.txt - Compression method IDs for .7z + +bin/installer/ - example script to create installer that uses SFX module, + +bin/7zdec.exe - simplified 7z archive decoder +bin/7zr.exe - 7-Zip console program (reduced version) +bin/x64/7zr.exe - 7-Zip console program (reduced version) (x64 version) +bin/lzma.exe - file->file LZMA encoder/decoder for Windows +bin/7zS2.sfx - small SFX module for installers (GUI version) +bin/7zS2con.sfx - small SFX module for installers (Console version) +bin/7zSD.sfx - SFX module for installers. + + +7zDec.exe +--------- +7zDec.exe is simplified 7z archive decoder. +It supports only LZMA, LZMA2, and PPMd methods. +7zDec decodes whole solid block from 7z archive to RAM. +The RAM consumption can be high. + + + + +Source code structure +--------------------- + + +Asm/ - asm files (optimized code for CRC calculation and Intel-AES encryption) + +C/ - C files (compression / decompression and other) + Util/ + 7z - 7z decoder program (decoding 7z files) + Lzma - LZMA program (file->file LZMA encoder/decoder). + LzmaLib - LZMA library (.DLL for Windows) + SfxSetup - small SFX module for installers + +CPP/ -- CPP files + + Common - common files for C++ projects + Windows - common files for Windows related code + + 7zip - files related to 7-Zip + + Archive - files related to archiving + + Common - common files for archive handling + 7z - 7z C++ Encoder/Decoder + + Bundles - Modules that are bundles of other modules (files) + + Alone7z - 7zr.exe: Standalone 7-Zip console program (reduced version) + Format7zExtractR - 7zxr.dll: Reduced version of 7z DLL: extracting from 7z/LZMA/BCJ/BCJ2. + Format7zR - 7zr.dll: Reduced version of 7z DLL: extracting/compressing to 7z/LZMA/BCJ/BCJ2 + LzmaCon - lzma.exe: LZMA compression/decompression + LzmaSpec - example code for LZMA Specification + SFXCon - 7zCon.sfx: Console 7z SFX module + SFXSetup - 7zS.sfx: 7z SFX module for installers + SFXWin - 7z.sfx: GUI 7z SFX module + + Common - common files for 7-Zip + + Compress - files for compression/decompression + + Crypto - files for encryption / decompression + + UI - User Interface files + + Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll + Common - Common UI files + Console - Code for console program (7z.exe) + Explorer - Some code from 7-Zip Shell extension + FileManager - Some GUI code from 7-Zip File Manager + GUI - Some GUI code from 7-Zip + + +CS/ - C# files + 7zip + Common - some common files for 7-Zip + Compress - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + LzmaAlone - file->file LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + +Java/ - Java files + SevenZip + Compression - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + + +Note: + Asm / C / C++ source code of LZMA SDK is part of 7-Zip's source code. + 7-Zip's source code can be downloaded from 7-Zip's SourceForge page: + + http://sourceforge.net/projects/sevenzip/ + + + +LZMA features +------------- + - Variable dictionary size (up to 1 GB) + - Estimated compressing speed: about 2 MB/s on 2 GHz CPU + - Estimated decompressing speed: + - 20-30 MB/s on modern 2 GHz cpu + - 1-2 MB/s on 200 MHz simple RISC cpu: (ARM, MIPS, PowerPC) + - Small memory requirements for decompressing (16 KB + DictionarySize) + - Small code size for decompressing: 5-8 KB + +LZMA decoder uses only integer operations and can be +implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). + +Some critical operations that affect the speed of LZMA decompression: + 1) 32*16 bit integer multiply + 2) Mispredicted branches (penalty mostly depends from pipeline length) + 3) 32-bit shift and arithmetic operations + +The speed of LZMA decompressing mostly depends from CPU speed. +Memory speed has no big meaning. But if your CPU has small data cache, +overall weight of memory speed will slightly increase. + + +How To Use +---------- + +Using LZMA encoder/decoder executable +-------------------------------------- + +Usage: LZMA inputFile outputFile [...] + + e: encode file + + d: decode file + + b: Benchmark. There are two tests: compressing and decompressing + with LZMA method. Benchmark shows rating in MIPS (million + instructions per second). Rating value is calculated from + measured speed and it is normalized with Intel's Core 2 results. + Also Benchmark checks possible hardware errors (RAM + errors in most cases). Benchmark uses these settings: + (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. + Also you can change the number of iterations. Example for 30 iterations: + LZMA b 30 + Default number of iterations is 10. + + + + + -a{N}: set compression mode 0 = fast, 1 = normal + default: 1 (normal) + + d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) + The maximum value for dictionary size is 1 GB = 2^30 bytes. + Dictionary size is calculated as DictionarySize = 2^N bytes. + For decompressing file compressed by LZMA method with dictionary + size D = 2^N you need about D bytes of memory (RAM). + + -fb{N}: set number of fast bytes - [5, 273], default: 128 + Usually big number gives a little bit better compression ratio + and slower compression process. + + -lc{N}: set number of literal context bits - [0, 8], default: 3 + Sometimes lc=4 gives gain for big files. + + -lp{N}: set number of literal pos bits - [0, 4], default: 0 + lp switch is intended for periodical data when period is + equal 2^N. For example, for 32-bit (4 bytes) + periodical data you can use lp=2. Often it's better to set lc0, + if you change lp switch. + + -pb{N}: set number of pos bits - [0, 4], default: 2 + pb switch is intended for periodical data + when period is equal 2^N. + + -mf{MF_ID}: set Match Finder. Default: bt4. + Algorithms from hc* group doesn't provide good compression + ratio, but they often works pretty fast in combination with + fast mode (-a0). + + Memory requirements depend from dictionary size + (parameter "d" in table below). + + MF_ID Memory Description + + bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. + bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. + bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. + hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. + + -eos: write End Of Stream marker. By default LZMA doesn't write + eos marker, since LZMA decoder knows uncompressed size + stored in .lzma file header. + + -si: Read data from stdin (it will write End Of Stream marker). + -so: Write data to stdout + + +Examples: + +1) LZMA e file.bin file.lzma -d16 -lc0 + +compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) +and 0 literal context bits. -lc0 allows to reduce memory requirements +for decompression. + + +2) LZMA e file.bin file.lzma -lc0 -lp2 + +compresses file.bin to file.lzma with settings suitable +for 32-bit periodical data (for example, ARM or MIPS code). + +3) LZMA d file.lzma file.bin + +decompresses file.lzma to file.bin. + + +Compression ratio hints +----------------------- + +Recommendations +--------------- + +To increase the compression ratio for LZMA compressing it's desirable +to have aligned data (if it's possible) and also it's desirable to locate +data in such order, where code is grouped in one place and data is +grouped in other place (it's better than such mixing: code, data, code, +data, ...). + + +Filters +------- +You can increase the compression ratio for some data types, using +special filters before compressing. For example, it's possible to +increase the compression ratio on 5-10% for code for those CPU ISAs: +x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. + +You can find C source code of such filters in C/Bra*.* files + +You can check the compression ratio gain of these filters with such +7-Zip commands (example for ARM code): +No filter: + 7z a a1.7z a.bin -m0=lzma + +With filter for little-endian ARM code: + 7z a a2.7z a.bin -m0=arm -m1=lzma + +It works in such manner: +Compressing = Filter_encoding + LZMA_encoding +Decompressing = LZMA_decoding + Filter_decoding + +Compressing and decompressing speed of such filters is very high, +so it will not increase decompressing time too much. +Moreover, it reduces decompression time for LZMA_decoding, +since compression ratio with filtering is higher. + +These filters convert CALL (calling procedure) instructions +from relative offsets to absolute addresses, so such data becomes more +compressible. + +For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. + + + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/other-licenses/7zstub/src/DOC/lzma-specification.txt b/other-licenses/7zstub/src/DOC/lzma-specification.txt new file mode 100644 index 0000000000..b6796df756 --- /dev/null +++ b/other-licenses/7zstub/src/DOC/lzma-specification.txt @@ -0,0 +1,1176 @@ +LZMA specification (DRAFT version) +---------------------------------- + +Author: Igor Pavlov +Date: 2015-06-14 + +This specification defines the format of LZMA compressed data and lzma file format. + +Notation +-------- + +We use the syntax of C++ programming language. +We use the following types in C++ code: + unsigned - unsigned integer, at least 16 bits in size + int - signed integer, at least 16 bits in size + UInt64 - 64-bit unsigned integer + UInt32 - 32-bit unsigned integer + UInt16 - 16-bit unsigned integer + Byte - 8-bit unsigned integer + bool - boolean type with two possible values: false, true + + +lzma file format +================ + +The lzma file contains the raw LZMA stream and the header with related properties. + +The files in that format use ".lzma" extension. + +The lzma file format layout: + +Offset Size Description + + 0 1 LZMA model properties (lc, lp, pb) in encoded form + 1 4 Dictionary size (32-bit unsigned integer, little-endian) + 5 8 Uncompressed size (64-bit unsigned integer, little-endian) + 13 Compressed data (LZMA stream) + +LZMA properties: + + name Range Description + + lc [0, 8] the number of "literal context" bits + lp [0, 4] the number of "literal pos" bits + pb [0, 4] the number of "pos" bits +dictSize [0, 2^32 - 1] the dictionary size + +The following code encodes LZMA properties: + +void EncodeProperties(Byte *properties) +{ + properties[0] = (Byte)((pb * 5 + lp) * 9 + lc); + Set_UInt32_LittleEndian(properties + 1, dictSize); +} + +If the value of dictionary size in properties is smaller than (1 << 12), +the LZMA decoder must set the dictionary size variable to (1 << 12). + +#define LZMA_DIC_MIN (1 << 12) + + 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; + } + +If "Uncompressed size" field contains ones in all 64 bits, it means that +uncompressed size is unknown and there is the "end marker" in stream, +that indicates the end of decoding point. +In opposite case, if the value from "Uncompressed size" field is not +equal to ((2^64) - 1), the LZMA stream decoding must be finished after +specified number of bytes (Uncompressed size) is decoded. And if there +is the "end marker", the LZMA decoder must read that marker also. + + +The new scheme to encode LZMA properties +---------------------------------------- + +If LZMA compression is used for some another format, it's recommended to +use a new improved scheme to encode LZMA properties. That new scheme was +used in xz format that uses the LZMA2 compression algorithm. +The LZMA2 is a new compression algorithm that is based on the LZMA algorithm. + +The dictionary size in LZMA2 is encoded with just one byte and LZMA2 supports +only reduced set of dictionary sizes: + (2 << 11), (3 << 11), + (2 << 12), (3 << 12), + ... + (2 << 30), (3 << 30), + (2 << 31) - 1 + +The dictionary size can be extracted from encoded value with the following code: + + dictSize = (p == 40) ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)); + +Also there is additional limitation (lc + lp <= 4) in LZMA2 for values of +"lc" and "lp" properties: + + if (lc + lp > 4) + throw "Unsupported properties: (lc + lp) > 4"; + +There are some advantages for LZMA decoder with such (lc + lp) value +limitation. It reduces the maximum size of tables allocated by decoder. +And it reduces the complexity of initialization procedure, that can be +important to keep high speed of decoding of big number of small LZMA streams. + +It's recommended to use that limitation (lc + lp <= 4) for any new format +that uses LZMA compression. Note that the combinations of "lc" and "lp" +parameters, where (lc + lp > 4), can provide significant improvement in +compression ratio only in some rare cases. + +The LZMA properties can be encoded into two bytes in new scheme: + +Offset Size Description + + 0 1 The dictionary size encoded with LZMA2 scheme + 1 1 LZMA model properties (lc, lp, pb) in encoded form + + +The RAM usage +============= + +The RAM usage for LZMA decoder is determined by the following parts: + +1) The Sliding Window (from 4 KiB to 4 GiB). +2) The probability model counter arrays (arrays of 16-bit variables). +3) Some additional state variables (about 10 variables of 32-bit integers). + + +The RAM usage for Sliding Window +-------------------------------- + +There are two main scenarios of decoding: + +1) The decoding of full stream to one RAM buffer. + + If we decode full LZMA stream to one output buffer in RAM, the decoder + can use that output buffer as sliding window. So the decoder doesn't + need additional buffer allocated for sliding window. + +2) The decoding to some external storage. + + If we decode LZMA stream to external storage, the decoder must allocate + the buffer for sliding window. The size of that buffer must be equal + or larger than the value of dictionary size from properties of LZMA stream. + +In this specification we describe the code for decoding to some external +storage. The optimized version of code for decoding of full stream to one +output RAM buffer can require some minor changes in code. + + +The RAM usage for the probability model counters +------------------------------------------------ + +The size of the probability model counter arrays is calculated with the +following formula: + +size_of_prob_arrays = 1846 + 768 * (1 << (lp + lc)) + +Each probability model counter is 11-bit unsigned integer. +If we use 16-bit integer variables (2-byte integers) for these probability +model counters, the RAM usage required by probability model counter arrays +can be estimated with the following formula: + + RAM = 4 KiB + 1.5 KiB * (1 << (lp + lc)) + +For example, for default LZMA parameters (lp = 0 and lc = 3), the RAM usage is + + RAM_lc3_lp0 = 4 KiB + 1.5 KiB * 8 = 16 KiB + +The maximum RAM state usage is required for decoding the stream with lp = 4 +and lc = 8: + + RAM_lc8_lp4 = 4 KiB + 1.5 KiB * 4096 = 6148 KiB + +If the decoder uses LZMA2's limited property condition +(lc + lp <= 4), the RAM usage will be not larger than + + RAM_lc_lp_4 = 4 KiB + 1.5 KiB * 16 = 28 KiB + + +The RAM usage for encoder +------------------------- + +There are many variants for LZMA encoding code. +These variants have different values for memory consumption. +Note that memory consumption for LZMA Encoder can not be +smaller than memory consumption of LZMA Decoder for same stream. + +The RAM usage required by modern effective implementation of +LZMA Encoder can be estimated with the following formula: + + Encoder_RAM_Usage = 4 MiB + 11 * dictionarySize. + +But there are some modes of the encoder that require less memory. + + +LZMA Decoding +============= + +The LZMA compression algorithm uses LZ-based compression with Sliding Window +and Range Encoding as entropy coding method. + + +Sliding Window +-------------- + +LZMA uses Sliding Window compression similar to LZ77 algorithm. + +LZMA stream must be decoded to the sequence that consists +of MATCHES and LITERALS: + + - a LITERAL is a 8-bit character (one byte). + The decoder just puts that LITERAL to the uncompressed stream. + + - a MATCH is a pair of two numbers (DISTANCE-LENGTH pair). + The decoder takes one byte exactly "DISTANCE" characters behind + current position in the uncompressed stream and puts it to + uncompressed stream. The decoder must repeat it "LENGTH" times. + +The "DISTANCE" can not be larger than dictionary size. +And the "DISTANCE" can not be larger than the number of bytes in +the uncompressed stream that were decoded before that match. + +In this specification we use cyclic buffer to implement Sliding Window +for LZMA decoder: + +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; + } +}; + + +In another implementation it's possible to use one buffer that contains +Sliding Window and the whole data stream after uncompressing. + + +Range Decoder +------------- + +LZMA algorithm uses Range Encoding (1) as entropy coding method. + +LZMA stream contains just one very big number in big-endian encoding. +LZMA decoder uses the Range Decoder to extract a sequence of binary +symbols from that big number. + +The state of the Range Decoder: + +struct CRangeDecoder +{ + UInt32 Range; + UInt32 Code; + InputStream *InStream; + + bool Corrupted; +} + +The notes about UInt32 type for the "Range" and "Code" variables: + + It's possible to use 64-bit (unsigned or signed) integer type + for the "Range" and the "Code" variables instead of 32-bit unsigned, + but some additional code must be used to truncate the values to + low 32-bits after some operations. + + If the programming language does not support 32-bit unsigned integer type + (like in case of JAVA language), it's possible to use 32-bit signed integer, + but some code must be changed. For example, it's required to change the code + that uses comparison operations for UInt32 variables in this specification. + +The Range Decoder can be in some states that can be treated as +"Corruption" in LZMA stream. The Range Decoder uses the variable "Corrupted": + + (Corrupted == false), if the Range Decoder has not detected any corruption. + (Corrupted == true), if the Range Decoder has detected some corruption. + +The reference LZMA Decoder ignores the value of the "Corrupted" variable. +So it continues to decode the stream, even if the corruption can be detected +in the Range Decoder. To provide the full compatibility with output of the +reference LZMA Decoder, another LZMA Decoder implementations must also +ignore the value of the "Corrupted" variable. + +The LZMA Encoder is required to create only such LZMA streams, that will not +lead the Range Decoder to states, where the "Corrupted" variable is set to true. + +The Range Decoder reads first 5 bytes from input stream to initialize +the state: + +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; +} + +The LZMA Encoder always writes ZERO in initial byte of compressed stream. +That scheme allows to simplify the code of the Range Encoder in the +LZMA Encoder. If initial byte is not equal to ZERO, the LZMA Decoder must +stop decoding and report error. + +After the last bit of data was decoded by Range Decoder, the value of the +"Code" variable must be equal to 0. The LZMA Decoder must check it by +calling the IsFinishedOK() function: + + bool IsFinishedOK() const { return Code == 0; } + +If there is corruption in data stream, there is big probability that +the "Code" value will be not equal to 0 in the Finish() function. So that +check in the IsFinishedOK() function provides very good feature for +corruption detection. + +The value of the "Range" variable before each bit decoding can not be smaller +than ((UInt32)1 << 24). The Normalize() function keeps the "Range" value in +described range. + +#define kTopValue ((UInt32)1 << 24) + +void CRangeDecoder::Normalize() +{ + if (Range < kTopValue) + { + Range <<= 8; + Code = (Code << 8) | InStream->ReadByte(); + } +} + +Notes: if the size of the "Code" variable is larger than 32 bits, it's +required to keep only low 32 bits of the "Code" variable after the change +in Normalize() function. + +If the LZMA Stream is not corrupted, the value of the "Code" variable is +always smaller than value of the "Range" variable. +But the Range Decoder ignores some types of corruptions, so the value of +the "Code" variable can be equal or larger than value of the "Range" variable +for some "Corrupted" archives. + + +LZMA uses Range Encoding only with binary symbols of two types: + 1) binary symbols with fixed and equal probabilities (direct bits) + 2) binary symbols with predicted probabilities + +The DecodeDirectBits() function decodes the sequence of direct bits: + +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; +} + + +The Bit Decoding with Probability Model +--------------------------------------- + +The task of Bit Probability Model is to estimate probabilities of binary +symbols. And then it provides the Range Decoder with that information. +The better prediction provides better compression ratio. +The Bit Probability Model uses statistical data of previous decoded +symbols. + +That estimated probability is presented as 11-bit unsigned integer value +that represents the probability of symbol "0". + +#define kNumBitModelTotalBits 11 + +Mathematical probabilities can be presented with the following formulas: + probability(symbol_0) = prob / 2048. + probability(symbol_1) = 1 - Probability(symbol_0) = + = 1 - prob / 2048 = + = (2048 - prob) / 2048 +where the "prob" variable contains 11-bit integer probability counter. + +It's recommended to use 16-bit unsigned integer type, to store these 11-bit +probability values: + +typedef UInt16 CProb; + +Each probability value must be initialized with value ((1 << 11) / 2), +that represents the state, where probabilities of symbols 0 and 1 +are equal to 0.5: + +#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2) + +The INIT_PROBS macro is used to initialize the array of CProb variables: + +#define INIT_PROBS(p) \ + { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; } + + +The DecodeBit() function decodes one bit. +The LZMA decoder provides the pointer to CProb variable that contains +information about estimated probability for symbol 0 and the Range Decoder +updates that CProb variable after decoding. The Range Decoder increases +estimated probability of the symbol that was decoded: + +#define kNumMoveBits 5 + +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; +} + + +The Binary Tree of bit model counters +------------------------------------- + +LZMA uses a tree of Bit model variables to decode symbol that needs +several bits for storing. There are two versions of such trees in LZMA: + 1) the tree that decodes bits from high bit to low bit (the normal scheme). + 2) the tree that decodes bits from low bit to high bit (the reverse scheme). + +Each binary tree structure supports different size of decoded symbol +(the size of binary sequence that contains value of symbol). +If that size of decoded symbol is "NumBits" bits, the tree structure +uses the array of (2 << NumBits) counters of CProb type. +But only ((2 << NumBits) - 1) items are used by encoder and decoder. +The first item (the item with index equal to 0) in array is unused. +That scheme with unused array's item allows to simplify the code. + +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 +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); + } +}; + + +LZ part of LZMA +--------------- + +LZ part of LZMA describes details about the decoding of MATCHES and LITERALS. + + +The Literal Decoding +-------------------- + +The LZMA Decoder uses (1 << (lc + lp)) tables with CProb values, where +each table contains 0x300 CProb values: + + 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; + } + +To select the table for decoding it uses the context that consists of +(lc) high bits from previous literal and (lp) low bits from value that +represents current position in outputStream. + +If (State > 7), the Literal Decoder also uses "matchByte" that represents +the byte in OutputStream at position the is the DISTANCE bytes before +current position, where the DISTANCE is the distance in DISTANCE-LENGTH pair +of latest decoded match. + +The following code decodes one literal and puts it to Sliding Window buffer: + + 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)); + } + + +The match length decoding +------------------------- + +The match length decoder returns normalized (zero-based value) +length of match. That value can be converted to real length of the match +with the following code: + +#define kMatchMinLen 2 + + matchLen = len + kMatchMinLen; + +The match length decoder can return the values from 0 to 271. +And the corresponded real match length values can be in the range +from 2 to 273. + +The following scheme is used for the match length encoding: + + Binary encoding Binary Tree structure Zero-based match length + sequence (binary + decimal): + + 0 xxx LowCoder[posState] xxx + 1 0 yyy MidCoder[posState] yyy + 8 + 1 1 zzzzzzzz HighCoder zzzzzzzz + 16 + +LZMA uses bit model variable "Choice" to decode the first selection bit. + +If the first selection bit is equal to 0, the decoder uses binary tree + LowCoder[posState] to decode 3-bit zero-based match length (xxx). + +If the first selection bit is equal to 1, the decoder uses bit model + variable "Choice2" to decode the second selection bit. + + If the second selection bit is equal to 0, the decoder uses binary tree + MidCoder[posState] to decode 3-bit "yyy" value, and zero-based match + length is equal to (yyy + 8). + + If the second selection bit is equal to 1, the decoder uses binary tree + HighCoder to decode 8-bit "zzzzzzzz" value, and zero-based + match length is equal to (zzzzzzzz + 16). + +LZMA uses "posState" value as context to select the binary tree +from LowCoder and MidCoder binary tree arrays: + + unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1); + +The full code of the length decoder: + +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); + } +}; + +The LZMA decoder uses two instances of CLenDecoder class. +The first instance is for the matches of "Simple Match" type, +and the second instance is for the matches of "Rep Match" type: + + CLenDecoder LenDecoder; + CLenDecoder RepLenDecoder; + + +The match distance decoding +--------------------------- + +LZMA supports dictionary sizes up to 4 GiB minus 1. +The value of match distance (decoded by distance decoder) can be +from 1 to 2^32. But the distance value that is equal to 2^32 is used to +indicate the "End of stream" marker. So real largest match distance +that is used for LZ-window match is (2^32 - 1). + +LZMA uses normalized match length (zero-based length) +to calculate the context state "lenState" do decode the distance value: + +#define kNumLenToPosStates 4 + + unsigned lenState = len; + if (lenState > kNumLenToPosStates - 1) + lenState = kNumLenToPosStates - 1; + +The distance decoder returns the "dist" value that is zero-based value +of match distance. The real match distance can be calculated with the +following code: + + matchDistance = dist + 1; + +The state of the distance decoder and the initialization code: + + #define kEndPosModelIndex 14 + #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + #define kNumAlignBits 4 + + CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates]; + CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex]; + CBitTreeDecoder AlignDecoder; + + void InitDist() + { + for (unsigned i = 0; i < kNumLenToPosStates; i++) + PosSlotDecoder[i].Init(); + AlignDecoder.Init(); + INIT_PROBS(PosDecoders); + } + +At first stage the distance decoder decodes 6-bit "posSlot" value with bit +tree decoder from PosSlotDecoder array. It's possible to get 2^6=64 different +"posSlot" values. + + unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec); + +The encoding scheme for distance value is shown in the following table: + +posSlot (decimal) / + zero-based distance (binary) + 0 0 + 1 1 + 2 10 + 3 11 + + 4 10 x + 5 11 x + 6 10 xx + 7 11 xx + 8 10 xxx + 9 11 xxx +10 10 xxxx +11 11 xxxx +12 10 xxxxx +13 11 xxxxx + +14 10 yy zzzz +15 11 yy zzzz +16 10 yyy zzzz +17 11 yyy zzzz +... +62 10 yyyyyyyyyyyyyyyyyyyyyyyyyy zzzz +63 11 yyyyyyyyyyyyyyyyyyyyyyyyyy zzzz + +where + "x ... x" means the sequence of binary symbols encoded with binary tree and + "Reverse" scheme. It uses separated binary tree for each posSlot from 4 to 13. + "y" means direct bit encoded with range coder. + "zzzz" means the sequence of four binary symbols encoded with binary + tree with "Reverse" scheme, where one common binary tree "AlignDecoder" + is used for all posSlot values. + +If (posSlot < 4), the "dist" value is equal to posSlot value. + +If (posSlot >= 4), the decoder uses "posSlot" value to calculate the value of + the high bits of "dist" value and the number of the low bits. + + If (4 <= posSlot < kEndPosModelIndex), the decoder uses bit tree decoders. + (one separated bit tree decoder per one posSlot value) and "Reverse" scheme. + In this implementation we use one CProb array "PosDecoders" that contains + all CProb variables for all these bit decoders. + + if (posSlot >= kEndPosModelIndex), the middle bits are decoded as direct + bits from RangeDecoder and the low 4 bits are decoded with a bit tree + decoder "AlignDecoder" with "Reverse" scheme. + +The code to decode zero-based match distance: + + 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; + } + + + +LZMA Decoding modes +------------------- + +There are 2 types of LZMA streams: + +1) The stream with "End of stream" marker. +2) The stream without "End of stream" marker. + +And the LZMA Decoder supports 3 modes of decoding: + +1) The unpack size is undefined. The LZMA decoder stops decoding after + getting "End of stream" marker. + The input variables for that case: + + markerIsMandatory = true + unpackSizeDefined = false + unpackSize contains any value + +2) The unpack size is defined and LZMA decoder supports both variants, + where the stream can contain "End of stream" marker or the stream is + finished without "End of stream" marker. The LZMA decoder must detect + any of these situations. + The input variables for that case: + + markerIsMandatory = false + unpackSizeDefined = true + unpackSize contains unpack size + +3) The unpack size is defined and the LZMA stream must contain + "End of stream" marker + The input variables for that case: + + markerIsMandatory = true + unpackSizeDefined = true + unpackSize contains unpack size + + +The main loop of decoder +------------------------ + +The main loop of LZMA decoder: + +Initialize the LZMA state. +loop +{ + // begin of loop + Check "end of stream" conditions. + Decode Type of MATCH / LITERAL. + If it's LITERAL, decode LITERAL value and put the LITERAL to Window. + If it's MATCH, decode the length of match and the match distance. + Check error conditions, check end of stream conditions and copy + the sequence of match bytes from sliding window to current position + in window. + Go to begin of loop +} + +The reference implementation of LZMA decoder uses "unpackSize" variable +to keep the number of remaining bytes in output stream. So it reduces +"unpackSize" value after each decoded LITERAL or MATCH. + +The following code contains the "end of stream" condition check at the start +of the loop: + + if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory) + if (RangeDec.IsFinishedOK()) + return LZMA_RES_FINISHED_WITHOUT_MARKER; + +LZMA uses three types of matches: + +1) "Simple Match" - the match with distance value encoded with bit models. + +2) "Rep Match" - the match that uses the distance from distance + history table. + +3) "Short Rep Match" - the match of single byte length, that uses the latest + distance from distance history table. + +The LZMA decoder keeps the history of latest 4 match distances that were used +by decoder. That set of 4 variables contains zero-based match distances and +these variables are initialized with zero values: + + UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + +The LZMA decoder uses binary model variables to select type of MATCH or LITERAL: + +#define kNumStates 12 +#define kNumPosBitsMax 4 + + CProb IsMatch[kNumStates << kNumPosBitsMax]; + CProb IsRep[kNumStates]; + CProb IsRepG0[kNumStates]; + CProb IsRepG1[kNumStates]; + CProb IsRepG2[kNumStates]; + CProb IsRep0Long[kNumStates << kNumPosBitsMax]; + +The decoder uses "state" variable value to select exact variable +from "IsRep", "IsRepG0", "IsRepG1" and "IsRepG2" arrays. +The "state" variable can get the value from 0 to 11. +Initial value for "state" variable is zero: + + unsigned state = 0; + +The "state" variable is updated after each LITERAL or MATCH with one of the +following functions: + +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; } + +The decoder calculates "state2" variable value to select exact variable from +"IsMatch" and "IsRep0Long" arrays: + +unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1); +unsigned state2 = (state << kNumPosBitsMax) + posState; + +The decoder uses the following code flow scheme to select exact +type of LITERAL or MATCH: + +IsMatch[state2] decode + 0 - the Literal + 1 - the Match + IsRep[state] decode + 0 - Simple Match + 1 - Rep Match + IsRepG0[state] decode + 0 - the distance is rep0 + IsRep0Long[state2] decode + 0 - Short Rep Match + 1 - Rep Match 0 + 1 - + IsRepG1[state] decode + 0 - Rep Match 1 + 1 - + IsRepG2[state] decode + 0 - Rep Match 2 + 1 - Rep Match 3 + + +LITERAL symbol +-------------- +If the value "0" was decoded with IsMatch[state2] decoding, we have "LITERAL" type. + +At first the LZMA decoder must check that it doesn't exceed +specified uncompressed size: + + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + +Then it decodes literal value and puts it to sliding window: + + DecodeLiteral(state, rep0); + +Then the decoder must update the "state" value and "unpackSize" value; + + state = UpdateState_Literal(state); + unpackSize--; + +Then the decoder must go to the begin of main loop to decode next Match or Literal. + + +Simple Match +------------ + +If the value "1" was decoded with IsMatch[state2] decoding, +we have the "Simple Match" type. + +The distance history table is updated with the following scheme: + + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + +The zero-based length is decoded with "LenDecoder": + + len = LenDecoder.Decode(&RangeDec, posState); + +The state is update with UpdateState_Match function: + + state = UpdateState_Match(state); + +and the new "rep0" value is decoded with DecodeDistance: + + rep0 = DecodeDistance(len); + +That "rep0" will be used as zero-based distance for current match. + +If the value of "rep0" is equal to 0xFFFFFFFF, it means that we have +"End of stream" marker, so we can stop decoding and check finishing +condition in Range Decoder: + + if (rep0 == 0xFFFFFFFF) + return RangeDec.IsFinishedOK() ? + LZMA_RES_FINISHED_WITH_MARKER : + LZMA_RES_ERROR; + +If uncompressed size is defined, LZMA decoder must check that it doesn't +exceed that specified uncompressed size: + + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + +Also the decoder must check that "rep0" value is not larger than dictionary size +and is not larger than the number of already decoded bytes: + + if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0)) + return LZMA_RES_ERROR; + +Then the decoder must copy match bytes as described in +"The match symbols copying" section. + + +Rep Match +--------- + +If the LZMA decoder has decoded the value "1" with IsRep[state] variable, +we have "Rep Match" type. + +At first the LZMA decoder must check that it doesn't exceed +specified uncompressed size: + + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + +Also the decoder must return error, if the LZ window is empty: + + if (OutWindow.IsEmpty()) + return LZMA_RES_ERROR; + +If the match type is "Rep Match", the decoder uses one of the 4 variables of +distance history table to get the value of distance for current match. +And there are 4 corresponding ways of decoding flow. + +The decoder updates the distance history with the following scheme +depending from type of match: + +- "Rep Match 0" or "Short Rep Match": + ; LZMA doesn't update the distance history + +- "Rep Match 1": + UInt32 dist = rep1; + rep1 = rep0; + rep0 = dist; + +- "Rep Match 2": + UInt32 dist = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = dist; + +- "Rep Match 3": + UInt32 dist = rep3; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = dist; + +Then the decoder decodes exact subtype of "Rep Match" using "IsRepG0", "IsRep0Long", +"IsRepG1", "IsRepG2". + +If the subtype is "Short Rep Match", the decoder updates the state, puts +the one byte from window to current position in window and goes to next +MATCH/LITERAL symbol (the begin of main loop): + + state = UpdateState_ShortRep(state); + OutWindow.PutByte(OutWindow.GetByte(rep0 + 1)); + unpackSize--; + continue; + +In other cases (Rep Match 0/1/2/3), it decodes the zero-based +length of match with "RepLenDecoder" decoder: + + len = RepLenDecoder.Decode(&RangeDec, posState); + +Then it updates the state: + + state = UpdateState_Rep(state); + +Then the decoder must copy match bytes as described in +"The Match symbols copying" section. + + +The match symbols copying +------------------------- + +If we have the match (Simple Match or Rep Match 0/1/2/3), the decoder must +copy the sequence of bytes with calculated match distance and match length. +If uncompressed size is defined, LZMA decoder must check that it doesn't +exceed that specified uncompressed size: + + 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; + +Then the decoder must go to the begin of main loop to decode next MATCH or LITERAL. + + + +NOTES +----- + +This specification doesn't describe the variant of decoder implementation +that supports partial decoding. Such partial decoding case can require some +changes in "end of stream" condition checks code. Also such code +can use additional status codes, returned by decoder. + +This specification uses C++ code with templates to simplify describing. +The optimized version of LZMA decoder doesn't need templates. +Such optimized version can use just two arrays of CProb variables: + 1) The dynamic array of CProb variables allocated for the Literal Decoder. + 2) The one common array that contains all other CProb variables. + + +References: + +1. G. N. N. Martin, Range encoding: an algorithm for removing redundancy + from a digitized message, Video & Data Recording Conference, + Southampton, UK, July 24-27, 1979. diff --git a/other-licenses/7zstub/src/DOC/lzma.txt b/other-licenses/7zstub/src/DOC/lzma.txt new file mode 100644 index 0000000000..1f92142ead --- /dev/null +++ b/other-licenses/7zstub/src/DOC/lzma.txt @@ -0,0 +1,328 @@ +LZMA compression +---------------- +Version: 9.35 + +This file describes LZMA encoding and decoding functions written in C language. + +LZMA is an improved version of famous LZ77 compression algorithm. +It was improved in way of maximum increasing of compression ratio, +keeping high decompression speed and low memory requirements for +decompressing. + +Note: you can read also LZMA Specification (lzma-specification.txt from LZMA SDK) + +Also you can look source code for LZMA encoding and decoding: + C/Util/Lzma/LzmaUtil.c + + +LZMA compressed file format +--------------------------- +Offset Size Description + 0 1 Special LZMA properties (lc,lp, pb in encoded form) + 1 4 Dictionary size (little endian) + 5 8 Uncompressed size (little endian). -1 means unknown size + 13 Compressed data + + + +ANSI-C LZMA Decoder +~~~~~~~~~~~~~~~~~~~ + +Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. +If you want to use old interfaces you can download previous version of LZMA SDK +from sourceforge.net site. + +To use ANSI-C LZMA Decoder you need the following files: +1) LzmaDec.h + LzmaDec.c + 7zTypes.h + Precomp.h + Compiler.h + +Look example code: + C/Util/Lzma/LzmaUtil.c + + +Memory requirements for LZMA decoding +------------------------------------- + +Stack usage of LZMA decoding function for local variables is not +larger than 200-400 bytes. + +LZMA Decoder uses dictionary buffer and internal state structure. +Internal state structure consumes + state_size = (4 + (1.5 << (lc + lp))) KB +by default (lc=3, lp=0), state_size = 16 KB. + + +How To decompress data +---------------------- + +LZMA Decoder (ANSI-C version) now supports 2 interfaces: +1) Single-call Decompressing +2) Multi-call State Decompressing (zlib-like interface) + +You must use external allocator: +Example: +void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } +void SzFree(void *p, void *address) { p = p; free(address); } +ISzAlloc alloc = { SzAlloc, SzFree }; + +You can use p = p; operator to disable compiler warnings. + + +Single-call Decompressing +------------------------- +When to use: RAM->RAM decompressing +Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h +Compile defines: no defines +Memory Requirements: + - Input buffer: compressed size + - Output buffer: uncompressed size + - LZMA Internal Structures: state_size (16 KB for default settings) + +Interface: + int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size + propData - LZMA properties (5 bytes) + propSize - size of propData buffer (5 bytes) + finishMode - It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + You can use LZMA_FINISH_END, when you know that + current output buffer covers last bytes of stream. + alloc - Memory allocator. + + Out: + destLen - processed output size + srcLen - processed input size + + Output: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + If LZMA decoder sees end_marker before reaching output limit, it returns OK result, + and output value of destLen will be less than output buffer size limit. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + + +Multi-call State Decompressing (zlib-like interface) +---------------------------------------------------- + +When to use: file->file decompressing +Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h + +Memory Requirements: + - Buffer for input stream: any size (for example, 16 KB) + - Buffer for output stream: any size (for example, 16 KB) + - LZMA Internal Structures: state_size (16 KB for default settings) + - LZMA dictionary (dictionary size is encoded in LZMA properties header) + +1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: + unsigned char header[LZMA_PROPS_SIZE + 8]; + ReadFile(inFile, header, sizeof(header) + +2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties + + CLzmaDec state; + LzmaDec_Constr(&state); + res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); + if (res != SZ_OK) + return res; + +3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop + + LzmaDec_Init(&state); + for (;;) + { + ... + int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); + ... + } + + +4) Free all allocated structures + LzmaDec_Free(&state, &g_Alloc); + +Look example code: + C/Util/Lzma/LzmaUtil.c + + +How To compress data +-------------------- + +Compile files: + 7zTypes.h + Threads.h + LzmaEnc.h + LzmaEnc.c + LzFind.h + LzFind.c + LzFindMt.h + LzFindMt.c + LzHash.h + +Memory Requirements: + - (dictSize * 11.5 + 6 MB) + state_size + +Lzma Encoder can use two memory allocators: +1) alloc - for small arrays. +2) allocBig - for big arrays. + +For example, you can use Large RAM Pages (2 MB) in allocBig allocator for +better compression speed. Note that Windows has bad implementation for +Large RAM Pages. +It's OK to use same allocator for alloc and allocBig. + + +Single-call Compression with callbacks +-------------------------------------- + +Look example code: + C/Util/Lzma/LzmaUtil.c + +When to use: file->file compressing + +1) you must implement callback structures for interfaces: +ISeqInStream +ISeqOutStream +ICompressProgress +ISzAlloc + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + + CFileSeqInStream inStream; + CFileSeqOutStream outStream; + + inStream.funcTable.Read = MyRead; + inStream.file = inFile; + outStream.funcTable.Write = MyWrite; + outStream.file = outFile; + + +2) Create CLzmaEncHandle object; + + CLzmaEncHandle enc; + + enc = LzmaEnc_Create(&g_Alloc); + if (enc == 0) + return SZ_ERROR_MEM; + + +3) initialize CLzmaEncProps properties; + + LzmaEncProps_Init(&props); + + Then you can change some properties in that structure. + +4) Send LZMA properties to LZMA Encoder + + res = LzmaEnc_SetProps(enc, &props); + +5) Write encoded properties to header + + Byte header[LZMA_PROPS_SIZE + 8]; + size_t headerSize = LZMA_PROPS_SIZE; + UInt64 fileSize; + int i; + + res = LzmaEnc_WriteProperties(enc, header, &headerSize); + fileSize = MyGetFileLength(inFile); + for (i = 0; i < 8; i++) + header[headerSize++] = (Byte)(fileSize >> (8 * i)); + MyWriteFileAndCheck(outFile, header, headerSize) + +6) Call encoding function: + res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, + NULL, &g_Alloc, &g_Alloc); + +7) Destroy LZMA Encoder Object + LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); + + +If callback function return some error code, LzmaEnc_Encode also returns that code +or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. + + +Single-call RAM->RAM Compression +-------------------------------- + +Single-call RAM->RAM Compression is similar to Compression with callbacks, +but you provide pointers to buffers instead of pointers to stream callbacks: + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) + + + +Defines +------- + +_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. + +_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for + some structures will be doubled in that case. + +_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. + +_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. + + +_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder. + + +C++ LZMA Encoder/Decoder +~~~~~~~~~~~~~~~~~~~~~~~~ +C++ LZMA code use COM-like interfaces. So if you want to use it, +you can study basics of COM/OLE. +C++ LZMA code is just wrapper over ANSI-C code. + + +C++ Notes +~~~~~~~~~~~~~~~~~~~~~~~~ +If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), +you must check that you correctly work with "new" operator. +7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. +So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: +operator new(size_t size) +{ + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} +If you use MSCV that throws exception for "new" operator, you can compile without +"NewHandler.cpp". So standard exception will be used. Actually some code of +7-Zip catches any exception in internal code and converts it to HRESULT code. +So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/other-licenses/7zstub/src/Java/SevenZip/CRC.java b/other-licenses/7zstub/src/Java/SevenZip/CRC.java new file mode 100644 index 0000000000..f2f791f17a --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/CRC.java @@ -0,0 +1,52 @@ +// SevenZip/CRC.java + +package SevenZip; + +public class CRC +{ + static public int[] Table = new int[256]; + + static + { + for (int i = 0; i < 256; i++) + { + int r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >>> 1) ^ 0xEDB88320; + else + r >>>= 1; + Table[i] = r; + } + } + + int _value = -1; + + public void Init() + { + _value = -1; + } + + public void Update(byte[] data, int offset, int size) + { + for (int i = 0; i < size; i++) + _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); + } + + public void Update(byte[] data) + { + int size = data.length; + for (int i = 0; i < size; i++) + _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); + } + + public void UpdateByte(int b) + { + _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); + } + + public int GetDigest() + { + return _value ^ (-1); + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/BinTree.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/BinTree.java new file mode 100644 index 0000000000..63d58c05a0 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/BinTree.java @@ -0,0 +1,382 @@ +// LZ.BinTree + +package SevenZip.Compression.LZ; +import java.io.IOException; + + +public class BinTree extends InWindow +{ + int _cyclicBufferPos; + int _cyclicBufferSize = 0; + int _matchMaxLen; + + int[] _son; + int[] _hash; + + int _cutValue = 0xFF; + int _hashMask; + int _hashSizeSum = 0; + + boolean HASH_ARRAY = true; + + static final int kHash2Size = 1 << 10; + static final int kHash3Size = 1 << 16; + static final int kBT2HashSize = 1 << 16; + static final int kStartMaxLen = 1; + static final int kHash3Offset = kHash2Size; + static final int kEmptyHashValue = 0; + static final int kMaxValForNormalize = (1 << 30) - 1; + + int kNumHashDirectBytes = 0; + int kMinMatchCheck = 4; + int kFixHashSize = kHash2Size + kHash3Size; + + public void SetType(int numHashBytes) + { + HASH_ARRAY = (numHashBytes > 2); + if (HASH_ARRAY) + { + kNumHashDirectBytes = 0; + kMinMatchCheck = 4; + kFixHashSize = kHash2Size + kHash3Size; + } + else + { + kNumHashDirectBytes = 2; + kMinMatchCheck = 2 + 1; + kFixHashSize = 0; + } + } + + + + + public void Init() throws IOException + { + super.Init(); + for (int i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + } + + public void MovePos() throws IOException + { + if (++_cyclicBufferPos >= _cyclicBufferSize) + _cyclicBufferPos = 0; + super.MovePos(); + if (_pos == kMaxValForNormalize) + Normalize(); + } + + + + + + + + + public boolean Create(int historySize, int keepAddBufferBefore, + int matchMaxLen, int keepAddBufferAfter) + { + if (historySize > kMaxValForNormalize - 256) + return false; + _cutValue = 16 + (matchMaxLen >> 1); + + int windowReservSize = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + + super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); + + _matchMaxLen = matchMaxLen; + + int cyclicBufferSize = historySize + 1; + if (_cyclicBufferSize != cyclicBufferSize) + _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; + + int hs = kBT2HashSize; + + if (HASH_ARRAY) + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + _hashMask = hs; + hs++; + hs += kFixHashSize; + } + if (hs != _hashSizeSum) + _hash = new int [_hashSizeSum = hs]; + return true; + } + public int GetMatches(int[] distances) throws IOException + { + int lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + return 0; + } + } + + int offset = 0; + int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + int cur = _bufferOffset + _pos; + int maxLen = kStartMaxLen; // to avoid items for len < hashSize; + int hashValue, hash2Value = 0, hash3Value = 0; + + if (HASH_ARRAY) + { + int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); + hash2Value = temp & (kHash2Size - 1); + temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); + hash3Value = temp & (kHash3Size - 1); + hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; + } + else + hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); + + int curMatch = _hash[kFixHashSize + hashValue]; + if (HASH_ARRAY) + { + int curMatch2 = _hash[hash2Value]; + int curMatch3 = _hash[kHash3Offset + hash3Value]; + _hash[hash2Value] = _pos; + _hash[kHash3Offset + hash3Value] = _pos; + if (curMatch2 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + if (curMatch3 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + if (offset != 0 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + } + + _hash[kFixHashSize + hashValue] = _pos; + + int ptr0 = (_cyclicBufferPos << 1) + 1; + int ptr1 = (_cyclicBufferPos << 1); + + int len0, len1; + len0 = len1 = kNumHashDirectBytes; + + if (kNumHashDirectBytes != 0) + { + if (curMatch > matchMinPos) + { + if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != + _bufferBase[cur + kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + } + + int count = _cutValue; + + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + int delta = _pos - curMatch; + int cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + int pby1 = _bufferOffset + curMatch; + int len = Math.min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while(++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + } + if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + return offset; + } + + public void Skip(int num) throws IOException + { + do + { + int lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + continue; + } + } + + int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + int cur = _bufferOffset + _pos; + + int hashValue; + + if (HASH_ARRAY) + { + int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); + int hash2Value = temp & (kHash2Size - 1); + _hash[hash2Value] = _pos; + temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); + int hash3Value = temp & (kHash3Size - 1); + _hash[kHash3Offset + hash3Value] = _pos; + hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; + } + else + hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); + + int curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + int ptr0 = (_cyclicBufferPos << 1) + 1; + int ptr1 = (_cyclicBufferPos << 1); + + int len0, len1; + len0 = len1 = kNumHashDirectBytes; + + int count = _cutValue; + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + + int delta = _pos - curMatch; + int cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + int pby1 = _bufferOffset + curMatch; + int len = Math.min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while (++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + } + while (--num != 0); + } + + void NormalizeLinks(int[] items, int numItems, int subValue) + { + for (int i = 0; i < numItems; i++) + { + int value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + } + + void Normalize() + { + int subValue = _pos - _cyclicBufferSize; + NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); + NormalizeLinks(_hash, _hashSizeSum, subValue); + ReduceOffsets(subValue); + } + + public void SetCutValue(int cutValue) { _cutValue = cutValue; } + + private static final int[] CrcTable = new int[256]; + + static + { + for (int i = 0; i < 256; i++) + { + int r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >>> 1) ^ 0xEDB88320; + else + r >>>= 1; + CrcTable[i] = r; + } + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/InWindow.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/InWindow.java new file mode 100644 index 0000000000..5f3f0b4d09 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/InWindow.java @@ -0,0 +1,131 @@ +// LZ.InWindow + +package SevenZip.Compression.LZ; + +import java.io.IOException; + +public class InWindow +{ + public byte[] _bufferBase; // pointer to buffer with data + java.io.InputStream _stream; + int _posLimit; // offset (from _buffer) of first byte when new block reading must be done + boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream + + int _pointerToLastSafePosition; + + public int _bufferOffset; + + public int _blockSize; // Size of Allocated memory block + public int _pos; // offset (from _buffer) of curent byte + int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + public int _streamPos; // offset (from _buffer) of first not read byte from Stream + + public void MoveBlock() + { + int offset = _bufferOffset + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + + int numBytes = _bufferOffset + _streamPos - offset; + + // check negative offset ???? + for (int i = 0; i < numBytes; i++) + _bufferBase[i] = _bufferBase[offset + i]; + _bufferOffset -= offset; + } + + public void ReadBlock() throws IOException + { + if (_streamEndWasReached) + return; + while (true) + { + int size = (0 - _bufferOffset) + _blockSize - _streamPos; + if (size == 0) + return; + int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); + if (numReadBytes == -1) + { + _posLimit = _streamPos; + int pointerToPostion = _bufferOffset + _posLimit; + if (pointerToPostion > _pointerToLastSafePosition) + _posLimit = _pointerToLastSafePosition - _bufferOffset; + + _streamEndWasReached = true; + return; + } + _streamPos += numReadBytes; + if (_streamPos >= _pos + _keepSizeAfter) + _posLimit = _streamPos - _keepSizeAfter; + } + } + + void Free() { _bufferBase = null; } + + public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) + { + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == null || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + _bufferBase = new byte[_blockSize]; + } + _pointerToLastSafePosition = _blockSize - keepSizeAfter; + } + + public void SetStream(java.io.InputStream stream) { _stream = stream; } + public void ReleaseStream() { _stream = null; } + + public void Init() throws IOException + { + _bufferOffset = 0; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + ReadBlock(); + } + + public void MovePos() throws IOException + { + _pos++; + if (_pos > _posLimit) + { + int pointerToPostion = _bufferOffset + _pos; + if (pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + ReadBlock(); + } + } + + public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } + + // index + limit have not to exceed _keepSizeAfter; + public int GetMatchLen(int index, int distance, int limit) + { + if (_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (_pos + index); + distance++; + // Byte *pby = _buffer + (size_t)_pos + index; + int pby = _bufferOffset + _pos + index; + + int i; + for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); + return i; + } + + public int GetNumAvailableBytes() { return _streamPos - _pos; } + + public void ReduceOffsets(int subValue) + { + _bufferOffset += subValue; + _posLimit -= subValue; + _pos -= subValue; + _streamPos -= subValue; + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/OutWindow.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/OutWindow.java new file mode 100644 index 0000000000..620cb41b47 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZ/OutWindow.java @@ -0,0 +1,85 @@ +// LZ.OutWindow + +package SevenZip.Compression.LZ; + +import java.io.IOException; + +public class OutWindow +{ + byte[] _buffer; + int _pos; + int _windowSize = 0; + int _streamPos; + java.io.OutputStream _stream; + + public void Create(int windowSize) + { + if (_buffer == null || _windowSize != windowSize) + _buffer = new byte[windowSize]; + _windowSize = windowSize; + _pos = 0; + _streamPos = 0; + } + + public void SetStream(java.io.OutputStream stream) throws IOException + { + ReleaseStream(); + _stream = stream; + } + + public void ReleaseStream() throws IOException + { + Flush(); + _stream = null; + } + + public void Init(boolean solid) + { + if (!solid) + { + _streamPos = 0; + _pos = 0; + } + } + + public void Flush() throws IOException + { + int size = _pos - _streamPos; + if (size == 0) + return; + _stream.write(_buffer, _streamPos, size); + if (_pos >= _windowSize) + _pos = 0; + _streamPos = _pos; + } + + public void CopyBlock(int distance, int len) throws IOException + { + int pos = _pos - distance - 1; + if (pos < 0) + pos += _windowSize; + for (; len != 0; len--) + { + if (pos >= _windowSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos >= _windowSize) + Flush(); + } + } + + public void PutByte(byte b) throws IOException + { + _buffer[_pos++] = b; + if (_pos >= _windowSize) + Flush(); + } + + public byte GetByte(int distance) + { + int pos = _pos - distance - 1; + if (pos < 0) + pos += _windowSize; + return _buffer[pos]; + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Base.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Base.java new file mode 100644 index 0000000000..18deed9232 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Base.java @@ -0,0 +1,88 @@ +// Base.java + +package SevenZip.Compression.LZMA; + +public class Base +{ + public static final int kNumRepDistances = 4; + public static final int kNumStates = 12; + + public static final int StateInit() + { + return 0; + } + + public static final int StateUpdateChar(int index) + { + if (index < 4) + return 0; + if (index < 10) + return index - 3; + return index - 6; + } + + public static final int StateUpdateMatch(int index) + { + return (index < 7 ? 7 : 10); + } + + public static final int StateUpdateRep(int index) + { + return (index < 7 ? 8 : 11); + } + + public static final int StateUpdateShortRep(int index) + { + return (index < 7 ? 9 : 11); + } + + public static final boolean StateIsCharState(int index) + { + return index < 7; + } + + public static final int kNumPosSlotBits = 6; + public static final int kDicLogSizeMin = 0; + // public static final int kDicLogSizeMax = 28; + // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; + + public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization + public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; + + public static final int kMatchMinLen = 2; + + public static final int GetLenToPosState(int len) + { + len -= kMatchMinLen; + if (len < kNumLenToPosStates) + return len; + return (int)(kNumLenToPosStates - 1); + } + + public static final int kNumAlignBits = 4; + public static final int kAlignTableSize = 1 << kNumAlignBits; + public static final int kAlignMask = (kAlignTableSize - 1); + + public static final int kStartPosModelIndex = 4; + public static final int kEndPosModelIndex = 14; + public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + + public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); + + public static final int kNumLitPosStatesBitsEncodingMax = 4; + public static final int kNumLitContextBitsMax = 8; + + public static final int kNumPosStatesBitsMax = 4; + public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + public static final int kNumPosStatesBitsEncodingMax = 4; + public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + + public static final int kNumLowLenBits = 3; + public static final int kNumMidLenBits = 3; + public static final int kNumHighLenBits = 8; + public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; + public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; + public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + + (1 << kNumHighLenBits); + public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Decoder.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Decoder.java new file mode 100644 index 0000000000..4ebd571106 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Decoder.java @@ -0,0 +1,329 @@ +package SevenZip.Compression.LZMA; + +import SevenZip.Compression.RangeCoder.BitTreeDecoder; +import SevenZip.Compression.LZMA.Base; +import SevenZip.Compression.LZ.OutWindow; +import java.io.IOException; + +public class Decoder +{ + class LenDecoder + { + short[] m_Choice = new short[2]; + BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); + int m_NumPosStates = 0; + + public void Create(int numPosStates) + { + for (; m_NumPosStates < numPosStates; m_NumPosStates++) + { + m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); + m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); + } + } + + public void Init() + { + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); + for (int posState = 0; posState < m_NumPosStates; posState++) + { + m_LowCoder[posState].Init(); + m_MidCoder[posState].Init(); + } + m_HighCoder.Init(); + } + + public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException + { + if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) + return m_LowCoder[posState].Decode(rangeDecoder); + int symbol = Base.kNumLowLenSymbols; + if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) + symbol += m_MidCoder[posState].Decode(rangeDecoder); + else + symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); + return symbol; + } + } + + class LiteralDecoder + { + class Decoder2 + { + short[] m_Decoders = new short[0x300]; + + public void Init() + { + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); + } + + public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException + { + int symbol = 1; + do + symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); + while (symbol < 0x100); + return (byte)symbol; + } + + public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException + { + int symbol = 1; + do + { + int matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + { + while (symbol < 0x100) + symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); + break; + } + } + while (symbol < 0x100); + return (byte)symbol; + } + } + + Decoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + int m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = (1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + int numStates = 1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Decoder2[numStates]; + for (int i = 0; i < numStates; i++) + m_Coders[i] = new Decoder2(); + } + + public void Init() + { + int numStates = 1 << (m_NumPrevBits + m_NumPosBits); + for (int i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + Decoder2 GetDecoder(int pos, byte prevByte) + { + return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; + } + } + + OutWindow m_OutWindow = new OutWindow(); + SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); + + short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; + short[] m_IsRepDecoders = new short[Base.kNumStates]; + short[] m_IsRepG0Decoders = new short[Base.kNumStates]; + short[] m_IsRepG1Decoders = new short[Base.kNumStates]; + short[] m_IsRepG2Decoders = new short[Base.kNumStates]; + short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; + short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; + + BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); + + LenDecoder m_LenDecoder = new LenDecoder(); + LenDecoder m_RepLenDecoder = new LenDecoder(); + + LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); + + int m_DictionarySize = -1; + int m_DictionarySizeCheck = -1; + + int m_PosStateMask; + + public Decoder() + { + for (int i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); + } + + boolean SetDictionarySize(int dictionarySize) + { + if (dictionarySize < 0) + return false; + if (m_DictionarySize != dictionarySize) + { + m_DictionarySize = dictionarySize; + m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); + m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); + } + return true; + } + + boolean SetLcLpPb(int lc, int lp, int pb) + { + if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) + return false; + m_LiteralDecoder.Create(lp, lc); + int numPosStates = 1 << pb; + m_LenDecoder.Create(numPosStates); + m_RepLenDecoder.Create(numPosStates); + m_PosStateMask = numPosStates - 1; + return true; + } + + void Init() throws IOException + { + m_OutWindow.Init(false); + + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); + + m_LiteralDecoder.Init(); + int i; + for (i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + m_LenDecoder.Init(); + m_RepLenDecoder.Init(); + m_PosAlignDecoder.Init(); + m_RangeDecoder.Init(); + } + + public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, + long outSize) throws IOException + { + m_RangeDecoder.SetStream(inStream); + m_OutWindow.SetStream(outStream); + Init(); + + int state = Base.StateInit(); + int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + + long nowPos64 = 0; + byte prevByte = 0; + while (outSize < 0 || nowPos64 < outSize) + { + int posState = (int)nowPos64 & m_PosStateMask; + if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) + { + LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); + if (!Base.StateIsCharState(state)) + prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); + else + prevByte = decoder2.DecodeNormal(m_RangeDecoder); + m_OutWindow.PutByte(prevByte); + state = Base.StateUpdateChar(state); + nowPos64++; + } + else + { + int len; + if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) + { + len = 0; + if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) + { + if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) + { + state = Base.StateUpdateShortRep(state); + len = 1; + } + } + else + { + int distance; + if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) + distance = rep1; + else + { + if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + if (len == 0) + { + len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; + state = Base.StateUpdateRep(state); + } + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); + state = Base.StateUpdateMatch(state); + int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); + if (posSlot >= Base.kStartPosModelIndex) + { + int numDirectBits = (posSlot >> 1) - 1; + rep0 = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < Base.kEndPosModelIndex) + rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, + rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); + else + { + rep0 += (m_RangeDecoder.DecodeDirectBits( + numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); + rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); + if (rep0 < 0) + { + if (rep0 == -1) + break; + return false; + } + } + } + else + rep0 = posSlot; + } + if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) + { + // m_OutWindow.Flush(); + return false; + } + m_OutWindow.CopyBlock(rep0, len); + nowPos64 += len; + prevByte = m_OutWindow.GetByte(0); + } + } + m_OutWindow.Flush(); + m_OutWindow.ReleaseStream(); + m_RangeDecoder.ReleaseStream(); + return true; + } + + public boolean SetDecoderProperties(byte[] properties) + { + if (properties.length < 5) + return false; + int val = properties[0] & 0xFF; + int lc = val % 9; + int remainder = val / 9; + int lp = remainder % 5; + int pb = remainder / 5; + int dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); + if (!SetLcLpPb(lc, lp, pb)) + return false; + return SetDictionarySize(dictionarySize); + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Encoder.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Encoder.java new file mode 100644 index 0000000000..771fb21946 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/LZMA/Encoder.java @@ -0,0 +1,1416 @@ +package SevenZip.Compression.LZMA; + +import SevenZip.Compression.RangeCoder.BitTreeEncoder; +import SevenZip.Compression.LZMA.Base; +import SevenZip.Compression.LZ.BinTree; +import SevenZip.ICodeProgress; +import java.io.IOException; + +public class Encoder +{ + public static final int EMatchFinderTypeBT2 = 0; + public static final int EMatchFinderTypeBT4 = 1; + + + + + static final int kIfinityPrice = 0xFFFFFFF; + + static byte[] g_FastPos = new byte[1 << 11]; + + static + { + int kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (int slotFast = 2; slotFast < kFastSlots; slotFast++) + { + int k = (1 << ((slotFast >> 1) - 1)); + for (int j = 0; j < k; j++, c++) + g_FastPos[c] = (byte)slotFast; + } + } + + static int GetPosSlot(int pos) + { + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return (g_FastPos[pos >> 10] + 20); + return (g_FastPos[pos >> 20] + 40); + } + + static int GetPosSlot2(int pos) + { + if (pos < (1 << 17)) + return (g_FastPos[pos >> 6] + 12); + if (pos < (1 << 27)) + return (g_FastPos[pos >> 16] + 32); + return (g_FastPos[pos >> 26] + 52); + } + + int _state = Base.StateInit(); + byte _previousByte; + int[] _repDistances = new int[Base.kNumRepDistances]; + + void BaseInit() + { + _state = Base.StateInit(); + _previousByte = 0; + for (int i = 0; i < Base.kNumRepDistances; i++) + _repDistances[i] = 0; + } + + static final int kDefaultDictionaryLogSize = 22; + static final int kNumFastBytesDefault = 0x20; + + class LiteralEncoder + { + class Encoder2 + { + short[] m_Encoders = new short[0x300]; + + public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } + + + + public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException + { + int context = 1; + for (int i = 7; i >= 0; i--) + { + int bit = ((symbol >> i) & 1); + rangeEncoder.Encode(m_Encoders, context, bit); + context = (context << 1) | bit; + } + } + + public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException + { + int context = 1; + boolean same = true; + for (int i = 7; i >= 0; i--) + { + int bit = ((symbol >> i) & 1); + int state = context; + if (same) + { + int matchBit = ((matchByte >> i) & 1); + state += ((1 + matchBit) << 8); + same = (matchBit == bit); + } + rangeEncoder.Encode(m_Encoders, state, bit); + context = (context << 1) | bit; + } + } + + public int GetPrice(boolean matchMode, byte matchByte, byte symbol) + { + int price = 0; + int context = 1; + int i = 7; + if (matchMode) + { + for (; i >= 0; i--) + { + int matchBit = (matchByte >> i) & 1; + int bit = (symbol >> i) & 1; + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + i--; + break; + } + } + } + for (; i >= 0; i--) + { + int bit = (symbol >> i) & 1; + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); + context = (context << 1) | bit; + } + return price; + } + } + + Encoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + int m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = (1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + int numStates = 1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Encoder2[numStates]; + for (int i = 0; i < numStates; i++) + m_Coders[i] = new Encoder2(); + } + + public void Init() + { + int numStates = 1 << (m_NumPrevBits + m_NumPosBits); + for (int i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + public Encoder2 GetSubCoder(int pos, byte prevByte) + { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } + } + + class LenEncoder + { + short[] _choice = new short[2]; + BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); + + + public LenEncoder() + { + for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) + { + _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); + _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); + } + } + + public void Init(int numPosStates) + { + SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); + + for (int posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); + } + + public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException + { + if (symbol < Base.kNumLowLenSymbols) + { + rangeEncoder.Encode(_choice, 0, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + symbol -= Base.kNumLowLenSymbols; + rangeEncoder.Encode(_choice, 0, 1); + if (symbol < Base.kNumMidLenSymbols) + { + rangeEncoder.Encode(_choice, 1, 0); + _midCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + rangeEncoder.Encode(_choice, 1, 1); + _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); + } + } + } + + public void SetPrices(int posState, int numSymbols, int[] prices, int st) + { + int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); + int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); + int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); + int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); + int i = 0; + for (i = 0; i < Base.kNumLowLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); + } + for (; i < numSymbols; i++) + prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); + } + }; + + public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; + + class LenPriceTableEncoder extends LenEncoder + { + int[] _prices = new int[Base.kNumLenSymbols< 0) + { + lenRes = _matchDistances[_numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], + Base.kMatchMaxLen - lenRes); + } + _additionalOffset++; + return lenRes; + } + + void MovePos(int num) throws java.io.IOException + { + if (num > 0) + { + _matchFinder.Skip(num); + _additionalOffset += num; + } + } + + int GetRepLen1Price(int state, int posState) + { + return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); + } + + int GetPureRepPrice(int repIndex, int state, int posState) + { + int price; + if (repIndex == 0) + { + price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); + } + else + { + price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); + if (repIndex == 1) + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); + else + { + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); + } + } + return price; + } + + int GetRepPrice(int repIndex, int len, int state, int posState) + { + int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + return price + GetPureRepPrice(repIndex, state, posState); + } + + int GetPosLenPrice(int pos, int len, int posState) + { + int price; + int lenToPosState = Base.GetLenToPosState(len); + if (pos < Base.kNumFullDistances) + price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; + else + price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + + _alignPrices[pos & Base.kAlignMask]; + return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + } + + int Backward(int cur) + { + _optimumEndIndex = cur; + int posMem = _optimum[cur].PosPrev; + int backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + int posPrev = posMem; + int backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while (cur > 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; + } + + int[] reps = new int[Base.kNumRepDistances]; + int[] repLens = new int[Base.kNumRepDistances]; + int backRes; + + int GetOptimum(int position) throws IOException + { + if (_optimumEndIndex != _optimumCurrentIndex) + { + int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; + backRes = _optimum[_optimumCurrentIndex].BackPrev; + _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + return lenRes; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + int lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + lenMain = ReadMatchDistances(); + } + else + { + lenMain = _longestMatchLength; + _longestMatchWasFound = false; + } + numDistancePairs = _numDistancePairs; + + int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = -1; + return 1; + } + if (numAvailableBytes > Base.kMatchMaxLen) + numAvailableBytes = Base.kMatchMaxLen; + + int repMaxIndex = 0; + int i; + for (i = 0; i < Base.kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); + if (repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + int lenRes = repLens[repMaxIndex]; + MovePos(lenRes - 1); + return lenRes; + } + + if (lenMain >= _numFastBytes) + { + backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + + byte currentByte = _matchFinder.GetIndexByte(0 - 1); + byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); + + if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = -1; + return 1; + } + + _optimum[0].State = _state; + + int posState = (position & _posStateMask); + + _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); + _optimum[1].MakeAsChar(); + + int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); + int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); + + if (matchByte == currentByte) + { + int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if (shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + + int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + return 1; + } + + _optimum[1].PosPrev = 0; + + _optimum[0].Backs0 = reps[0]; + _optimum[0].Backs1 = reps[1]; + _optimum[0].Backs2 = reps[2]; + _optimum[0].Backs3 = reps[3]; + + int len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); + + for (i = 0; i < Base.kNumRepDistances; i++) + { + int repLen = repLens[i]; + if (repLen < 2) + continue; + int price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + Optimal optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + while (--repLen >= 2); + } + + int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + int offs = 0; + while (len > _matchDistances[offs]) + offs += 2; + for (; ; len++) + { + int distance = _matchDistances[offs + 1]; + int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + Optimal optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == _matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + int cur = 0; + + while (true) + { + cur++; + if (cur == lenEnd) + return Backward(cur); + int newLen = ReadMatchDistances(); + numDistancePairs = _numDistancePairs; + if (newLen >= _numFastBytes) + { + + _longestMatchLength = newLen; + _longestMatchWasFound = true; + return Backward(cur); + } + position++; + int posPrev = _optimum[cur].PosPrev; + int state; + if (_optimum[cur].Prev1IsChar) + { + posPrev--; + if (_optimum[cur].Prev2) + { + state = _optimum[_optimum[cur].PosPrev2].State; + if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) + state = Base.StateUpdateRep(state); + else + state = Base.StateUpdateMatch(state); + } + else + state = _optimum[posPrev].State; + state = Base.StateUpdateChar(state); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (_optimum[cur].IsShortRep()) + state = Base.StateUpdateShortRep(state); + else + state = Base.StateUpdateChar(state); + } + else + { + int pos; + if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + { + posPrev = _optimum[cur].PosPrev2; + pos = _optimum[cur].BackPrev2; + state = Base.StateUpdateRep(state); + } + else + { + pos = _optimum[cur].BackPrev; + if (pos < Base.kNumRepDistances) + state = Base.StateUpdateRep(state); + else + state = Base.StateUpdateMatch(state); + } + Optimal opt = _optimum[posPrev]; + if (pos < Base.kNumRepDistances) + { + if (pos == 0) + { + reps[0] = opt.Backs0; + reps[1] = opt.Backs1; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 1) + { + reps[0] = opt.Backs1; + reps[1] = opt.Backs0; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 2) + { + reps[0] = opt.Backs2; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs3; + } + else + { + reps[0] = opt.Backs3; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + else + { + reps[0] = (pos - Base.kNumRepDistances); + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + _optimum[cur].State = state; + _optimum[cur].Backs0 = reps[0]; + _optimum[cur].Backs1 = reps[1]; + _optimum[cur].Backs2 = reps[2]; + _optimum[cur].Backs3 = reps[3]; + int curPrice = _optimum[cur].Price; + + currentByte = _matchFinder.GetIndexByte(0 - 1); + matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); + + posState = (position & _posStateMask); + + int curAnd1Price = curPrice + + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). + GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); + + Optimal nextOptimum = _optimum[cur + 1]; + + boolean nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); + repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); + + if (matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if (shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + + int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; + numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); + numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) + { + // try Literal + rep0 + int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); + int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); + if (lenTest2 >= 2) + { + int state2 = Base.StateUpdateChar(state); + + int posStateNext = (position + 1) & _posStateMask; + int nextRepMatchPrice = curAnd1Price + + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); + { + int offset = cur + 1 + lenTest2; + while (lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + int curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + int startLen = 2; // speed optimization + + for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) + { + int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); + if (lenTest < 2) + continue; + int lenTestTemp = lenTest; + do + { + while (lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } + while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + if (lenTest < numAvailableBytesFull) + { + int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); + if (lenTest2 >= 2) + { + int state2 = Base.StateUpdateRep(state); + + int posStateNext = (position + lenTest) & _posStateMask; + int curAndLenCharPrice = + repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, + _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), + _matchFinder.GetIndexByte(lenTest - 1)); + state2 = Base.StateUpdateChar(state2); + posStateNext = (position + lenTest + 1) & _posStateMask; + int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); + int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); + + // for(; lenTest2 >= 2; lenTest2--) + { + int offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; + _matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); + while (lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + int offs = 0; + while (startLen > _matchDistances[offs]) + offs += 2; + + for (int lenTest = startLen; ; lenTest++) + { + int curBack = _matchDistances[offs + 1]; + int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (lenTest == _matchDistances[offs]) + { + if (lenTest < numAvailableBytesFull) + { + int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); + if (lenTest2 >= 2) + { + int state2 = Base.StateUpdateMatch(state); + + int posStateNext = (position + lenTest) & _posStateMask; + int curAndLenCharPrice = curAndLenPrice + + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte(lenTest - 1 - 1)). + GetPrice(true, + _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), + _matchFinder.GetIndexByte(lenTest - 1)); + state2 = Base.StateUpdateChar(state2); + posStateNext = (position + lenTest + 1) & _posStateMask; + int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); + int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); + + int offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + Base.kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + } + } + + boolean ChangePair(int smallDist, int bigDist) + { + int kDif = 7; + return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); + } + + void WriteEndMarker(int posState) throws IOException + { + if (!_writeEndMark) + return; + + _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); + _rangeEncoder.Encode(_isRep, _state, 0); + _state = Base.StateUpdateMatch(_state); + int len = Base.kMatchMinLen; + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + int posSlot = (1 << Base.kNumPosSlotBits) - 1; + int lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + int footerBits = 30; + int posReduced = (1 << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + } + + void Flush(int nowPos) throws IOException + { + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + _rangeEncoder.FlushStream(); + } + + public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException + { + inSize[0] = 0; + outSize[0] = 0; + finished[0] = true; + + if (_inStream != null) + { + _matchFinder.SetStream(_inStream); + _matchFinder.Init(); + _needReleaseMFStream = true; + _inStream = null; + } + + if (_finished) + return; + _finished = true; + + + long progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((int)nowPos64); + return; + } + + ReadMatchDistances(); + int posState = (int)(nowPos64) & _posStateMask; + _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); + _state = Base.StateUpdateChar(_state); + byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); + _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((int)nowPos64); + return; + } + while (true) + { + + int len = GetOptimum((int)nowPos64); + int pos = backRes; + int posState = ((int)nowPos64) & _posStateMask; + int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; + if (len == 1 && pos == -1) + { + _rangeEncoder.Encode(_isMatch, complexState, 0); + byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); + LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); + if (!Base.StateIsCharState(_state)) + { + byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); + subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); + } + else + subCoder.Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _state = Base.StateUpdateChar(_state); + } + else + { + _rangeEncoder.Encode(_isMatch, complexState, 1); + if (pos < Base.kNumRepDistances) + { + _rangeEncoder.Encode(_isRep, _state, 1); + if (pos == 0) + { + _rangeEncoder.Encode(_isRepG0, _state, 0); + if (len == 1) + _rangeEncoder.Encode(_isRep0Long, complexState, 0); + else + _rangeEncoder.Encode(_isRep0Long, complexState, 1); + } + else + { + _rangeEncoder.Encode(_isRepG0, _state, 1); + if (pos == 1) + _rangeEncoder.Encode(_isRepG1, _state, 0); + else + { + _rangeEncoder.Encode(_isRepG1, _state, 1); + _rangeEncoder.Encode(_isRepG2, _state, pos - 2); + } + } + if (len == 1) + _state = Base.StateUpdateShortRep(_state); + else + { + _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + _state = Base.StateUpdateRep(_state); + } + int distance = _repDistances[pos]; + if (pos != 0) + { + for (int i = pos; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + } + else + { + _rangeEncoder.Encode(_isRep, _state, 0); + _state = Base.StateUpdateMatch(_state); + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + pos -= Base.kNumRepDistances; + int posSlot = GetPosSlot(pos); + int lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + + if (posSlot >= Base.kStartPosModelIndex) + { + int footerBits = (int)((posSlot >> 1) - 1); + int baseVal = ((2 | (posSlot & 1)) << footerBits); + int posReduced = pos - baseVal; + + if (posSlot < Base.kEndPosModelIndex) + BitTreeEncoder.ReverseEncode(_posEncoders, + baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + _alignPriceCount++; + } + } + int distance = pos; + for (int i = Base.kNumRepDistances - 1; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + _matchPriceCount++; + } + _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); + } + _additionalOffset -= len; + nowPos64 += len; + if (_additionalOffset == 0) + { + // if (!_fastMode) + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= Base.kAlignTableSize) + FillAlignPrices(); + inSize[0] = nowPos64; + outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((int)nowPos64); + return; + } + + if (nowPos64 - progressPosValuePrev >= (1 << 12)) + { + _finished = false; + finished[0] = false; + return; + } + } + } + } + + void ReleaseMFStream() + { + if (_matchFinder != null && _needReleaseMFStream) + { + _matchFinder.ReleaseStream(); + _needReleaseMFStream = false; + } + } + + void SetOutStream(java.io.OutputStream outStream) + { _rangeEncoder.SetStream(outStream); } + void ReleaseOutStream() + { _rangeEncoder.ReleaseStream(); } + + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, + long inSize, long outSize) + { + _inStream = inStream; + _finished = false; + Create(); + SetOutStream(outStream); + Init(); + + // if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _lenEncoder.UpdateTables(1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _repMatchLenEncoder.UpdateTables(1 << _posStateBits); + + nowPos64 = 0; + } + + long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; + public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, + long inSize, long outSize, ICodeProgress progress) throws IOException + { + _needReleaseMFStream = false; + try + { + SetStreams(inStream, outStream, inSize, outSize); + while (true) + { + + + + CodeOneBlock(processedInSize, processedOutSize, finished); + if (finished[0]) + return; + if (progress != null) + { + progress.SetProgress(processedInSize[0], processedOutSize[0]); + } + } + } + finally + { + ReleaseStreams(); + } + } + + public static final int kPropSize = 5; + byte[] properties = new byte[kPropSize]; + + public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException + { + properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); + for (int i = 0; i < 4; i++) + properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); + outStream.write(properties, 0, kPropSize); + } + + int[] tempPrices = new int[Base.kNumFullDistances]; + int _matchPriceCount; + + void FillDistancesPrices() + { + for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) + { + int posSlot = GetPosSlot(i); + int footerBits = (int)((posSlot >> 1) - 1); + int baseVal = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, + baseVal - posSlot - 1, footerBits, i - baseVal); + } + + for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) + { + int posSlot; + BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; + + int st = (lenToPosState << Base.kNumPosSlotBits); + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); + for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); + + int st2 = lenToPosState * Base.kNumFullDistances; + int i; + for (i = 0; i < Base.kStartPosModelIndex; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + i]; + for (; i < Base.kNumFullDistances; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; + } + + void FillAlignPrices() + { + for (int i = 0; i < Base.kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; + } + + + public boolean SetAlgorithm(int algorithm) + { + /* + _fastMode = (algorithm == 0); + _maxMode = (algorithm >= 2); + */ + return true; + } + + public boolean SetDictionarySize(int dictionarySize) + { + int kDicLogSizeMaxCompress = 29; + if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) + return false; + _dictionarySize = dictionarySize; + int dicLogSize; + for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; + _distTableSize = dicLogSize * 2; + return true; + } + + public boolean SetNumFastBytes(int numFastBytes) + { + if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) + return false; + _numFastBytes = numFastBytes; + return true; + } + + public boolean SetMatchFinder(int matchFinderIndex) + { + if (matchFinderIndex < 0 || matchFinderIndex > 2) + return false; + int matchFinderIndexPrev = _matchFinderType; + _matchFinderType = matchFinderIndex; + if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) + { + _dictionarySizePrev = -1; + _matchFinder = null; + } + return true; + } + + public boolean SetLcLpPb(int lc, int lp, int pb) + { + if ( + lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || + lc < 0 || lc > Base.kNumLitContextBitsMax || + pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) + return false; + _numLiteralPosStateBits = lp; + _numLiteralContextBits = lc; + _posStateBits = pb; + _posStateMask = ((1) << _posStateBits) - 1; + return true; + } + + public void SetEndMarkerMode(boolean endMarkerMode) + { + _writeEndMark = endMarkerMode; + } +} + diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java new file mode 100644 index 0000000000..6864c69cef --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java @@ -0,0 +1,55 @@ +package SevenZip.Compression.RangeCoder; + +public class BitTreeDecoder +{ + short[] Models; + int NumBitLevels; + + public BitTreeDecoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new short[1 << numBitLevels]; + } + + public void Init() + { + Decoder.InitBitModels(Models); + } + + public int Decode(Decoder rangeDecoder) throws java.io.IOException + { + int m = 1; + for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) + m = (m << 1) + rangeDecoder.DecodeBit(Models, m); + return m - (1 << NumBitLevels); + } + + public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException + { + int m = 1; + int symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + int bit = rangeDecoder.DecodeBit(Models, m); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + + public static int ReverseDecode(short[] Models, int startIndex, + Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException + { + int m = 1; + int symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + int bit = rangeDecoder.DecodeBit(Models, startIndex + m); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java new file mode 100644 index 0000000000..b4c0a0721d --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java @@ -0,0 +1,99 @@ +package SevenZip.Compression.RangeCoder; +import java.io.IOException; + +public class BitTreeEncoder +{ + short[] Models; + int NumBitLevels; + + public BitTreeEncoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new short[1 << numBitLevels]; + } + + public void Init() + { + Decoder.InitBitModels(Models); + } + + public void Encode(Encoder rangeEncoder, int symbol) throws IOException + { + int m = 1; + for (int bitIndex = NumBitLevels; bitIndex != 0; ) + { + bitIndex--; + int bit = (symbol >>> bitIndex) & 1; + rangeEncoder.Encode(Models, m, bit); + m = (m << 1) | bit; + } + } + + public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException + { + int m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + int bit = symbol & 1; + rangeEncoder.Encode(Models, m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + + public int GetPrice(int symbol) + { + int price = 0; + int m = 1; + for (int bitIndex = NumBitLevels; bitIndex != 0; ) + { + bitIndex--; + int bit = (symbol >>> bitIndex) & 1; + price += Encoder.GetPrice(Models[m], bit); + m = (m << 1) + bit; + } + return price; + } + + public int ReverseGetPrice(int symbol) + { + int price = 0; + int m = 1; + for (int i = NumBitLevels; i != 0; i--) + { + int bit = symbol & 1; + symbol >>>= 1; + price += Encoder.GetPrice(Models[m], bit); + m = (m << 1) | bit; + } + return price; + } + + public static int ReverseGetPrice(short[] Models, int startIndex, + int NumBitLevels, int symbol) + { + int price = 0; + int m = 1; + for (int i = NumBitLevels; i != 0; i--) + { + int bit = symbol & 1; + symbol >>>= 1; + price += Encoder.GetPrice(Models[startIndex + m], bit); + m = (m << 1) | bit; + } + return price; + } + + public static void ReverseEncode(short[] Models, int startIndex, + Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException + { + int m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + int bit = symbol & 1; + rangeEncoder.Encode(Models, startIndex + m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Decoder.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Decoder.java new file mode 100644 index 0000000000..7453383483 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Decoder.java @@ -0,0 +1,88 @@ +package SevenZip.Compression.RangeCoder; +import java.io.IOException; + +public class Decoder +{ + static final int kTopMask = ~((1 << 24) - 1); + + static final int kNumBitModelTotalBits = 11; + static final int kBitModelTotal = (1 << kNumBitModelTotalBits); + static final int kNumMoveBits = 5; + + int Range; + int Code; + + java.io.InputStream Stream; + + public final void SetStream(java.io.InputStream stream) + { + Stream = stream; + } + + public final void ReleaseStream() + { + Stream = null; + } + + public final void Init() throws IOException + { + Code = 0; + Range = -1; + for (int i = 0; i < 5; i++) + Code = (Code << 8) | Stream.read(); + } + + public final int DecodeDirectBits(int numTotalBits) throws IOException + { + int result = 0; + for (int i = numTotalBits; i != 0; i--) + { + Range >>>= 1; + int t = ((Code - Range) >>> 31); + Code -= Range & (t - 1); + result = (result << 1) | (1 - t); + + if ((Range & kTopMask) == 0) + { + Code = (Code << 8) | Stream.read(); + Range <<= 8; + } + } + return result; + } + + public int DecodeBit(short []probs, int index) throws IOException + { + int prob = probs[index]; + int newBound = (Range >>> kNumBitModelTotalBits) * prob; + if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) + { + Range = newBound; + probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); + if ((Range & kTopMask) == 0) + { + Code = (Code << 8) | Stream.read(); + Range <<= 8; + } + return 0; + } + else + { + Range -= newBound; + Code -= newBound; + probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); + if ((Range & kTopMask) == 0) + { + Code = (Code << 8) | Stream.read(); + Range <<= 8; + } + return 1; + } + } + + public static void InitBitModels(short []probs) + { + for (int i = 0; i < probs.length; i++) + probs[i] = (kBitModelTotal >>> 1); + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Encoder.java b/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Encoder.java new file mode 100644 index 0000000000..2273e92e50 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/Compression/RangeCoder/Encoder.java @@ -0,0 +1,151 @@ +package SevenZip.Compression.RangeCoder; +import java.io.IOException; + +public class Encoder +{ + static final int kTopMask = ~((1 << 24) - 1); + + static final int kNumBitModelTotalBits = 11; + static final int kBitModelTotal = (1 << kNumBitModelTotalBits); + static final int kNumMoveBits = 5; + + java.io.OutputStream Stream; + + long Low; + int Range; + int _cacheSize; + int _cache; + + long _position; + + public void SetStream(java.io.OutputStream stream) + { + Stream = stream; + } + + public void ReleaseStream() + { + Stream = null; + } + + public void Init() + { + _position = 0; + Low = 0; + Range = -1; + _cacheSize = 1; + _cache = 0; + } + + public void FlushData() throws IOException + { + for (int i = 0; i < 5; i++) + ShiftLow(); + } + + public void FlushStream() throws IOException + { + Stream.flush(); + } + + public void ShiftLow() throws IOException + { + int LowHi = (int)(Low >>> 32); + if (LowHi != 0 || Low < 0xFF000000L) + { + _position += _cacheSize; + int temp = _cache; + do + { + Stream.write(temp + LowHi); + temp = 0xFF; + } + while(--_cacheSize != 0); + _cache = (((int)Low) >>> 24); + } + _cacheSize++; + Low = (Low & 0xFFFFFF) << 8; + } + + public void EncodeDirectBits(int v, int numTotalBits) throws IOException + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>>= 1; + if (((v >>> i) & 1) == 1) + Low += Range; + if ((Range & Encoder.kTopMask) == 0) + { + Range <<= 8; + ShiftLow(); + } + } + } + + + public long GetProcessedSizeAdd() + { + return _cacheSize + _position + 4; + } + + + + static final int kNumMoveReducingBits = 2; + public static final int kNumBitPriceShiftBits = 6; + + public static void InitBitModels(short []probs) + { + for (int i = 0; i < probs.length; i++) + probs[i] = (kBitModelTotal >>> 1); + } + + public void Encode(short []probs, int index, int symbol) throws IOException + { + int prob = probs[index]; + int newBound = (Range >>> kNumBitModelTotalBits) * prob; + if (symbol == 0) + { + Range = newBound; + probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); + } + else + { + Low += (newBound & 0xFFFFFFFFL); + Range -= newBound; + probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); + } + if ((Range & kTopMask) == 0) + { + Range <<= 8; + ShiftLow(); + } + } + + private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; + + static + { + int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for (int i = kNumBits - 1; i >= 0; i--) + { + int start = 1 << (kNumBits - i - 1); + int end = 1 << (kNumBits - i); + for (int j = start; j < end; j++) + ProbPrices[j] = (i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); + } + } + + static public int GetPrice(int Prob, int symbol) + { + return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; + } + static public int GetPrice0(int Prob) + { + return ProbPrices[Prob >>> kNumMoveReducingBits]; + } + static public int GetPrice1(int Prob) + { + return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/ICodeProgress.java b/other-licenses/7zstub/src/Java/SevenZip/ICodeProgress.java new file mode 100644 index 0000000000..290bd2d024 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/ICodeProgress.java @@ -0,0 +1,6 @@ +package SevenZip; + +public interface ICodeProgress +{ + public void SetProgress(long inSize, long outSize); +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/LzmaAlone.java b/other-licenses/7zstub/src/Java/SevenZip/LzmaAlone.java new file mode 100644 index 0000000000..de39a22cc2 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/LzmaAlone.java @@ -0,0 +1,253 @@ +package SevenZip; + +public class LzmaAlone +{ + static public class CommandLine + { + public static final int kEncode = 0; + public static final int kDecode = 1; + public static final int kBenchmak = 2; + + public int Command = -1; + public int NumBenchmarkPasses = 10; + + public int DictionarySize = 1 << 23; + public boolean DictionarySizeIsDefined = false; + + public int Lc = 3; + public int Lp = 0; + public int Pb = 2; + + public int Fb = 128; + public boolean FbIsDefined = false; + + public boolean Eos = false; + + public int Algorithm = 2; + public int MatchFinder = 1; + + public String InFile; + public String OutFile; + + boolean ParseSwitch(String s) + { + if (s.startsWith("d")) + { + DictionarySize = 1 << Integer.parseInt(s.substring(1)); + DictionarySizeIsDefined = true; + } + else if (s.startsWith("fb")) + { + Fb = Integer.parseInt(s.substring(2)); + FbIsDefined = true; + } + else if (s.startsWith("a")) + Algorithm = Integer.parseInt(s.substring(1)); + else if (s.startsWith("lc")) + Lc = Integer.parseInt(s.substring(2)); + else if (s.startsWith("lp")) + Lp = Integer.parseInt(s.substring(2)); + else if (s.startsWith("pb")) + Pb = Integer.parseInt(s.substring(2)); + else if (s.startsWith("eos")) + Eos = true; + else if (s.startsWith("mf")) + { + String mfs = s.substring(2); + if (mfs.equals("bt2")) + MatchFinder = 0; + else if (mfs.equals("bt4")) + MatchFinder = 1; + else if (mfs.equals("bt4b")) + MatchFinder = 2; + else + return false; + } + else + return false; + return true; + } + + public boolean Parse(String[] args) throws Exception + { + int pos = 0; + boolean switchMode = true; + for (int i = 0; i < args.length; i++) + { + String s = args[i]; + if (s.length() == 0) + return false; + if (switchMode) + { + if (s.compareTo("--") == 0) + { + switchMode = false; + continue; + } + if (s.charAt(0) == '-') + { + String sw = s.substring(1).toLowerCase(); + if (sw.length() == 0) + return false; + try + { + if (!ParseSwitch(sw)) + return false; + } + catch (NumberFormatException e) + { + return false; + } + continue; + } + } + if (pos == 0) + { + if (s.equalsIgnoreCase("e")) + Command = kEncode; + else if (s.equalsIgnoreCase("d")) + Command = kDecode; + else if (s.equalsIgnoreCase("b")) + Command = kBenchmak; + else + return false; + } + else if(pos == 1) + { + if (Command == kBenchmak) + { + try + { + NumBenchmarkPasses = Integer.parseInt(s); + if (NumBenchmarkPasses < 1) + return false; + } + catch (NumberFormatException e) + { + return false; + } + } + else + InFile = s; + } + else if(pos == 2) + OutFile = s; + else + return false; + pos++; + continue; + } + return true; + } + } + + + static void PrintHelp() + { + System.out.println( + "\nUsage: LZMA [...] inputFile outputFile\n" + + " e: encode file\n" + + " d: decode file\n" + + " b: Benchmark\n" + + "\n" + + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + + " -eos: write End Of Stream marker\n" + ); + } + + public static void main(String[] args) throws Exception + { + System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); + + if (args.length < 1) + { + PrintHelp(); + return; + } + + CommandLine params = new CommandLine(); + if (!params.Parse(args)) + { + System.out.println("\nIncorrect command"); + return; + } + + if (params.Command == CommandLine.kBenchmak) + { + int dictionary = (1 << 21); + if (params.DictionarySizeIsDefined) + dictionary = params.DictionarySize; + if (params.MatchFinder > 1) + throw new Exception("Unsupported match finder"); + SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); + } + else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) + { + java.io.File inFile = new java.io.File(params.InFile); + java.io.File outFile = new java.io.File(params.OutFile); + + java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); + java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); + + boolean eos = false; + if (params.Eos) + eos = true; + if (params.Command == CommandLine.kEncode) + { + SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); + if (!encoder.SetAlgorithm(params.Algorithm)) + throw new Exception("Incorrect compression mode"); + if (!encoder.SetDictionarySize(params.DictionarySize)) + throw new Exception("Incorrect dictionary size"); + if (!encoder.SetNumFastBytes(params.Fb)) + throw new Exception("Incorrect -fb value"); + if (!encoder.SetMatchFinder(params.MatchFinder)) + throw new Exception("Incorrect -mf value"); + if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) + throw new Exception("Incorrect -lc or -lp or -pb value"); + encoder.SetEndMarkerMode(eos); + encoder.WriteCoderProperties(outStream); + long fileSize; + if (eos) + fileSize = -1; + else + fileSize = inFile.length(); + for (int i = 0; i < 8; i++) + outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); + encoder.Code(inStream, outStream, -1, -1, null); + } + else + { + int propertiesSize = 5; + byte[] properties = new byte[propertiesSize]; + if (inStream.read(properties, 0, propertiesSize) != propertiesSize) + throw new Exception("input .lzma file is too short"); + SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); + if (!decoder.SetDecoderProperties(properties)) + throw new Exception("Incorrect stream properties"); + long outSize = 0; + for (int i = 0; i < 8; i++) + { + int v = inStream.read(); + if (v < 0) + throw new Exception("Can't read stream size"); + outSize |= ((long)v) << (8 * i); + } + if (!decoder.Code(inStream, outStream, outSize)) + throw new Exception("Error in data stream"); + } + outStream.flush(); + outStream.close(); + inStream.close(); + } + else + throw new Exception("Incorrect command"); + return; + } +} diff --git a/other-licenses/7zstub/src/Java/SevenZip/LzmaBench.java b/other-licenses/7zstub/src/Java/SevenZip/LzmaBench.java new file mode 100644 index 0000000000..cceda24da2 --- /dev/null +++ b/other-licenses/7zstub/src/Java/SevenZip/LzmaBench.java @@ -0,0 +1,392 @@ +package SevenZip; + +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +public class LzmaBench +{ + static final int kAdditionalSize = (1 << 21); + static final int kCompressedAdditionalSize = (1 << 10); + + static class CRandomGenerator + { + int A1; + int A2; + public CRandomGenerator() { Init(); } + public void Init() { A1 = 362436069; A2 = 521288629; } + public int GetRnd() + { + return + ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ + ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); + } + }; + + static class CBitRandomGenerator + { + CRandomGenerator RG = new CRandomGenerator(); + int Value; + int NumBits; + public void Init() + { + Value = 0; + NumBits = 0; + } + public int GetRnd(int numBits) + { + int result; + if (NumBits > numBits) + { + result = Value & ((1 << numBits) - 1); + Value >>>= numBits; + NumBits -= numBits; + return result; + } + numBits -= NumBits; + result = (Value << numBits); + Value = RG.GetRnd(); + result |= Value & (((int)1 << numBits) - 1); + Value >>>= numBits; + NumBits = 32 - numBits; + return result; + } + }; + + static class CBenchRandomGenerator + { + CBitRandomGenerator RG = new CBitRandomGenerator(); + int Pos; + int Rep0; + + public int BufferSize; + public byte[] Buffer = null; + + public CBenchRandomGenerator() { } + public void Set(int bufferSize) + { + Buffer = new byte[bufferSize]; + Pos = 0; + BufferSize = bufferSize; + } + int GetRndBit() { return RG.GetRnd(1); } + int GetLogRandBits(int numBits) + { + int len = RG.GetRnd(numBits); + return RG.GetRnd((int)len); + } + int GetOffset() + { + if (GetRndBit() == 0) + return GetLogRandBits(4); + return (GetLogRandBits(4) << 10) | RG.GetRnd(10); + } + int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } + int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } + public void Generate() + { + RG.Init(); + Rep0 = 1; + while (Pos < BufferSize) + { + if (GetRndBit() == 0 || Pos < 1) + Buffer[Pos++] = (byte)(RG.GetRnd(8)); + else + { + int len; + if (RG.GetRnd(3) == 0) + len = 1 + GetLen1(); + else + { + do + Rep0 = GetOffset(); + while (Rep0 >= Pos); + Rep0++; + len = 2 + GetLen2(); + } + for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) + Buffer[Pos] = Buffer[Pos - Rep0]; + } + } + } + }; + + static class CrcOutStream extends java.io.OutputStream + { + public CRC CRC = new CRC(); + + public void Init() + { + CRC.Init(); + } + public int GetDigest() + { + return CRC.GetDigest(); + } + public void write(byte[] b) + { + CRC.Update(b); + } + public void write(byte[] b, int off, int len) + { + CRC.Update(b, off, len); + } + public void write(int b) + { + CRC.UpdateByte(b); + } + }; + + static class MyOutputStream extends java.io.OutputStream + { + byte[] _buffer; + int _size; + int _pos; + + public MyOutputStream(byte[] buffer) + { + _buffer = buffer; + _size = _buffer.length; + } + + public void reset() + { + _pos = 0; + } + + public void write(int b) throws IOException + { + if (_pos >= _size) + throw new IOException("Error"); + _buffer[_pos++] = (byte)b; + } + + public int size() + { + return _pos; + } + }; + + static class MyInputStream extends java.io.InputStream + { + byte[] _buffer; + int _size; + int _pos; + + public MyInputStream(byte[] buffer, int size) + { + _buffer = buffer; + _size = size; + } + + public void reset() + { + _pos = 0; + } + + public int read() + { + if (_pos >= _size) + return -1; + return _buffer[_pos++] & 0xFF; + } + }; + + static class CProgressInfo implements ICodeProgress + { + public long ApprovedStart; + public long InSize; + public long Time; + public void Init() + { InSize = 0; } + public void SetProgress(long inSize, long outSize) + { + if (inSize >= ApprovedStart && InSize == 0) + { + Time = System.currentTimeMillis(); + InSize = inSize; + } + } + } + static final int kSubBits = 8; + + static int GetLogSize(int size) + { + for (int i = kSubBits; i < 32; i++) + for (int j = 0; j < (1 << kSubBits); j++) + if (size <= ((1) << i) + (j << (i - kSubBits))) + return (i << kSubBits) + j; + return (32 << kSubBits); + } + + static long MyMultDiv64(long value, long elapsedTime) + { + long freq = 1000; // ms + long elTime = elapsedTime; + while (freq > 1000000) + { + freq >>>= 1; + elTime >>>= 1; + } + if (elTime == 0) + elTime = 1; + return value * freq / elTime; + } + + static long GetCompressRating(int dictionarySize, long elapsedTime, long size) + { + long t = GetLogSize(dictionarySize) - (18 << kSubBits); + long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); + long numCommands = (long)(size) * numCommandsForOne; + return MyMultDiv64(numCommands, elapsedTime); + } + + static long GetDecompressRating(long elapsedTime, long outSize, long inSize) + { + long numCommands = inSize * 220 + outSize * 20; + return MyMultDiv64(numCommands, elapsedTime); + } + + static long GetTotalRating( + int dictionarySize, + long elapsedTimeEn, long sizeEn, + long elapsedTimeDe, + long inSizeDe, long outSizeDe) + { + return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; + } + + static void PrintValue(long v) + { + String s = ""; + s += v; + for (int i = 0; i + s.length() < 6; i++) + System.out.print(" "); + System.out.print(s); + } + + static void PrintRating(long rating) + { + PrintValue(rating / 1000000); + System.out.print(" MIPS"); + } + + static void PrintResults( + int dictionarySize, + long elapsedTime, + long size, + boolean decompressMode, long secondSize) + { + long speed = MyMultDiv64(size, elapsedTime); + PrintValue(speed / 1024); + System.out.print(" KB/s "); + long rating; + if (decompressMode) + rating = GetDecompressRating(elapsedTime, size, secondSize); + else + rating = GetCompressRating(dictionarySize, elapsedTime, size); + PrintRating(rating); + } + + static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception + { + if (numIterations <= 0) + return 0; + if (dictionarySize < (1 << 18)) + { + System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); + return 1; + } + System.out.print("\n Compressing Decompressing\n\n"); + + SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); + SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); + + if (!encoder.SetDictionarySize(dictionarySize)) + throw new Exception("Incorrect dictionary size"); + + int kBufferSize = dictionarySize + kAdditionalSize; + int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; + + ByteArrayOutputStream propStream = new ByteArrayOutputStream(); + encoder.WriteCoderProperties(propStream); + byte[] propArray = propStream.toByteArray(); + decoder.SetDecoderProperties(propArray); + + CBenchRandomGenerator rg = new CBenchRandomGenerator(); + + rg.Set(kBufferSize); + rg.Generate(); + CRC crc = new CRC(); + crc.Init(); + crc.Update(rg.Buffer, 0, rg.BufferSize); + + CProgressInfo progressInfo = new CProgressInfo(); + progressInfo.ApprovedStart = dictionarySize; + + long totalBenchSize = 0; + long totalEncodeTime = 0; + long totalDecodeTime = 0; + long totalCompressedSize = 0; + + MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); + + byte[] compressedBuffer = new byte[kCompressedBufferSize]; + MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); + CrcOutStream crcOutStream = new CrcOutStream(); + MyInputStream inputCompressedStream = null; + int compressedSize = 0; + for (int i = 0; i < numIterations; i++) + { + progressInfo.Init(); + inStream.reset(); + compressedStream.reset(); + encoder.Code(inStream, compressedStream, -1, -1, progressInfo); + long encodeTime = System.currentTimeMillis() - progressInfo.Time; + + if (i == 0) + { + compressedSize = compressedStream.size(); + inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); + } + else if (compressedSize != compressedStream.size()) + throw (new Exception("Encoding error")); + + if (progressInfo.InSize == 0) + throw (new Exception("Internal ERROR 1282")); + + long decodeTime = 0; + for (int j = 0; j < 2; j++) + { + inputCompressedStream.reset(); + crcOutStream.Init(); + + long outSize = kBufferSize; + long startTime = System.currentTimeMillis(); + if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) + throw (new Exception("Decoding Error"));; + decodeTime = System.currentTimeMillis() - startTime; + if (crcOutStream.GetDigest() != crc.GetDigest()) + throw (new Exception("CRC Error")); + } + long benchSize = kBufferSize - (long)progressInfo.InSize; + PrintResults(dictionarySize, encodeTime, benchSize, false, 0); + System.out.print(" "); + PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); + System.out.println(); + + totalBenchSize += benchSize; + totalEncodeTime += encodeTime; + totalDecodeTime += decodeTime; + totalCompressedSize += compressedSize; + } + System.out.println("---------------------------------------------------"); + PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); + System.out.print(" "); + PrintResults(dictionarySize, totalDecodeTime, + kBufferSize * (long)numIterations, true, totalCompressedSize); + System.out.println(" Average"); + return 0; + } +} diff --git a/other-licenses/7zstub/src/bin/7zS2.sfx b/other-licenses/7zstub/src/bin/7zS2.sfx new file mode 100644 index 0000000000..261214ffc1 Binary files /dev/null and b/other-licenses/7zstub/src/bin/7zS2.sfx differ diff --git a/other-licenses/7zstub/src/bin/7zS2con.sfx b/other-licenses/7zstub/src/bin/7zS2con.sfx new file mode 100644 index 0000000000..137b83cbe3 Binary files /dev/null and b/other-licenses/7zstub/src/bin/7zS2con.sfx differ diff --git a/other-licenses/7zstub/src/bin/7zSD.sfx b/other-licenses/7zstub/src/bin/7zSD.sfx new file mode 100644 index 0000000000..caff364a97 Binary files /dev/null and b/other-licenses/7zstub/src/bin/7zSD.sfx differ diff --git a/other-licenses/7zstub/src/bin/7zdec.exe b/other-licenses/7zstub/src/bin/7zdec.exe new file mode 100644 index 0000000000..4d3fe370fd Binary files /dev/null and b/other-licenses/7zstub/src/bin/7zdec.exe differ diff --git a/other-licenses/7zstub/src/bin/7zr.exe b/other-licenses/7zstub/src/bin/7zr.exe new file mode 100644 index 0000000000..04e96e7235 Binary files /dev/null and b/other-licenses/7zstub/src/bin/7zr.exe differ diff --git a/other-licenses/7zstub/src/bin/installer/config.txt b/other-licenses/7zstub/src/bin/installer/config.txt new file mode 100644 index 0000000000..f7f8fb42ec --- /dev/null +++ b/other-licenses/7zstub/src/bin/installer/config.txt @@ -0,0 +1,5 @@ +;!@Install@!UTF-8! +Title="Software 7.00" +BeginPrompt="Do you want to install the Software 7.00?" +RunProgram="7zr.exe b" +;!@InstallEnd@! diff --git a/other-licenses/7zstub/src/bin/installer/cr.bat b/other-licenses/7zstub/src/bin/installer/cr.bat new file mode 100644 index 0000000000..b51a52ae8a --- /dev/null +++ b/other-licenses/7zstub/src/bin/installer/cr.bat @@ -0,0 +1,5 @@ +del archive.7z +del archive.exe +..\7zr a archive.7z ..\7zr.exe -mx -mf=BCJ2 +copy /b ..\7zSD.sfx + config.txt + archive.7z archive.exe + diff --git a/other-licenses/7zstub/src/bin/lzma.exe b/other-licenses/7zstub/src/bin/lzma.exe new file mode 100644 index 0000000000..533e24c53a Binary files /dev/null and b/other-licenses/7zstub/src/bin/lzma.exe differ diff --git a/other-licenses/7zstub/src/bin/x64/7zr.exe b/other-licenses/7zstub/src/bin/x64/7zr.exe new file mode 100644 index 0000000000..b41277429f Binary files /dev/null and b/other-licenses/7zstub/src/bin/x64/7zr.exe differ -- cgit v1.2.3